Commit a2149215 authored by Robert Lyon's avatar Robert Lyon
Browse files

Bug 1340151: dealing with libxml_disable_entity_loader

Set the state of the libxml entity loader & use internal
errors settings, back to what they were before we called
them, as a workaround to https://bugs.php.net/bug.php?id=64938

,
which causes them to be shared by all threads in a single
process.

behatnotneeded

Change-Id: I0720146b1e91c24095a18636e09981830ef4ce8f
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent 296fe519
......@@ -161,8 +161,10 @@ function addvariantform_submit(Pieform $form, $values) {
// Get SVG id from SVG font file...
$tempname = $values['fontfileSVG']['tmp_name'];
$filename = $values['fontfileSVG']['name'];
libxml_before(true);
$xmlDoc = simplexml_load_string(file_get_contents($tempname));
$svg_id = (string) $xmlDoc->defs->font->attributes()->id;
libxml_after();
// Update variants column in database record...
switch ($values['fontstyle']) {
......
......@@ -271,8 +271,11 @@ function addfontform_submit(Pieform $form, $values) {
// Get SVG id from SVG font file...
$tempname = (!empty($values['fontfileZip'])) ? $fontpath . $values['fontfileSVG']['name'] : $values['fontfileSVG']['tmp_name'];
$filename = $values['fontfileSVG']['name'];
libxml_before(true);
$xmlDoc = simplexml_load_string(file_get_contents($tempname));
$svg_id = (string) $xmlDoc->defs->font->attributes()->id;
libxml_after();
// Insert new record with font data into 'skin_fonts' table in database...
// $foldername equals (only alphanumerical) font name, e.g. 'Nimbus Roman No.9' -> 'NimbusRomanNo9'
......
......@@ -121,6 +121,7 @@ class PluginBlocktypeGallery extends PluginBlocktype {
}
$big = 's' . get_config_plugin('blocktype', 'gallery', 'previewwidth');
libxml_before(true);
$xmlDoc = new DOMDocument('1.0', 'UTF-8');
$config = array(
CURLOPT_URL => $URL,
......@@ -129,6 +130,8 @@ class PluginBlocktypeGallery extends PluginBlocktype {
$result = mahara_http_request($config);
$xmlDoc->loadXML($result->data);
$photos = $xmlDoc->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'group');
libxml_after();
foreach ($photos as $photo) {
$children = $photo->cloneNode(true);
$thumb = $children->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'thumbnail')->item(0)->getAttribute('url');
......@@ -161,6 +164,7 @@ class PluginBlocktypeGallery extends PluginBlocktype {
$api_key = get_config_plugin('blocktype', 'gallery', 'flickrapikey');
$URL = 'https://api.flickr.com/services/rest/?method=flickr.photosets.getPhotos&extras=url_sq,url_t&photoset_id=' . $var2 . '&api_key=' . $api_key;
libxml_before(true);
$xmlDoc = new DOMDocument('1.0', 'UTF-8');
$config = array(
CURLOPT_URL => $URL,
......@@ -169,6 +173,7 @@ class PluginBlocktypeGallery extends PluginBlocktype {
$result = mahara_http_request($config);
$xmlDoc->loadXML($result->data);
$photos = $xmlDoc->getElementsByTagName('photo');
libxml_after();
foreach ($photos as $photo) {
// If the Thumbnails should be Square...
if ($style == 2) {
......@@ -260,6 +265,7 @@ class PluginBlocktypeGallery extends PluginBlocktype {
$oauth_signature = base64_encode(hash_hmac('sha1', $base, $consumer_secret.'&', true));
$URL = $api_url . '?' . $paramstring . '&oauth_signature=' . urlencode($oauth_signature);
libxml_before(true);
$xmlDoc = new DOMDocument('1.0', 'UTF-8');
$config = array(
CURLOPT_URL => $URL,
......@@ -279,6 +285,7 @@ class PluginBlocktypeGallery extends PluginBlocktype {
$xmlDoc2->loadXML($result->data);
$photos = $xmlDoc2->getElementsByTagName('media');
libxml_after();
foreach ($photos as $photo) {
$children = $photo->cloneNode(true);
$link = $children->getElementsByTagName('url')->item(0)->firstChild->nodeValue;
......
......@@ -629,10 +629,12 @@ class PluginExportLeap extends PluginExport {
* @return xhtml content or false for unmodified text content
*/
public static function parse_xhtmlish_content($content, $viewid=null) {
libxml_before(true);
$dom = new DomDocument();
$topel = $dom->createElement('tmp');
$tmp = new DomDocument();
if (strpos($content, '<') === false && strpos($content, '>') === false) {
libxml_after();
return false;
}
if (@$tmp->loadXML('<div>' . $content . '</div>')) {
......@@ -655,6 +657,7 @@ class PluginExportLeap extends PluginExport {
log_warn("Leap2a export: invalid html found in view $viewid");
}
if ($elements->length < 1) {
libxml_after();
return false;
}
}
......@@ -663,9 +666,12 @@ class PluginExportLeap extends PluginExport {
$content->setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
$topel->appendChild($content);
} else {
libxml_after();
return false; // wtf is it then?
}
$dom->appendChild($topel->firstChild);
libxml_after();
return $dom->saveXML($dom->documentElement);
}
}
......
......@@ -119,17 +119,14 @@ class PluginImportLeap extends PluginImport {
LIBXML_COMPACT | // Reported to greatly speed XML parsing
LIBXML_NONET // Disable network access - security check
;
if (function_exists('libxml_disable_entity_loader')) {
// The LIBXML_NONET stops proper network based XXE attacks from happening
libxml_disable_entity_loader(false);
}
libxml_before(false);
if (!$this->xml = simplexml_load_file($this->filename, 'SimpleXMLElement', $options)) {
// TODO: bail out in a much nicer way...
libxml_after();
throw new ImportException($this, "FATAL: XML file is not well formed! Please consult Mahara's error log for more information");
}
if (function_exists('libxml_disable_entity_loader')) {
libxml_disable_entity_loader(true);
}
libxml_after();
$this->namespaces = array_flip($this->xml->getDocNamespaces());
$this->registerXpathNamespaces($this->xml);
$this->trace("Document loaded, entries: " . count($this->xml->entry));
......
......@@ -49,27 +49,6 @@ if (!is_readable($CFG->docroot . 'config.php')) {
init_performance_info();
// Because the default XML loader is vulnerable to XEE attacks, we're disabling it by default.
// If you need to use it, you can re-enable the function, call it while passing in the
// LIBXML_NONET parameter, and then disable the function again, like this:
//
// EXAMPLE
// if (function_exists('libxml_disable_entity_loader')) {
// libxml_disable_entity_loader(false);
// }
// $options =
// LIBXML_COMPACT | // Reported to greatly speed XML parsing
// LIBXML_NONET // Disable network access - security check
// ;
// $xml = simplexml_load_file($filename, 'SimpleXMLElement', $options);
// if (function_exists('libxml_disable_entity_loader')) {
// libxml_disable_entity_loader(true);
// }
// END EXAMPLE
if (function_exists('libxml_disable_entity_loader')) {
libxml_disable_entity_loader(true);
}
require($CFG->docroot . 'config.php');
$CFG = (object)array_merge((array)$cfg, (array)$CFG);
require_once('config-defaults.php');
......
......@@ -4053,3 +4053,48 @@ function server_busy($threshold = false) {
}
return false;
}
/**
* Set libxml internal errors and entity loader
* state before accessing an external xml document
*
* @param boolean $state The state to set the options to
*/
function libxml_before($state = true) {
$xmlstate = $xmlerrors = null;
if (function_exists('libxml_disable_entity_loader')) {
$xmlerrors = libxml_use_internal_errors($state);
$xmlstate = libxml_disable_entity_loader($state);
// Record these settings so we can go back them at the end, as a workaround
// to PHP bug https://bugs.php.net/bug.php?id=64938
if (!defined('MAHARA_LIBXML_ENTITY_LOADER_BEFORE')) {
define('MAHARA_LIBXML_USE_INTERNAL_ERRORS_BEFORE', $xmlerrors);
define('MAHARA_LIBXML_ENTITY_LOADER_BEFORE', $xmlstate);
register_shutdown_function('libxml_after');
}
}
return array($xmlstate, $xmlerrors);
}
/**
* Set libxml internal errors and entity loader
* state after accessing an external xml document
*/
function libxml_after() {
if (function_exists('libxml_disable_entity_loader')) {
if (defined('MAHARA_LIBXML_ENTITY_LOADER_BEFORE')) {
$xmlerrors = MAHARA_LIBXML_USE_INTERNAL_ERRORS_BEFORE;
$xmlstate = MAHARA_LIBXML_ENTITY_LOADER_BEFORE;
}
else {
$xmlerrors = true;
$xmlstate = true;
}
libxml_use_internal_errors($xmlerrors);
libxml_disable_entity_loader($xmlstate);
}
}
......@@ -93,11 +93,13 @@ function importskinform_submit(Pieform $form, $values) {
$filename = $values['file']['tmp_name'];
$contents = file_get_contents($filename);
libxml_before(true);
$xmldoc = new DOMDocument('1.0', 'UTF-8');
//$xmldoc->load($filename);
$xmldoc->loadXML($contents);
$skinsdata = $xmldoc->getElementsByTagName('skin');
libxml_after();
$siteskin = ($values['skintype'] == 'site');
// A non-admin can't create a site skin.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment