diff --git a/data/patches/OPSA-2013-003.diff b/data/patches/OPSA-2013-003.diff
new file mode 100644
index 0000000..8352544
--- /dev/null
+++ b/data/patches/OPSA-2013-003.diff
@@ -0,0 +1,20 @@
+diff --git a/lib/vendor/php-openid/Auth/Yadis/XML.php b/lib/vendor/php-openid/Auth/Yadis/XML.php
+index 2704c78..f5e80a5 100644
+--- a/lib/vendor/php-openid/Auth/Yadis/XML.php
++++ b/lib/vendor/php-openid/Auth/Yadis/XML.php
+@@ -234,7 +234,14 @@ function setXML($xml_string)
+ return false;
+ }
+
+- if (!@$this->doc->loadXML($xml_string)) {
++ // disable external entities and libxml errors
++ $loader = libxml_disable_entity_loader(true);
++ $errors = libxml_use_internal_errors(true);
++ $parse_result = @$this->doc->loadXML($xml_string);
++ libxml_disable_entity_loader($loader);
++ libxml_use_internal_errors($errors);
++
++ if (!$parse_result) {
+ return false;
+ }
+
diff --git a/data/version.php b/data/version.php
index bc478cf..ea8237a 100644
--- a/data/version.php
+++ b/data/version.php
@@ -10,5 +10,5 @@
if (!defined('OPENPNE_VERSION'))
{
- define('OPENPNE_VERSION', '3.8.7');
+ define('OPENPNE_VERSION', '3.8.7.1');
}
diff --git a/doc/en/OpenPNE3_Setup_Guide.txt b/doc/en/OpenPNE3_Setup_Guide.txt
index 76f1c7e..b9a6e10 100644
--- a/doc/en/OpenPNE3_Setup_Guide.txt
+++ b/doc/en/OpenPNE3_Setup_Guide.txt
@@ -13,7 +13,7 @@ Web Server
Apache
* The "mod_rewrite" module is available
PHP
- PHP version 5.2.3 or later
+ PHP version 5.2.11 or later (if you want to use with earlier than PHP 5.2.11, you should build PHP with libxml 2.9+)
* The "mbstring" module is available
* The "xml" module is available
* The "PCRE" module is available (That must be support UTF-8)
diff --git a/doc/ja/OpenPNE3_Setup_Guide.txt b/doc/ja/OpenPNE3_Setup_Guide.txt
index 7ef58b3..36caaf0 100644
--- a/doc/ja/OpenPNE3_Setup_Guide.txt
+++ b/doc/ja/OpenPNE3_Setup_Guide.txt
@@ -13,7 +13,7 @@ Webサーバ
Apache
* mod_rewrite を使用可能
PHP
- PHP5.2.3 以降
+ PHP 5.2.11 以降 (PHP 5.2.11 未満で動作させる場合は libxml 2.9 以降と一緒に PHP をビルドしてください)
* PHP の mbstring 拡張モジュールを使用可能
* PHP の XML 拡張モジュールを使用可能
* PHP の PCRE 拡張モジュールを使用可能 (UTF-8 サポート)
diff --git a/lib/plugin/opPearRest.class.php b/lib/plugin/opPearRest.class.php
index 38aa2df..514e00e 100644
--- a/lib/plugin/opPearRest.class.php
+++ b/lib/plugin/opPearRest.class.php
@@ -27,7 +27,10 @@ public function retrieveData($url, $accept = false, $forcestring = false, $chann
public function retrieveXml($url)
{
$content = $this->downloadHttp($url);
- $result = @simplexml_load_string($content);
+ $result = @opToolkit::loadXmlString($content, array(
+ 'return' => 'SimpleXMLElement',
+ ));
+
return $result;
}
diff --git a/lib/plugin/opPlugin.class.php b/lib/plugin/opPlugin.class.php
index 242e3f9..cc3acdb 100644
--- a/lib/plugin/opPlugin.class.php
+++ b/lib/plugin/opPlugin.class.php
@@ -125,7 +125,11 @@ protected function getPackageInfo()
{
return false;
}
- return simplexml_load_file($xmlPath);
+ $content = file_get_contents($xmlPath);
+
+ return opToolkit::loadXmlString($content, array(
+ 'return' => 'SimpleXMLElement',
+ ));
}
public function setIsActive($isActive)
diff --git a/lib/task/opPluginArchiveTask.class.php b/lib/task/opPluginArchiveTask.class.php
index 484d5d8..84edaab 100644
--- a/lib/task/opPluginArchiveTask.class.php
+++ b/lib/task/opPluginArchiveTask.class.php
@@ -47,7 +47,11 @@ protected function execute($arguments = array(), $options = array())
throw new sfException(sprintf('Plugin "%s" dosen\'t have a definition file.', $pluginName));
}
- $infoXml = simplexml_load_file($packagePath.'/package.xml');
+ $content = file_get_contents($packagePath.'/package.xml');
+ $infoXml = opToolkit::loadXmlString($content, array(
+ 'return' => 'SimpleXMLElement',
+ ));
+
$filename = sprintf('%s-%s.tgz', (string)$infoXml->name, (string)$infoXml->version->release);
$dirPath = sfConfig::get('sf_plugins_dir').'/'.$pluginName;
diff --git a/lib/util/opToolkit.class.php b/lib/util/opToolkit.class.php
index 61fb771..41c733f 100644
--- a/lib/util/opToolkit.class.php
+++ b/lib/util/opToolkit.class.php
@@ -582,4 +582,48 @@ static public function writeCacheFile($pathToCacheFile, $content)
$filesystem->chmod($pathToCacheFile, 0666);
umask($currentUmask);
}
+
+ /**
+ * Parse the input data and create either a SimpleXmlElement object or a DOMDocument (from CakePHP 2.3.9)
+ *
+ * This method is based Xml::_loadXmlString() in CakePHP 2.3.9 with many our arranged
+ *
+ * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://cakephp.org CakePHP(tm) Project
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ *
+ * @param string $input The input to load.
+ * @param array $options The options to use.
+ * @return SimpleXmlElement|DOMDocument
+ */
+ public static function loadXmlString($input, $options = array())
+ {
+ $hasDisable = function_exists('libxml_disable_entity_loader');
+ $internalErrors = libxml_use_internal_errors(true);
+ $isDisableEntityLoader = ($hasDisable && empty($options['loadEntities']));
+ if ($isDisableEntityLoader)
+ {
+ $entityLoaderConfig = libxml_disable_entity_loader(true);
+ }
+
+ $returnClass = isset($options['return']) ? strtolower($options['return']) : '';
+
+ if ('simplexml' === $returnClass || 'simplexmlelement' === $returnClass)
+ {
+ $xml = simplexml_load_string($input);
+ }
+ else
+ {
+ $xml = new DOMDocument();
+ $xml->loadXML($input);
+ }
+
+ if ($isDisableEntityLoader)
+ {
+ libxml_disable_entity_loader($entityLoaderConfig);
+ }
+ libxml_use_internal_errors($internalErrors);
+
+ return $xml;
+ }
}
diff --git a/lib/vendor/php-openid/Auth/Yadis/XML.php b/lib/vendor/php-openid/Auth/Yadis/XML.php
index 2704c78..f5e80a5 100644
--- a/lib/vendor/php-openid/Auth/Yadis/XML.php
+++ b/lib/vendor/php-openid/Auth/Yadis/XML.php
@@ -234,7 +234,14 @@ function setXML($xml_string)
return false;
}
- if (!@$this->doc->loadXML($xml_string)) {
+ // disable external entities and libxml errors
+ $loader = libxml_disable_entity_loader(true);
+ $errors = libxml_use_internal_errors(true);
+ $parse_result = @$this->doc->loadXML($xml_string);
+ libxml_disable_entity_loader($loader);
+ libxml_use_internal_errors($errors);
+
+ if (!$parse_result) {
return false;
}
diff --git a/test/unit/util/opToolkitLoadXmlStringTest.php b/test/unit/util/opToolkitLoadXmlStringTest.php
new file mode 100644
index 0000000..8d15160
--- /dev/null
+++ b/test/unit/util/opToolkitLoadXmlStringTest.php
@@ -0,0 +1,25 @@
+diag('opToolkit::loadXmlString()');
+
+$path_to_feed = realpath(dirname(__FILE__).'/../../fixtures/feeds/www.xss.feed.rss');
+$xml = 'ok';
+$xml_with_xxe = ']>ok&xxe;';
+
+$t->comment('with no external entities');
+
+$t->isa_ok(opToolkit::loadXmlString($xml), 'DOMDocument', 'returns an instance of "DOMDocument"');
+$t->isa_ok(opToolkit::loadXmlString($xml, array('return' => 'SimpleXMLElement')), 'SimpleXMLElement', 'returns an instanceof "SimpleXMLElement"');
+
+$t->comment('with external entities');
+
+$t->isa_ok(opToolkit::loadXmlString($xml_with_xxe), 'DOMDocument', 'returns an instance of "DOMDocument"');
+$t->isa_ok(opToolkit::loadXmlString($xml_with_xxe, array('return' => 'SimpleXMLElement')), 'SimpleXMLElement', 'returns an instanceof "SimpleXMLElement"');
+$t->is(opToolkit::loadXmlString($xml_with_xxe)->textContent, 'ok', 'generated XML string by "DOMDocument" does not have entitied value');
+$t->is((string)opToolkit::loadXmlString($xml_with_xxe, array('return' => 'SimpleXMLElement')), 'ok', 'generated XML string by "SimpleXMLElement" does not have entitied value');
+$t->isnt(opToolkit::loadXmlString($xml_with_xxe, array('loadEntities' => true))->textContent, 'ok', 'generated XML string by "DOMDocument" has entitied value if "loadEntities" option is specified');
+$t->isnt((string)opToolkit::loadXmlString($xml_with_xxe, array('return' => 'SimpleXMLElement', 'loadEntities' => true)), 'ok', 'generated XML string by "SimpleXMLElement" has entitied value if "loadEntities" option is specified');