Skip to content

Commit

Permalink
Fix #234 pick up images from inline style background image.
Browse files Browse the repository at this point in the history
  • Loading branch information
katerynadegtyariova committed May 24, 2021
1 parent 2aec039 commit 92cb858
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
47 changes: 47 additions & 0 deletions classes/local/controllers/maintenance_static_page_generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public function generate() {
$this->update_link_favicon();
$this->update_images();
$this->remove_configured_css_selectors();
$this->update_inline_background_images();

$html = $this->dom->saveHTML();
if (trim($html) == '') {
Expand Down Expand Up @@ -150,6 +151,27 @@ public function get_urls_from_stylesheet($contents) {
return $matches;
}

/**
* Retrieves a URL from inline style using regular expressions.
*
* @param string $style Content of the style attribute
* @param string &$pattern Pattern used for matching URL
* @return array Array containing match
*/
public function get_url_from_inline_style($style, &$pattern) {
/*
* The pattern should match the attribute values that
* go as 'url(xxxxx)', but make sure 'url(data:xxxxx)' is not
* rewritten. Must be case insensitive to match 'URL(xxxxx)'.
* It should be possible to specify other background attributes as
* 'background: color url(xxxxx) no-repeat'.
*/
$pattern = '/url\s*\(\s*[\'"]?(?![\'"]?data:)([^\s\'"]+)[\'"]?\s*\)/i';
preg_match($pattern, $style, $match);
return $match;
}


/**
* Checks for urls inside filename.
*
Expand Down Expand Up @@ -218,6 +240,31 @@ private function update_images() {
}
}

/**
* Fetch and fixes all inline background images.
*/
private function update_inline_background_images() {
global $CFG;
$xpath = new \DOMXPath($this->dom);
$elements = $xpath->query("//*[@style]");

foreach ($elements as $element) {
$style = $element->getAttribute("style");
$matches = $this->get_url_from_inline_style($style, $pattern);
if (isset($matches[1])) {
// Allow incomplete URLs in style, assume it is from moodle root.
if (maintenance_static_page_io::is_url($matches[1])) {
$fullurl = $matches[1];
} else {
$fullurl = (string) new moodle_url($matches[1]);
}
$newurl = $this->io->generate_file_url($fullurl);
$updated = preg_replace($pattern, ' url('.$newurl.') ', $style);
$element->setAttribute('style', $updated);
}
}
}

/**
* Remove from DOM the CSS selectores defined in the plugin settings.
*/
Expand Down
54 changes: 54 additions & 0 deletions tests/phpunit/local/controllers/maintenance_static_page_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,60 @@ public function test_updatelinkfavicon() {
self::assertStringContainsString('www.example.com/moodle/auth/outage/file.php?file=', $generated);
}


/**
* Data provider for test_update_inline_background_images
* @return array
*/
public function test_update_inline_background_images_provider() {
return [
// Empty string.
["", false],
// URLs that should be retrieved.
["color: #FF00FF; background: lightblue url(/pluginfile.php/1/theme_custom/banner/251298630/0001.png) no-repeat", true],
["background: lightblue url(https://www.example.com/moodle/pluginfile.php/1/theme_custom/banner/251298630/0001.png) no-repeat", true],
["background:url('https://www.example.com/moodle/pluginfile.php/1/theme_custom/banner/251298630/0001.png')", true],
["background-image : url( /pix/help.png);", true],
["background-image: url ('/pix/help.png')", true],
// URLs that should not be retrieved.
["background-image:url(data:image/gif;base64,R0lGODlhYADIAP=)", false],
["background-image:url('data:image/gif;base64,R0lGODlhYADIAP=')", false]
];
}

/**
* Tests update_inline_background_images() method to update the background images.
*
* @dataProvider test_update_inline_background_images_provider
* @param string $stylecontent Content of the style to test
* @param bool $rewrite Flag if URL should be rewritten
* @throws coding_exception
*/
public function test_update_inline_background_images($stylecontent, $rewrite) {
global $CFG;
$this->resetAfterTest(true);
$generator = new maintenance_static_page_generator(new DOMDocument(), new maintenance_static_page_io());

$html = '<!DOCTYPE html>\n'.
'<html><head><title>Title</title></head>'.
'<body><div style="'.$stylecontent.'">Content</div></body></html>';

// Temporarily disable debugging to prevent errors because file does not exist
$debuglevel = $CFG->debug;
$CFG->debug = '';
$generated = $this->generated_page_html($html);
// Restore debugging level
$CFG->debug = $debuglevel;
$matches = $generator->get_url_from_inline_style($stylecontent, $pattern);
if ($rewrite) {
self::assertStringNotContainsString($matches[1], $generated);
self::assertStringContainsString('www.example.com/moodle/auth/outage/file.php?file=', $generated);
self::assertIsArray($matches);
} else {
self::assertStringContainsString($stylecontent, $generated);
}
}

/**
* Test update preview path to file.php style link.
*/
Expand Down

0 comments on commit 92cb858

Please sign in to comment.