Commit 76a2c6c9 authored by Robert Lyon's avatar Robert Lyon Committed by Aaron Wells

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 ffc3f7db
......@@ -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']) {
......
......@@ -270,8 +270,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'
......
......@@ -113,6 +113,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,
......@@ -121,6 +122,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');
......@@ -153,6 +156,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,
......@@ -161,6 +165,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) {
......@@ -252,6 +257,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,
......@@ -271,6 +277,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;
......
......@@ -624,10 +624,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>')) {
......@@ -650,6 +652,7 @@ class PluginExportLeap extends PluginExport {
log_warn("Leap2a export: invalid html found in view $viewid");
}
if ($elements->length < 1) {
libxml_after();
return false;
}
}
......@@ -658,9 +661,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,11 +119,7 @@ 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);
require_once('file.php');
if (!$this->xml = simplexml_load_string(
preg_replace(xml_filter_regex(), '', file_get_contents($this->filename)),
......@@ -131,11 +127,11 @@ class PluginImportLeap extends PluginImport {
$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));
......
......@@ -35,27 +35,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');
......
......@@ -4360,3 +4360,48 @@ function recursive_implode(array $array, $include_keys = false, $separator = ','
$trim_all and $glued_string = preg_replace("/(\s)/ixsm", '', $glued_string);
return (string) $glued_string;
}
/**
* 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);
}
}
......@@ -94,11 +94,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