Validate the info.xml against the appstore schema file
Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
parent
620ee00ac5
commit
17a26dfcc1
|
@ -44,20 +44,12 @@ use OC\App\CodeChecker\PrivateCheck;
|
||||||
|
|
||||||
class CheckCode extends Command implements CompletionAwareInterface {
|
class CheckCode extends Command implements CompletionAwareInterface {
|
||||||
|
|
||||||
/** @var InfoParser */
|
|
||||||
private $infoParser;
|
|
||||||
|
|
||||||
protected $checkers = [
|
protected $checkers = [
|
||||||
'private' => PrivateCheck::class,
|
'private' => PrivateCheck::class,
|
||||||
'deprecation' => DeprecationCheck::class,
|
'deprecation' => DeprecationCheck::class,
|
||||||
'strong-comparison' => StrongComparisonCheck::class,
|
'strong-comparison' => StrongComparisonCheck::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(InfoParser $infoParser) {
|
|
||||||
parent::__construct();
|
|
||||||
$this->infoParser = $infoParser;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function configure() {
|
protected function configure() {
|
||||||
$this
|
$this
|
||||||
->setName('app:check-code')
|
->setName('app:check-code')
|
||||||
|
@ -134,50 +126,12 @@ class CheckCode extends Command implements CompletionAwareInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$input->getOption('skip-validate-info')) {
|
if(!$input->getOption('skip-validate-info')) {
|
||||||
$infoChecker = new InfoChecker($this->infoParser);
|
// Can not inject because of circular dependency
|
||||||
|
$infoChecker = new InfoChecker(\OC::$server->getAppManager());
|
||||||
$infoChecker->listen('InfoChecker', 'mandatoryFieldMissing', function($key) use ($output) {
|
$infoChecker->listen('InfoChecker', 'parseError', function($error) use ($output) {
|
||||||
$output->writeln("<error>Mandatory field missing: $key</error>");
|
$output->writeln("<error>Invalid appinfo.xml file found: $error</error>");
|
||||||
});
|
});
|
||||||
|
|
||||||
$infoChecker->listen('InfoChecker', 'deprecatedFieldFound', function($key, $value) use ($output) {
|
|
||||||
if($value === [] || is_null($value) || $value === '') {
|
|
||||||
$output->writeln("<info>Deprecated field available: $key</info>");
|
|
||||||
} else {
|
|
||||||
$output->writeln("<info>Deprecated field available: $key => $value</info>");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$infoChecker->listen('InfoChecker', 'missingRequirement', function($minMax) use ($output) {
|
|
||||||
$output->writeln("<error>Nextcloud $minMax version requirement missing</error>");
|
|
||||||
});
|
|
||||||
|
|
||||||
$infoChecker->listen('InfoChecker', 'differentVersions', function($versionFile, $infoXML) use ($output) {
|
|
||||||
$output->writeln("<error>Different versions provided (appinfo/version: $versionFile - appinfo/info.xml: $infoXML)</error>");
|
|
||||||
});
|
|
||||||
|
|
||||||
$infoChecker->listen('InfoChecker', 'sameVersions', function($path) use ($output) {
|
|
||||||
$output->writeln("<info>Version file isn't needed anymore and can be safely removed ($path)</info>");
|
|
||||||
});
|
|
||||||
|
|
||||||
$infoChecker->listen('InfoChecker', 'migrateVersion', function($version) use ($output) {
|
|
||||||
$output->writeln("<error>Migrate the app version to appinfo/info.xml (add <version>$version</version> to appinfo/info.xml and remove appinfo/version)</error>");
|
|
||||||
});
|
|
||||||
|
|
||||||
if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
|
|
||||||
$infoChecker->listen('InfoChecker', 'mandatoryFieldFound', function($key, $value) use ($output) {
|
|
||||||
$output->writeln("<info>Mandatory field available: $key => $value</info>");
|
|
||||||
});
|
|
||||||
|
|
||||||
$infoChecker->listen('InfoChecker', 'optionalFieldFound', function($key, $value) use ($output) {
|
|
||||||
$output->writeln("<info>Optional field available: $key => $value</info>");
|
|
||||||
});
|
|
||||||
|
|
||||||
$infoChecker->listen('InfoChecker', 'unusedFieldFound', function($key, $value) use ($output) {
|
|
||||||
$output->writeln("<info>Unused field available: $key => $value</info>");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$infoErrors = $infoChecker->analyse($appId);
|
$infoErrors = $infoChecker->analyse($appId);
|
||||||
|
|
||||||
$errors = array_merge($errors, $infoErrors);
|
$errors = array_merge($errors, $infoErrors);
|
||||||
|
|
|
@ -40,8 +40,7 @@
|
||||||
$application->add(new \Stecman\Component\Symfony\Console\BashCompletion\CompletionCommand());
|
$application->add(new \Stecman\Component\Symfony\Console\BashCompletion\CompletionCommand());
|
||||||
$application->add(new OC\Core\Command\Status);
|
$application->add(new OC\Core\Command\Status);
|
||||||
$application->add(new OC\Core\Command\Check(\OC::$server->getSystemConfig()));
|
$application->add(new OC\Core\Command\Check(\OC::$server->getSystemConfig()));
|
||||||
$infoParser = new \OC\App\InfoParser();
|
$application->add(new OC\Core\Command\App\CheckCode());
|
||||||
$application->add(new OC\Core\Command\App\CheckCode($infoParser));
|
|
||||||
$application->add(new OC\Core\Command\L10n\CreateJs());
|
$application->add(new OC\Core\Command\L10n\CreateJs());
|
||||||
$application->add(new \OC\Core\Command\Integrity\SignApp(
|
$application->add(new \OC\Core\Command\Integrity\SignApp(
|
||||||
\OC::$server->getIntegrityCodeChecker(),
|
\OC::$server->getIntegrityCodeChecker(),
|
||||||
|
|
|
@ -411,6 +411,7 @@ class AppManager implements IAppManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
* In case you change this method, also change \OC\App\CodeChecker\InfoChecker::isShipped()
|
||||||
*/
|
*/
|
||||||
public function isShipped($appId) {
|
public function isShipped($appId) {
|
||||||
$this->loadShippedJson();
|
$this->loadShippedJson();
|
||||||
|
@ -422,6 +423,10 @@ class AppManager implements IAppManager {
|
||||||
return in_array($appId, $alwaysEnabled, true);
|
return in_array($appId, $alwaysEnabled, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In case you change this method, also change \OC\App\CodeChecker\InfoChecker::loadShippedJson()
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
private function loadShippedJson() {
|
private function loadShippedJson() {
|
||||||
if ($this->shippedApps === null) {
|
if ($this->shippedApps === null) {
|
||||||
$shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
|
$shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
|
||||||
|
|
|
@ -23,121 +23,88 @@
|
||||||
|
|
||||||
namespace OC\App\CodeChecker;
|
namespace OC\App\CodeChecker;
|
||||||
|
|
||||||
use OC\App\InfoParser;
|
|
||||||
use OC\Hooks\BasicEmitter;
|
use OC\Hooks\BasicEmitter;
|
||||||
|
use OCP\App\AppPathNotFoundException;
|
||||||
|
use OCP\App\IAppManager;
|
||||||
|
|
||||||
class InfoChecker extends BasicEmitter {
|
class InfoChecker extends BasicEmitter {
|
||||||
|
|
||||||
/** @var InfoParser */
|
/** @var string[] */
|
||||||
private $infoParser;
|
private $shippedApps;
|
||||||
|
|
||||||
private $mandatoryFields = [
|
/** @var string[] */
|
||||||
'author',
|
private $alwaysEnabled;
|
||||||
'description',
|
|
||||||
'dependencies',
|
|
||||||
'id',
|
|
||||||
'licence',
|
|
||||||
'name',
|
|
||||||
'version',
|
|
||||||
];
|
|
||||||
private $optionalFields = [
|
|
||||||
'bugs',
|
|
||||||
'category',
|
|
||||||
'default_enable',
|
|
||||||
'documentation',
|
|
||||||
'namespace',
|
|
||||||
'ocsid',
|
|
||||||
'public',
|
|
||||||
'remote',
|
|
||||||
'repository',
|
|
||||||
'types',
|
|
||||||
'website',
|
|
||||||
];
|
|
||||||
private $deprecatedFields = [
|
|
||||||
'info',
|
|
||||||
'require',
|
|
||||||
'requiremax',
|
|
||||||
'requiremin',
|
|
||||||
'shipped',
|
|
||||||
'standalone',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __construct(InfoParser $infoParser) {
|
|
||||||
$this->infoParser = $infoParser;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $appId
|
* @param string $appId
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws \RuntimeException
|
||||||
*/
|
*/
|
||||||
public function analyse($appId) {
|
public function analyse($appId): array {
|
||||||
$appPath = \OC_App::getAppPath($appId);
|
$appPath = \OC_App::getAppPath($appId);
|
||||||
if ($appPath === false) {
|
if ($appPath === false) {
|
||||||
throw new \RuntimeException("No app with given id <$appId> known.");
|
throw new \RuntimeException("No app with given id <$appId> known.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$xml = new \DOMDocument();
|
||||||
|
$xml->load($appPath . '/appinfo/info.xml');
|
||||||
|
|
||||||
|
$schema = \OC::$SERVERROOT . '/resources/app-info.xsd';
|
||||||
|
try {
|
||||||
|
if ($this->isShipped($appId)) {
|
||||||
|
// Shipped apps are allowed to have the public and default_enabled tags
|
||||||
|
$schema = \OC::$SERVERROOT . '/resources/app-info-shipped.xsd';
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Assume it is not shipped
|
||||||
|
}
|
||||||
|
|
||||||
$errors = [];
|
$errors = [];
|
||||||
|
if (!$xml->schemaValidate($schema)) {
|
||||||
$info = $this->infoParser->parse($appPath . '/appinfo/info.xml');
|
foreach (libxml_get_errors() as $error) {
|
||||||
|
|
||||||
if (!isset($info['dependencies']['nextcloud']['@attributes']['min-version'])) {
|
|
||||||
$errors[] = [
|
|
||||||
'type' => 'missingRequirement',
|
|
||||||
'field' => 'min',
|
|
||||||
];
|
|
||||||
$this->emit('InfoChecker', 'missingRequirement', ['min']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($info['dependencies']['nextcloud']['@attributes']['max-version'])) {
|
|
||||||
$errors[] = [
|
|
||||||
'type' => 'missingRequirement',
|
|
||||||
'field' => 'max',
|
|
||||||
];
|
|
||||||
$this->emit('InfoChecker', 'missingRequirement', ['max']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($info as $key => $value) {
|
|
||||||
if(is_array($value)) {
|
|
||||||
$value = json_encode($value);
|
|
||||||
}
|
|
||||||
if (in_array($key, $this->mandatoryFields)) {
|
|
||||||
$this->emit('InfoChecker', 'mandatoryFieldFound', [$key, $value]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($key, $this->optionalFields)) {
|
|
||||||
$this->emit('InfoChecker', 'optionalFieldFound', [$key, $value]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($key, $this->deprecatedFields)) {
|
|
||||||
// skip empty arrays - empty arrays for remote and public are always added
|
|
||||||
if($value === '[]' && in_array($key, ['public', 'remote', 'info'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$this->emit('InfoChecker', 'deprecatedFieldFound', [$key, $value]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->emit('InfoChecker', 'unusedFieldFound', [$key, $value]);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->mandatoryFields as $key) {
|
|
||||||
if(!isset($info[$key])) {
|
|
||||||
$this->emit('InfoChecker', 'mandatoryFieldMissing', [$key]);
|
|
||||||
$errors[] = [
|
$errors[] = [
|
||||||
'type' => 'mandatoryFieldMissing',
|
'type' => 'parseError',
|
||||||
'field' => $key,
|
'field' => $error->message,
|
||||||
];
|
];
|
||||||
|
$this->emit('InfoChecker', 'parseError', [$error->message]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$versionFile = $appPath . '/appinfo/version';
|
|
||||||
if (is_file($versionFile)) {
|
|
||||||
$version = trim(file_get_contents($versionFile));
|
|
||||||
$this->emit('InfoChecker', 'migrateVersion', [$version]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $errors;
|
return $errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a copy of \OC\App\AppManager::isShipped(), keep both in sync.
|
||||||
|
* This method is copied, so the code checker works even when Nextcloud is
|
||||||
|
* not installed yet. The AppManager requires a database connection, which
|
||||||
|
* fails in that case.
|
||||||
|
*
|
||||||
|
* @param string $appId
|
||||||
|
* @return bool
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function isShipped(string $appId): bool {
|
||||||
|
$this->loadShippedJson();
|
||||||
|
return \in_array($appId, $this->shippedApps, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a copy of \OC\App\AppManager::loadShippedJson(), keep both in sync
|
||||||
|
* This method is copied, so the code checker works even when Nextcloud is
|
||||||
|
* not installed yet. The AppManager requires a database connection, which
|
||||||
|
* fails in that case.
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function loadShippedJson() {
|
||||||
|
if ($this->shippedApps === null) {
|
||||||
|
$shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
|
||||||
|
if (!file_exists($shippedJson)) {
|
||||||
|
throw new \Exception("File not found: $shippedJson");
|
||||||
|
}
|
||||||
|
$content = json_decode(file_get_contents($shippedJson), true);
|
||||||
|
$this->shippedApps = $content['shippedApps'];
|
||||||
|
$this->alwaysEnabled = $content['alwaysEnabled'];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,671 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||||
|
|
||||||
|
<xs:element name="info">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="id" type="id" minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="name" type="l10n-string" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="summary" type="l10n-string" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="description" type="l10n-text" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="version" type="semver"
|
||||||
|
minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="licence" type="licence" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="author" type="author" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="namespace" type="limited-string"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="default_enable" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="types" type="types" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="documentation" type="documentation"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="category" type="category" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="website" type="url" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="discussion" type="url" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="bugs" type="url" minOccurs="1"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="repository" type="repository" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="screenshot" type="screenshot" minOccurs="0"
|
||||||
|
maxOccurs="10"/>
|
||||||
|
<xs:element name="dependencies" type="dependencies"
|
||||||
|
minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="background-jobs" type="jobs"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="repair-steps" type="repair-steps"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="two-factor-providers"
|
||||||
|
type="two-factor-providers"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="commands" type="commands"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="settings" type="settings" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="activity" type="activity" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="navigations" type="navigations" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="contactsmenu" type="contactsmenu" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="collaboration" type="collaboration" minOccurs="0"
|
||||||
|
maxOccurs="1" />
|
||||||
|
<xs:element name="sabre" type="sabre" minOccurs="0"
|
||||||
|
maxOccurs="1" />
|
||||||
|
<xs:element name="public" type="public" minOccurs="0"
|
||||||
|
maxOccurs="1" />
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:unique name="uniqueNameL10n">
|
||||||
|
<xs:selector xpath="name"/>
|
||||||
|
<xs:field xpath="@lang"/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueSummaryL10n">
|
||||||
|
<xs:selector xpath="summary"/>
|
||||||
|
<xs:field xpath="@lang"/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueDescriptionL10n">
|
||||||
|
<xs:selector xpath="description"/>
|
||||||
|
<xs:field xpath="@lang"/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueLicense">
|
||||||
|
<xs:selector xpath="licence"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueTypes">
|
||||||
|
<xs:selector xpath="types/type"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueCategory">
|
||||||
|
<xs:selector xpath="category"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueDatabase">
|
||||||
|
<xs:selector xpath="dependencies/database"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueLib">
|
||||||
|
<xs:selector xpath="dependencies/lib"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueCommand">
|
||||||
|
<xs:selector xpath="dependencies/command"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<!-- basic types -->
|
||||||
|
<xs:simpleType name="empty-string">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:maxLength value="0"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<xs:simpleType name="non-empty-string">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:minLength value="1"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<xs:simpleType name="limited-string">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="l10n-text">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="non-empty-string">
|
||||||
|
<xs:attribute name="lang" type="l10n-code" default="en"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="l10n-string">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:restriction base="l10n-text">
|
||||||
|
<xs:maxLength value="128"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
|
||||||
|
<xs:simpleType name="l10n-code">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="af"/>
|
||||||
|
<xs:enumeration value="ar"/>
|
||||||
|
<xs:enumeration value="ast"/>
|
||||||
|
<xs:enumeration value="az"/>
|
||||||
|
<xs:enumeration value="bg"/>
|
||||||
|
<xs:enumeration value="be"/>
|
||||||
|
<xs:enumeration value="bn"/>
|
||||||
|
<xs:enumeration value="br"/>
|
||||||
|
<xs:enumeration value="bs"/>
|
||||||
|
<xs:enumeration value="ca"/>
|
||||||
|
<xs:enumeration value="cs"/>
|
||||||
|
<xs:enumeration value="cy"/>
|
||||||
|
<xs:enumeration value="da"/>
|
||||||
|
<xs:enumeration value="de"/>
|
||||||
|
<xs:enumeration value="el"/>
|
||||||
|
<xs:enumeration value="en"/>
|
||||||
|
<xs:enumeration value="eo"/>
|
||||||
|
<xs:enumeration value="es"/>
|
||||||
|
<xs:enumeration value="es-ar"/>
|
||||||
|
<xs:enumeration value="es-co"/>
|
||||||
|
<xs:enumeration value="es-mx"/>
|
||||||
|
<xs:enumeration value="es-ni"/>
|
||||||
|
<xs:enumeration value="es-ve"/>
|
||||||
|
<xs:enumeration value="et"/>
|
||||||
|
<xs:enumeration value="eu"/>
|
||||||
|
<xs:enumeration value="fa"/>
|
||||||
|
<xs:enumeration value="fi"/>
|
||||||
|
<xs:enumeration value="fr"/>
|
||||||
|
<xs:enumeration value="fy"/>
|
||||||
|
<xs:enumeration value="ga"/>
|
||||||
|
<xs:enumeration value="gd"/>
|
||||||
|
<xs:enumeration value="gl"/>
|
||||||
|
<xs:enumeration value="he"/>
|
||||||
|
<xs:enumeration value="hi"/>
|
||||||
|
<xs:enumeration value="hr"/>
|
||||||
|
<xs:enumeration value="hu"/>
|
||||||
|
<xs:enumeration value="ia"/>
|
||||||
|
<xs:enumeration value="id"/>
|
||||||
|
<xs:enumeration value="io"/>
|
||||||
|
<xs:enumeration value="is"/>
|
||||||
|
<xs:enumeration value="it"/>
|
||||||
|
<xs:enumeration value="ja"/>
|
||||||
|
<xs:enumeration value="ka"/>
|
||||||
|
<xs:enumeration value="kk"/>
|
||||||
|
<xs:enumeration value="km"/>
|
||||||
|
<xs:enumeration value="kn"/>
|
||||||
|
<xs:enumeration value="ko"/>
|
||||||
|
<xs:enumeration value="lb"/>
|
||||||
|
<xs:enumeration value="lt"/>
|
||||||
|
<xs:enumeration value="lv"/>
|
||||||
|
<xs:enumeration value="mk"/>
|
||||||
|
<xs:enumeration value="ml"/>
|
||||||
|
<xs:enumeration value="mn"/>
|
||||||
|
<xs:enumeration value="mr"/>
|
||||||
|
<xs:enumeration value="my"/>
|
||||||
|
<xs:enumeration value="nb"/>
|
||||||
|
<xs:enumeration value="ne"/>
|
||||||
|
<xs:enumeration value="nl"/>
|
||||||
|
<xs:enumeration value="nn"/>
|
||||||
|
<xs:enumeration value="os"/>
|
||||||
|
<xs:enumeration value="pa"/>
|
||||||
|
<xs:enumeration value="pl"/>
|
||||||
|
<xs:enumeration value="pt"/>
|
||||||
|
<xs:enumeration value="pt-br"/>
|
||||||
|
<xs:enumeration value="ro"/>
|
||||||
|
<xs:enumeration value="ru"/>
|
||||||
|
<xs:enumeration value="sk"/>
|
||||||
|
<xs:enumeration value="sl"/>
|
||||||
|
<xs:enumeration value="sq"/>
|
||||||
|
<xs:enumeration value="sr"/>
|
||||||
|
<xs:enumeration value="sr-latn"/>
|
||||||
|
<xs:enumeration value="sv"/>
|
||||||
|
<xs:enumeration value="sw"/>
|
||||||
|
<xs:enumeration value="ta"/>
|
||||||
|
<xs:enumeration value="te"/>
|
||||||
|
<xs:enumeration value="th"/>
|
||||||
|
<xs:enumeration value="tr"/>
|
||||||
|
<xs:enumeration value="tt"/>
|
||||||
|
<xs:enumeration value="udm"/>
|
||||||
|
<xs:enumeration value="uk"/>
|
||||||
|
<xs:enumeration value="ur"/>
|
||||||
|
<xs:enumeration value="vi"/>
|
||||||
|
<xs:enumeration value="zh-hans"/>
|
||||||
|
<xs:enumeration value="zh-hant"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="semver">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern
|
||||||
|
value="(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="version">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[0-9]+(\.[0-9]+){0,2}"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="url">
|
||||||
|
<xs:restriction base="xs:anyURI">
|
||||||
|
<xs:pattern value="https?://.+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="doc-user-url">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="https://.+|user-[a-z]+[\-a-z]*[a-z]+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="doc-admin-url">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="https://.+|admin-[a-z]+[\-a-z]*[a-z]+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="doc-developer-url">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="https://.+|developer-[a-z]+[\-a-z]*[a-z]+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="secure-url">
|
||||||
|
<xs:restriction base="xs:anyURI">
|
||||||
|
<xs:pattern value="https://.+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="email">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[^@]+@[^\.]+\..+"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<!-- first level elements -->
|
||||||
|
<xs:complexType name="screenshot">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="secure-url">
|
||||||
|
<xs:attribute name="small-thumbnail" use="optional"
|
||||||
|
type="secure-url"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="id">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[a-z]+[a-z0-9_]*[a-z0-9]+"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="author">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="limited-string">
|
||||||
|
<xs:attribute name="mail" type="email" use="optional"/>
|
||||||
|
<xs:attribute name="homepage" type="url" use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="repository">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="url">
|
||||||
|
<xs:attribute name="type" type="vcs" use="optional"
|
||||||
|
default="git"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="vcs">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="git"/>
|
||||||
|
<xs:enumeration value="mercurial"/>
|
||||||
|
<xs:enumeration value="subversion"/>
|
||||||
|
<xs:enumeration value="bzr"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="types">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="prelogin" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="filesystem" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="authentication" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="logging" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="dav" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="prevent_group_restriction" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="category">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="security"/>
|
||||||
|
<xs:enumeration value="customization"/>
|
||||||
|
<xs:enumeration value="files"/>
|
||||||
|
<xs:enumeration value="integration"/>
|
||||||
|
<xs:enumeration value="monitoring"/>
|
||||||
|
<xs:enumeration value="multimedia"/>
|
||||||
|
<xs:enumeration value="office"/>
|
||||||
|
<xs:enumeration value="organization"/>
|
||||||
|
<xs:enumeration value="social"/>
|
||||||
|
<xs:enumeration value="tools"/>
|
||||||
|
<xs:enumeration value="games"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="licence">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="agpl"/>
|
||||||
|
<xs:enumeration value="mpl"/>
|
||||||
|
<xs:enumeration value="apache"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="databases">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="sqlite"/>
|
||||||
|
<xs:enumeration value="mysql"/>
|
||||||
|
<xs:enumeration value="pgsql"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="documentation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="user" type="doc-user-url" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="admin" type="doc-admin-url" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="developer" type="doc-developer-url" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="settings">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="admin" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="admin-section" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="personal" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="personal-section" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="settings" type="activity-settings" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="filters" type="activity-filters" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="providers" type="activity-providers" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity-settings">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="setting" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity-filters">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="filter" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity-providers">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="provider" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="navigations">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="navigation" type="navigation" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="navigation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="id" type="id" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="name" type="non-empty-string" minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="route" type="route" minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="icon" type="xs:anyURI" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="order" type="xs:int" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="type" type="navigation-type" minOccurs="0" maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="role" type="navigation-role" default="all" use="optional"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="navigation-role">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="all"/>
|
||||||
|
<xs:enumeration value="admin"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="navigation-type">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="link"/>
|
||||||
|
<xs:enumeration value="settings"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="route">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="[0-9a-zA-Z_]+(\.[0-9a-zA-Z_]+){2}"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="contactsmenu">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="provider" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="collaboration">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="plugins" type="collaboration-plugins" minOccurs="0" maxOccurs="1">
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="collaboration-plugins">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="plugin" type="collaboration-plugins-plugin" minOccurs="1" maxOccurs="unbounded">
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="collaboration-plugins-plugin">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="php-class">
|
||||||
|
<xs:attribute name="type" type="collaboration-plugin-type" use="required"/>
|
||||||
|
<xs:attribute name="share-type" type="share-type" />
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="collaboration-plugin-type">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="collaborator-search"/>
|
||||||
|
<xs:enumeration value="autocomplete-sort"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="sabre">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="collections" type="sabre-collections" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="plugins" type="sabre-plugins" minOccurs="0" maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="sabre-collections">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="collection" type="php-class" minOccurs="1" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="sabre-plugins">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="plugin" type="php-class" minOccurs="1" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="share-type">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="SHARE_TYPE_USER"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_GROUP"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_LINK"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_EMAIL"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_CONTACT"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_REMOTE"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_CIRCLE"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_GUEST"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
|
||||||
|
<xs:complexType name="public">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="webdav" type="path" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="files" type="path" minOccurs="0" maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<!-- dependencies -->
|
||||||
|
<xs:complexType name="dependencies">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="php" type="php" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="database" type="database" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="command" type="shell-command" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="lib" type="min-max-version" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="owncloud" type="owncloud" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="nextcloud" type="nextcloud" minOccurs="1"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="owncloud">
|
||||||
|
<xs:attribute name="min-version" type="version" use="required"/>
|
||||||
|
<xs:attribute name="max-version" type="version" use="optional"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="nextcloud">
|
||||||
|
<xs:attribute name="min-version" type="version" use="required"/>
|
||||||
|
<xs:attribute name="max-version" type="version" use="required"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="shell-command">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[a-zA-Z\-_]+"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="min-max-version">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="limited-string">
|
||||||
|
<xs:attribute name="min-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
<xs:attribute name="max-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="database">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="databases">
|
||||||
|
<xs:attribute name="min-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
<xs:attribute name="max-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="php">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="empty-string">
|
||||||
|
<xs:attribute name="min-int-size" type="bits" use="optional"
|
||||||
|
default="32"/>
|
||||||
|
<xs:attribute name="min-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
<xs:attribute name="max-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="bits">
|
||||||
|
<xs:restriction base="xs:int">
|
||||||
|
<xs:enumeration value="32"/>
|
||||||
|
<xs:enumeration value="64"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="repair-steps">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="pre-migration" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="post-migration" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="live-migration" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="install" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="uninstall" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="jobs">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="job" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="steps">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="step" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="two-factor-providers">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="provider" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="commands">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="command" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="php-class">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:pattern
|
||||||
|
value="[a-zA-Z_][0-9a-zA-Z_]*(\\[a-zA-Z_][0-9a-zA-Z_]*)*"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="path">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:pattern
|
||||||
|
value="[a-zA-Z_][0-9a-zA-Z_]*(/[a-zA-Z_][0-9a-zA-Z_]*)*\.php"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
</xs:schema>
|
|
@ -0,0 +1,652 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||||
|
|
||||||
|
<xs:element name="info">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="id" type="id" minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="name" type="l10n-string" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="summary" type="l10n-string" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="description" type="l10n-text" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="version" type="semver"
|
||||||
|
minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="licence" type="licence" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="author" type="author" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="namespace" type="limited-string"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="types" type="types" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="documentation" type="documentation"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="category" type="category" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="website" type="url" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="discussion" type="url" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="bugs" type="url" minOccurs="1"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="repository" type="repository" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="screenshot" type="screenshot" minOccurs="0"
|
||||||
|
maxOccurs="10"/>
|
||||||
|
<xs:element name="dependencies" type="dependencies"
|
||||||
|
minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="background-jobs" type="jobs"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="repair-steps" type="repair-steps"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="two-factor-providers"
|
||||||
|
type="two-factor-providers"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="commands" type="commands"
|
||||||
|
minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="settings" type="settings" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="activity" type="activity" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="navigations" type="navigations" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="contactsmenu" type="contactsmenu" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="collaboration" type="collaboration" minOccurs="0"
|
||||||
|
maxOccurs="1" />
|
||||||
|
<xs:element name="sabre" type="sabre" minOccurs="0"
|
||||||
|
maxOccurs="1" />
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:unique name="uniqueNameL10n">
|
||||||
|
<xs:selector xpath="name"/>
|
||||||
|
<xs:field xpath="@lang"/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueSummaryL10n">
|
||||||
|
<xs:selector xpath="summary"/>
|
||||||
|
<xs:field xpath="@lang"/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueDescriptionL10n">
|
||||||
|
<xs:selector xpath="description"/>
|
||||||
|
<xs:field xpath="@lang"/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueLicense">
|
||||||
|
<xs:selector xpath="licence"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueTypes">
|
||||||
|
<xs:selector xpath="types/type"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueCategory">
|
||||||
|
<xs:selector xpath="category"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueDatabase">
|
||||||
|
<xs:selector xpath="dependencies/database"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueLib">
|
||||||
|
<xs:selector xpath="dependencies/lib"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
<xs:unique name="uniqueCommand">
|
||||||
|
<xs:selector xpath="dependencies/command"/>
|
||||||
|
<xs:field xpath="."/>
|
||||||
|
</xs:unique>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<!-- basic types -->
|
||||||
|
<xs:simpleType name="empty-string">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:maxLength value="0"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<xs:simpleType name="non-empty-string">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:minLength value="1"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<xs:simpleType name="limited-string">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="l10n-text">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="non-empty-string">
|
||||||
|
<xs:attribute name="lang" type="l10n-code" default="en"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="l10n-string">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:restriction base="l10n-text">
|
||||||
|
<xs:maxLength value="128"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
|
||||||
|
<xs:simpleType name="l10n-code">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="af"/>
|
||||||
|
<xs:enumeration value="ar"/>
|
||||||
|
<xs:enumeration value="ast"/>
|
||||||
|
<xs:enumeration value="az"/>
|
||||||
|
<xs:enumeration value="bg"/>
|
||||||
|
<xs:enumeration value="be"/>
|
||||||
|
<xs:enumeration value="bn"/>
|
||||||
|
<xs:enumeration value="br"/>
|
||||||
|
<xs:enumeration value="bs"/>
|
||||||
|
<xs:enumeration value="ca"/>
|
||||||
|
<xs:enumeration value="cs"/>
|
||||||
|
<xs:enumeration value="cy"/>
|
||||||
|
<xs:enumeration value="da"/>
|
||||||
|
<xs:enumeration value="de"/>
|
||||||
|
<xs:enumeration value="el"/>
|
||||||
|
<xs:enumeration value="en"/>
|
||||||
|
<xs:enumeration value="eo"/>
|
||||||
|
<xs:enumeration value="es"/>
|
||||||
|
<xs:enumeration value="es-ar"/>
|
||||||
|
<xs:enumeration value="es-co"/>
|
||||||
|
<xs:enumeration value="es-mx"/>
|
||||||
|
<xs:enumeration value="es-ni"/>
|
||||||
|
<xs:enumeration value="es-ve"/>
|
||||||
|
<xs:enumeration value="et"/>
|
||||||
|
<xs:enumeration value="eu"/>
|
||||||
|
<xs:enumeration value="fa"/>
|
||||||
|
<xs:enumeration value="fi"/>
|
||||||
|
<xs:enumeration value="fr"/>
|
||||||
|
<xs:enumeration value="fy"/>
|
||||||
|
<xs:enumeration value="ga"/>
|
||||||
|
<xs:enumeration value="gd"/>
|
||||||
|
<xs:enumeration value="gl"/>
|
||||||
|
<xs:enumeration value="he"/>
|
||||||
|
<xs:enumeration value="hi"/>
|
||||||
|
<xs:enumeration value="hr"/>
|
||||||
|
<xs:enumeration value="hu"/>
|
||||||
|
<xs:enumeration value="ia"/>
|
||||||
|
<xs:enumeration value="id"/>
|
||||||
|
<xs:enumeration value="io"/>
|
||||||
|
<xs:enumeration value="is"/>
|
||||||
|
<xs:enumeration value="it"/>
|
||||||
|
<xs:enumeration value="ja"/>
|
||||||
|
<xs:enumeration value="ka"/>
|
||||||
|
<xs:enumeration value="kk"/>
|
||||||
|
<xs:enumeration value="km"/>
|
||||||
|
<xs:enumeration value="kn"/>
|
||||||
|
<xs:enumeration value="ko"/>
|
||||||
|
<xs:enumeration value="lb"/>
|
||||||
|
<xs:enumeration value="lt"/>
|
||||||
|
<xs:enumeration value="lv"/>
|
||||||
|
<xs:enumeration value="mk"/>
|
||||||
|
<xs:enumeration value="ml"/>
|
||||||
|
<xs:enumeration value="mn"/>
|
||||||
|
<xs:enumeration value="mr"/>
|
||||||
|
<xs:enumeration value="my"/>
|
||||||
|
<xs:enumeration value="nb"/>
|
||||||
|
<xs:enumeration value="ne"/>
|
||||||
|
<xs:enumeration value="nl"/>
|
||||||
|
<xs:enumeration value="nn"/>
|
||||||
|
<xs:enumeration value="os"/>
|
||||||
|
<xs:enumeration value="pa"/>
|
||||||
|
<xs:enumeration value="pl"/>
|
||||||
|
<xs:enumeration value="pt"/>
|
||||||
|
<xs:enumeration value="pt-br"/>
|
||||||
|
<xs:enumeration value="ro"/>
|
||||||
|
<xs:enumeration value="ru"/>
|
||||||
|
<xs:enumeration value="sk"/>
|
||||||
|
<xs:enumeration value="sl"/>
|
||||||
|
<xs:enumeration value="sq"/>
|
||||||
|
<xs:enumeration value="sr"/>
|
||||||
|
<xs:enumeration value="sr-latn"/>
|
||||||
|
<xs:enumeration value="sv"/>
|
||||||
|
<xs:enumeration value="sw"/>
|
||||||
|
<xs:enumeration value="ta"/>
|
||||||
|
<xs:enumeration value="te"/>
|
||||||
|
<xs:enumeration value="th"/>
|
||||||
|
<xs:enumeration value="tr"/>
|
||||||
|
<xs:enumeration value="tt"/>
|
||||||
|
<xs:enumeration value="udm"/>
|
||||||
|
<xs:enumeration value="uk"/>
|
||||||
|
<xs:enumeration value="ur"/>
|
||||||
|
<xs:enumeration value="vi"/>
|
||||||
|
<xs:enumeration value="zh-hans"/>
|
||||||
|
<xs:enumeration value="zh-hant"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="semver">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern
|
||||||
|
value="(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="version">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[0-9]+(\.[0-9]+){0,2}"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="url">
|
||||||
|
<xs:restriction base="xs:anyURI">
|
||||||
|
<xs:pattern value="https?://.+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="doc-user-url">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="https://.+|user-[a-z]+[\-a-z]*[a-z]+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="doc-admin-url">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="https://.+|admin-[a-z]+[\-a-z]*[a-z]+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="doc-developer-url">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="https://.+|developer-[a-z]+[\-a-z]*[a-z]+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="secure-url">
|
||||||
|
<xs:restriction base="xs:anyURI">
|
||||||
|
<xs:pattern value="https://.+"/>
|
||||||
|
<xs:maxLength value="256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="email">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[^@]+@[^\.]+\..+"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<!-- first level elements -->
|
||||||
|
<xs:complexType name="screenshot">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="secure-url">
|
||||||
|
<xs:attribute name="small-thumbnail" use="optional"
|
||||||
|
type="secure-url"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="id">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[a-z]+[a-z0-9_]*[a-z0-9]+"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="author">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="limited-string">
|
||||||
|
<xs:attribute name="mail" type="email" use="optional"/>
|
||||||
|
<xs:attribute name="homepage" type="url" use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="repository">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="url">
|
||||||
|
<xs:attribute name="type" type="vcs" use="optional"
|
||||||
|
default="git"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="vcs">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="git"/>
|
||||||
|
<xs:enumeration value="mercurial"/>
|
||||||
|
<xs:enumeration value="subversion"/>
|
||||||
|
<xs:enumeration value="bzr"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="types">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="prelogin" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="filesystem" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="authentication" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="logging" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="dav" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="prevent_group_restriction" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="category">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="security"/>
|
||||||
|
<xs:enumeration value="customization"/>
|
||||||
|
<xs:enumeration value="files"/>
|
||||||
|
<xs:enumeration value="integration"/>
|
||||||
|
<xs:enumeration value="monitoring"/>
|
||||||
|
<xs:enumeration value="multimedia"/>
|
||||||
|
<xs:enumeration value="office"/>
|
||||||
|
<xs:enumeration value="organization"/>
|
||||||
|
<xs:enumeration value="social"/>
|
||||||
|
<xs:enumeration value="tools"/>
|
||||||
|
<xs:enumeration value="games"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="licence">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="agpl"/>
|
||||||
|
<xs:enumeration value="mpl"/>
|
||||||
|
<xs:enumeration value="apache"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="databases">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="sqlite"/>
|
||||||
|
<xs:enumeration value="mysql"/>
|
||||||
|
<xs:enumeration value="pgsql"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="documentation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="user" type="doc-user-url" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="admin" type="doc-admin-url" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="developer" type="doc-developer-url" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="settings">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="admin" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="admin-section" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="personal" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="personal-section" type="php-class" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="settings" type="activity-settings" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="filters" type="activity-filters" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="providers" type="activity-providers" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity-settings">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="setting" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity-filters">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="filter" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="activity-providers">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="provider" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="navigations">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="navigation" type="navigation" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="navigation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="id" type="id" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="name" type="non-empty-string" minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="route" type="route" minOccurs="1" maxOccurs="1"/>
|
||||||
|
<xs:element name="icon" type="xs:anyURI" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="order" type="xs:int" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="type" type="navigation-type" minOccurs="0" maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="role" type="navigation-role" default="all" use="optional"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="navigation-role">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="all"/>
|
||||||
|
<xs:enumeration value="admin"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="navigation-type">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="link"/>
|
||||||
|
<xs:enumeration value="settings"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="route">
|
||||||
|
<xs:restriction base="non-empty-string">
|
||||||
|
<xs:pattern value="[0-9a-zA-Z_]+(\.[0-9a-zA-Z_]+){2}"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="contactsmenu">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="provider" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="collaboration">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="plugins" type="collaboration-plugins" minOccurs="0" maxOccurs="1">
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="collaboration-plugins">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="plugin" type="collaboration-plugins-plugin" minOccurs="1" maxOccurs="unbounded">
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="collaboration-plugins-plugin">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="php-class">
|
||||||
|
<xs:attribute name="type" type="collaboration-plugin-type" use="required"/>
|
||||||
|
<xs:attribute name="share-type" type="share-type" />
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="collaboration-plugin-type">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="collaborator-search"/>
|
||||||
|
<xs:enumeration value="autocomplete-sort"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="sabre">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="collections" type="sabre-collections" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="plugins" type="sabre-plugins" minOccurs="0" maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="sabre-collections">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="collection" type="php-class" minOccurs="1" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="sabre-plugins">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="plugin" type="php-class" minOccurs="1" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="share-type">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="SHARE_TYPE_USER"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_GROUP"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_LINK"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_EMAIL"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_CONTACT"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_REMOTE"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_CIRCLE"/>
|
||||||
|
<xs:enumeration value="SHARE_TYPE_GUEST"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<!-- dependencies -->
|
||||||
|
<xs:complexType name="dependencies">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="php" type="php" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="database" type="database" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="command" type="shell-command" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="lib" type="min-max-version" minOccurs="0"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
<xs:element name="owncloud" type="owncloud" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="nextcloud" type="nextcloud" minOccurs="1"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="owncloud">
|
||||||
|
<xs:attribute name="min-version" type="version" use="required"/>
|
||||||
|
<xs:attribute name="max-version" type="version" use="optional"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="nextcloud">
|
||||||
|
<xs:attribute name="min-version" type="version" use="required"/>
|
||||||
|
<xs:attribute name="max-version" type="version" use="required"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="shell-command">
|
||||||
|
<xs:restriction base="limited-string">
|
||||||
|
<xs:pattern value="[a-zA-Z\-_]+"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="min-max-version">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="limited-string">
|
||||||
|
<xs:attribute name="min-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
<xs:attribute name="max-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="database">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="databases">
|
||||||
|
<xs:attribute name="min-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
<xs:attribute name="max-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="php">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="empty-string">
|
||||||
|
<xs:attribute name="min-int-size" type="bits" use="optional"
|
||||||
|
default="32"/>
|
||||||
|
<xs:attribute name="min-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
<xs:attribute name="max-version" type="version"
|
||||||
|
use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="bits">
|
||||||
|
<xs:restriction base="xs:int">
|
||||||
|
<xs:enumeration value="32"/>
|
||||||
|
<xs:enumeration value="64"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="repair-steps">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="pre-migration" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="post-migration" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="live-migration" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="install" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
<xs:element name="uninstall" type="steps" minOccurs="0"
|
||||||
|
maxOccurs="1"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="jobs">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="job" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="steps">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="step" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="two-factor-providers">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="provider" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="commands">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="command" type="php-class" minOccurs="1"
|
||||||
|
maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="php-class">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:pattern
|
||||||
|
value="[a-zA-Z_][0-9a-zA-Z_]*(\\[a-zA-Z_][0-9a-zA-Z_]*)*"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
</xs:schema>
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<info>
|
|
||||||
<id>testapp-infoxml-version</id>
|
|
||||||
<version>1.2.3</version>
|
|
||||||
<author>Jane</author>
|
|
||||||
<description>A b c</description>
|
|
||||||
<licence>Abc</licence>
|
|
||||||
<name>Test app</name>
|
|
||||||
</info>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<info>
|
|
||||||
<id>testapp-infoxml</id>
|
|
||||||
<version>1.2.3</version>
|
|
||||||
<author>Jane</author>
|
|
||||||
<description>A b c</description>
|
|
||||||
<licence>Abc</licence>
|
|
||||||
<name>Test app</name>
|
|
||||||
<dependencies>
|
|
||||||
<nextcloud min-version="12.0" max-version="12.0"/>
|
|
||||||
</dependencies>
|
|
||||||
</info>
|
|
|
@ -1,11 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<info>
|
|
||||||
<id>testapp-version</id>
|
|
||||||
<version>1.1.1</version>
|
|
||||||
<author>Jane</author>
|
|
||||||
<description>A b c</description>
|
|
||||||
<licence>Abc</licence>
|
|
||||||
<dependencies>
|
|
||||||
<nextcloud min-version="12.0" max-version="12.0"/>
|
|
||||||
</dependencies>
|
|
||||||
</info>
|
|
|
@ -1,11 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<info>
|
|
||||||
<id>testapp-version</id>
|
|
||||||
<author>Jane</author>
|
|
||||||
<description>A b c</description>
|
|
||||||
<licence>Abc</licence>
|
|
||||||
<name>Test app</name>
|
|
||||||
<dependencies>
|
|
||||||
<nextcloud min-version="12.0" max-version="12.0"/>
|
|
||||||
</dependencies>
|
|
||||||
</info>
|
|
|
@ -1 +0,0 @@
|
||||||
1.2.3
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
|
||||||
|
<id>testapp_infoxml</id>
|
||||||
|
<name>Test app</name>
|
||||||
|
<summary>A b c</summary>
|
||||||
|
<description>A b c</description>
|
||||||
|
<version>1.2.3</version>
|
||||||
|
<licence>agpl</licence>
|
||||||
|
<author>Jane</author>
|
||||||
|
<category>games</category>
|
||||||
|
<bugs>https://example.org</bugs>
|
||||||
|
</info>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
|
||||||
|
<id>testapp_infoxml</id>
|
||||||
|
<name>Test app</name>
|
||||||
|
<summary>A b c</summary>
|
||||||
|
<description>A b c</description>
|
||||||
|
<version>1.2.3</version>
|
||||||
|
<licence>agpl</licence>
|
||||||
|
<author>Jane</author>
|
||||||
|
<category>games</category>
|
||||||
|
<bugs>https://example.org</bugs>
|
||||||
|
<dependencies>
|
||||||
|
<nextcloud min-version="12.0" max-version="12.0"/>
|
||||||
|
</dependencies>
|
||||||
|
</info>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
|
||||||
|
<id>testapp_name_missing</id>
|
||||||
|
<summary>A b c</summary>
|
||||||
|
<description>A b c</description>
|
||||||
|
<version>1.2.3</version>
|
||||||
|
<licence>agpl</licence>
|
||||||
|
<author>Jane</author>
|
||||||
|
<category>games</category>
|
||||||
|
<bugs>https://example.org</bugs>
|
||||||
|
<dependencies>
|
||||||
|
<nextcloud min-version="12.0" max-version="12.0"/>
|
||||||
|
</dependencies>
|
||||||
|
</info>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
|
||||||
|
<id>testapp_version</id>
|
||||||
|
<name>Test app</name>
|
||||||
|
<summary>A b c</summary>
|
||||||
|
<description>A b c</description>
|
||||||
|
<licence>agpl</licence>
|
||||||
|
<author>Jane</author>
|
||||||
|
<category>games</category>
|
||||||
|
<bugs>https://example.org</bugs>
|
||||||
|
<dependencies>
|
||||||
|
<nextcloud min-version="12.0" max-version="12.0"/>
|
||||||
|
</dependencies>
|
||||||
|
</info>
|
|
@ -44,19 +44,21 @@ class InfoCheckerTest extends TestCase {
|
||||||
|
|
||||||
protected function setUp() {
|
protected function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->infoChecker = new InfoChecker(new InfoParser());
|
$this->infoChecker = new InfoChecker(\OC::$server->getAppManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function appInfoData() {
|
public function appInfoData() {
|
||||||
return [
|
return [
|
||||||
['testapp-infoxml', []],
|
['testapp_infoxml', []],
|
||||||
['testapp-version', [['type' => 'mandatoryFieldMissing', 'field' => 'version']]],
|
['testapp_version', [
|
||||||
['testapp-dependency-missing', [
|
['type' => 'parseError', 'field' => 'Element \'licence\': This element is not expected. Expected is one of ( description, version ).' . "\n"],
|
||||||
['type' => 'missingRequirement', 'field' => 'min'],
|
]],
|
||||||
['type' => 'missingRequirement', 'field' => 'max'],
|
['testapp_dependency_missing', [
|
||||||
['type' => 'mandatoryFieldMissing', 'field' => 'dependencies'],
|
['type' => 'parseError', 'field' => 'Element \'info\': Missing child element(s). Expected is one of ( repository, screenshot, dependencies ).' . "\n"],
|
||||||
|
]],
|
||||||
|
['testapp_name_missing', [
|
||||||
|
['type' => 'parseError', 'field' => 'Element \'summary\': This element is not expected. Expected is ( name ).' . "\n"],
|
||||||
]],
|
]],
|
||||||
['testapp-name-missing', [['type' => 'mandatoryFieldMissing', 'field' => 'name']]],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +70,7 @@ class InfoCheckerTest extends TestCase {
|
||||||
*/
|
*/
|
||||||
public function testApps($appId, $expectedErrors) {
|
public function testApps($appId, $expectedErrors) {
|
||||||
$errors = $this->infoChecker->analyse($appId);
|
$errors = $this->infoChecker->analyse($appId);
|
||||||
|
libxml_clear_errors();
|
||||||
|
|
||||||
$this->assertEquals($expectedErrors, $errors);
|
$this->assertEquals($expectedErrors, $errors);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue