Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App info xml parser 2 #12416

Merged
merged 3 commits into from
Nov 25, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 3 additions & 56 deletions lib/private/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -635,63 +635,10 @@ public static function getAppInfo($appId, $path = false) {
}
$file = self::getAppPath($appId) . '/appinfo/info.xml';
}
$data = array();
if (!file_exists($file)) {
return null;
}
$content = @file_get_contents($file);
if (!$content) {
return null;
}
$xml = new SimpleXMLElement($content);
$data['info'] = array();
$data['remote'] = array();
$data['public'] = array();
foreach ($xml->children() as $child) {
/**
* @var $child SimpleXMLElement
*/
if ($child->getName() == 'remote') {
foreach ($child->children() as $remote) {
/**
* @var $remote SimpleXMLElement
*/
$data['remote'][$remote->getName()] = (string)$remote;
}
} elseif ($child->getName() == 'public') {
foreach ($child->children() as $public) {
/**
* @var $public SimpleXMLElement
*/
$data['public'][$public->getName()] = (string)$public;
}
} elseif ($child->getName() == 'types') {
$data['types'] = array();
foreach ($child->children() as $type) {
/**
* @var $type SimpleXMLElement
*/
$data['types'][] = $type->getName();
}
} elseif ($child->getName() == 'description') {
$xml = (string)$child->asXML();
$data[$child->getName()] = substr($xml, 13, -14); //script <description> tags
} elseif ($child->getName() == 'documentation') {
foreach ($child as $subChild) {
$url = (string) $subChild;

// If it is not an absolute URL we assume it is a key
// i.e. admin-ldap will get converted to go.php?to=admin-ldap
if(!\OC::$server->getHTTPHelper()->isHTTPURL($url)) {
$url = OC_Helper::linkToDocs($url);
}

$data["documentation"][$subChild->getName()] = $url;
}
} else {
$data[$child->getName()] = (string)$child;
}
}
$parser = new \OC\App\InfoParser(\OC::$server->getHTTPHelper(), \OC::$server->getURLGenerator());
$data = $parser->parse($file);

self::$appInfo[$appId] = $data;

return $data;
Expand Down
84 changes: 84 additions & 0 deletions lib/private/app/infoparser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php
/**
* @author Thomas Müller
* @copyright 2014 Thomas Müller deepdiver@owncloud.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace OC\App;

use OCP\IURLGenerator;

class InfoParser {
/**
* @var \OC\HTTPHelper
*/
private $httpHelper;

/**
* @var IURLGenerator
*/
private $urlGenerator;

/**
* @param \OC\HTTPHelper $httpHelper
* @param IURLGenerator $urlGenerator
*/
public function __construct(\OC\HTTPHelper $httpHelper, IURLGenerator $urlGenerator) {
$this->httpHelper = $httpHelper;
$this->urlGenerator = $urlGenerator;
}

/**
* @param string $file the xml file to be loaded
* @return null|array where null is an indicator for an error
*/
public function parse($file) {
if (!file_exists($file)) {
return null;
}

$loadEntities = libxml_disable_entity_loader(false);
$xml = @simplexml_load_file($file);
libxml_disable_entity_loader($loadEntities);
if ($xml == false) {
return null;
}
$array = json_decode(json_encode((array)$xml), TRUE);
if (is_null($array)) {
return null;
}
if (!array_key_exists('info', $array)) {
$array['info'] = array();
}
if (!array_key_exists('remote', $array)) {
$array['remote'] = array();
}
if (!array_key_exists('public', $array)) {
$array['public'] = array();
}

if (array_key_exists('documentation', $array)) {
foreach ($array['documentation'] as $key => $url) {
// If it is not an absolute URL we assume it is a key
// i.e. admin-ldap will get converted to go.php?to=admin-ldap
if (!$this->httpHelper->isHTTPURL($url)) {
$url = $this->urlGenerator->linkToDocs($url);
}

$array['documentation'][$key] = $url;
}
}
if (array_key_exists('types', $array)) {
foreach ($array['types'] as $type => $v) {
unset($array['types'][$type]);
$array['types'][] = $type;
}
}

return $array;
}
}
5 changes: 2 additions & 3 deletions lib/private/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ public static function linkTo( $app, $file, $args = array() ) {
}

/**
* @param $key
* @param string $key
* @return string url to the online documentation
*/
public static function linkToDocs($key) {
$theme = new OC_Defaults();
return $theme->buildDocLinkToKey($key);
return OC::$server->getURLGenerator()->linkToDocs($key);
}

/**
Expand Down
12 changes: 11 additions & 1 deletion lib/private/urlgenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

namespace OC;
use OC_Defaults;
use OCP\IURLGenerator;
use RuntimeException;

Expand Down Expand Up @@ -156,7 +157,7 @@ public function imagePath($app, $image) {

/**
* Makes an URL absolute
* @param string $url the url in the owncloud host
* @param string $url the url in the ownCloud host
* @return string the absolute version of the url
*/
public function getAbsoluteURL($url) {
Expand All @@ -173,4 +174,13 @@ public function getAbsoluteURL($url) {

return \OC_Request::serverProtocol() . '://' . \OC_Request::serverHost(). $webRoot . $separator . $url;
}

/**
* @param string $key
* @return string url to the online documentation
*/
public function linkToDocs($key) {
$theme = new OC_Defaults();
return $theme->buildDocLinkToKey($key);
}
}
8 changes: 7 additions & 1 deletion lib/public/iurlgenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,14 @@ public function imagePath($appName, $file);

/**
* Makes an URL absolute
* @param string $url the url in the owncloud host
* @param string $url the url in the ownCloud host
* @return string the absolute version of the url
*/
public function getAbsoluteURL($url);

/**
* @param string $key
* @return string url to the online documentation
*/
public function linkToDocs($key);
}
19 changes: 19 additions & 0 deletions tests/data/app/expected-info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"info": [],
"remote": [],
"public": [],
"id": "files_encryption",
"name": "Server-side Encryption",
"description": "\n\tThis application encrypts all files accessed by ownCloud at rest, wherever they are stored. As an example, with this application enabled, external cloud based Amazon S3 storage will be encrypted, protecting this data on storage outside of the control of the Admin. When this application is enabled for the first time, all files are encrypted as users log in and are prompted for their password. The recommended recovery key option enables recovery of files in case the key is lost. \n\tNote that this app encrypts all files that are touched by ownCloud, so external storage providers and applications such as SharePoint will see new files encrypted when they are accessed. Encryption is based on AES 128 or 256 bit keys. More information is available in the Encryption documentation \n\t",
"licence": "AGPL",
"author": "Sam Tuke, Bjoern Schiessle, Florin Peter",
"requiremin": "4",
"shipped": "true",
"documentation": {
"user": "https://docs.example.com/server/go.php?to=user-encryption",
"admin": "https://docs.example.com/server/go.php?to=admin-encryption"
},
"rememberlogin": "false",
"types": ["filesystem"],
"ocsid": "166047"
}
22 changes: 22 additions & 0 deletions tests/data/app/invalid-info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<info
<id>files_encryption</id>
<name>Server-side Encryption</name>
<description>
This application encrypts all files accessed by ownCloud at rest, wherever they are stored. As an example, with this application enabled, external cloud based Amazon S3 storage will be encrypted, protecting this data on storage outside of the control of the Admin. When this application is enabled for the first time, all files are encrypted as users log in and are prompted for their password. The recommended recovery key option enables recovery of files in case the key is lost.
Note that this app encrypts all files that are touched by ownCloud, so external storage providers and applications such as SharePoint will see new files encrypted when they are accessed. Encryption is based on AES 128 or 256 bit keys. More information is available in the Encryption documentation
</description>
<licence>AGPL</licence>
<author>Sam Tuke, Bjoern Schiessle, Florin Peter</author>
<requiremin>4</requiremin>
<shipped>true</shipped>
<documentation>
<user>user-encryption</user>
<admin>admin-encryption</admin>
</documentation>
<rememberlogin>false</rememberlogin>
<types>
<filesystem/>
</types>
<ocsid>166047</ocsid>
</info>
22 changes: 22 additions & 0 deletions tests/data/app/valid-info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<info>
<id>files_encryption</id>
<name>Server-side Encryption</name>
<description>
This application encrypts all files accessed by ownCloud at rest, wherever they are stored. As an example, with this application enabled, external cloud based Amazon S3 storage will be encrypted, protecting this data on storage outside of the control of the Admin. When this application is enabled for the first time, all files are encrypted as users log in and are prompted for their password. The recommended recovery key option enables recovery of files in case the key is lost.
Note that this app encrypts all files that are touched by ownCloud, so external storage providers and applications such as SharePoint will see new files encrypted when they are accessed. Encryption is based on AES 128 or 256 bit keys. More information is available in the Encryption documentation
</description>
<licence>AGPL</licence>
<author>Sam Tuke, Bjoern Schiessle, Florin Peter</author>
<requiremin>4</requiremin>
<shipped>true</shipped>
<documentation>
<user>user-encryption</user>
<admin>admin-encryption</admin>
</documentation>
<rememberlogin>false</rememberlogin>
<types>
<filesystem/>
</types>
<ocsid>166047</ocsid>
</info>
53 changes: 53 additions & 0 deletions tests/lib/app/infoparser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/**
* @author Thomas Müller
* @copyright 2014 Thomas Müller deepdiver@owncloud.com
* later.
* See the COPYING-README file.
*/

namespace Test\App;

use OC;

class InfoParser extends \PHPUnit_Framework_TestCase {

/**
* @var \OC\App\InfoParser
*/
private $parser;

public function setUp() {
$config = $this->getMockBuilder('\OC\AllConfig')
->disableOriginalConstructor()->getMock();
$httpHelper = $this->getMockBuilder('\OC\HTTPHelper')
->setConstructorArgs(array($config))
->setMethods(array('getHeaders'))
->getMock();
$urlGenerator = $this->getMockBuilder('\OCP\IURLGenerator')
->disableOriginalConstructor()
->getMock();

//linkToDocs
$urlGenerator->expects($this->any())
->method('linkToDocs')
->will($this->returnCallback(function ($url) {
return "https://docs.example.com/server/go.php?to=$url";
}));

$this->parser = new \OC\App\InfoParser($httpHelper, $urlGenerator);
}

public function testParsingValidXml() {
$expectedData = json_decode(file_get_contents(OC::$SERVERROOT.'/tests/data/app/expected-info.json'), true);
$data = $this->parser->parse(OC::$SERVERROOT.'/tests/data/app/valid-info.xml');

$this->assertEquals($expectedData, $data);
}

public function testParsingInvalidXml() {
$data = $this->parser->parse(OC::$SERVERROOT.'/tests/data/app/invalid-info.xml');
$this->assertNull($data);
}
}