From af2e76e97257be9c21eb4e697c0847b31294592d Mon Sep 17 00:00:00 2001 From: Daniel Thee Roperto Date: Thu, 10 Nov 2016 17:06:56 +1100 Subject: [PATCH] Issue #22 - Fetching url() inside CSS files. --- .../controllers/maintenance_static_page.php | 49 ++++++++++++++----- .../fixtures/subdir/withurls-subdir.css | 1 + .../controllers/fixtures/withurls-quoted.css | 7 +++ .../local/controllers/fixtures/withurls.css | 7 +++ .../maintenance_static_page_test.php | 47 +++++++++++++++++- 5 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 tests/phpunit/local/controllers/fixtures/subdir/withurls-subdir.css create mode 100644 tests/phpunit/local/controllers/fixtures/withurls-quoted.css create mode 100644 tests/phpunit/local/controllers/fixtures/withurls.css diff --git a/classes/local/controllers/maintenance_static_page.php b/classes/local/controllers/maintenance_static_page.php index 55ae182..74f3a33 100644 --- a/classes/local/controllers/maintenance_static_page.php +++ b/classes/local/controllers/maintenance_static_page.php @@ -291,12 +291,12 @@ class maintenance_static_page { if (($rel != 'stylesheet') || ($href == '')) { continue; } - $filename = $this->save_url_file($href); - if (is_null($filename)) { + $saved = $this->save_url_file($href); + if (is_null($saved['url'])) { $url = $href; // Skipped, use original URL. } else { - $this->update_link_stylesheet_parse($filename); - $url = $this->get_url_for_file($filename); + $this->update_link_stylesheet_parse($saved['file'], dirname($href)); + $url = $this->get_url_for_file($saved['url']); } $link->setAttribute('href', $url); } @@ -306,7 +306,31 @@ class maintenance_static_page { * Checks for urls inside filename. * @param string $filename */ - private function update_link_stylesheet_parse($filename) { + private function update_link_stylesheet_parse($filename, $baseref) { + global $CFG; + + $contents = file_get_contents($filename); + if (!preg_match_all('#url\([\'"]?([^\'"\)]+)#', $contents, $matches)) { + return; + } + foreach ($matches[1] as $original_url) { + // Allow incomplete URLs in CSS, assume it is from moodle root. + if (self::is_url($original_url)) { + $full_url = $original_url; + } else if ($original_url[0] == '/') { + $full_url = $CFG->wwwroot.$original_url; + } else { + $full_url = $baseref.'/'.$original_url; + } + + $saved = $this->save_url_file($full_url); + if (!is_null($saved)) { + $final_url = $this->get_url_for_file($saved['url']); + $contents = str_replace($original_url, $final_url, $contents); + } + } + + file_put_contents($filename, $contents); } /** @@ -346,11 +370,11 @@ class maintenance_static_page { * @return string Output URL. */ private function generate_file_url($url) { - $filename = $this->save_url_file($url); - if (is_null($filename)) { + $saved = $this->save_url_file($url); + if (is_null($saved)) { return $url; // Skipped, use original URL. } - return $this->get_url_for_file($filename); + return $this->get_url_for_file($saved['url']); } /** @@ -387,13 +411,14 @@ class maintenance_static_page { $data = self::file_get_data($url); $mime = trim(base64_encode($data['mime']), '='); - $filename = sha1($data['contents']).'.'.$mime; - $filepath = $this->get_resources_folder().'/'.$filename; + $url = sha1($data['contents']).'.'.$mime; + $filepath = $this->get_resources_folder().'/'.$url; file_put_contents($filepath, $data['contents']); if ($this->preview) { - $filename = 'preview/'.$filename; + $url = 'preview/'.$url; } - return $filename; + + return ['file' => $filepath, 'url' => $url]; } } diff --git a/tests/phpunit/local/controllers/fixtures/subdir/withurls-subdir.css b/tests/phpunit/local/controllers/fixtures/subdir/withurls-subdir.css new file mode 100644 index 0000000..3e9c1a8 --- /dev/null +++ b/tests/phpunit/local/controllers/fixtures/subdir/withurls-subdir.css @@ -0,0 +1 @@ +@import url(../simple.css); diff --git a/tests/phpunit/local/controllers/fixtures/withurls-quoted.css b/tests/phpunit/local/controllers/fixtures/withurls-quoted.css new file mode 100644 index 0000000..012773c --- /dev/null +++ b/tests/phpunit/local/controllers/fixtures/withurls-quoted.css @@ -0,0 +1,7 @@ +a { + font-size: 200%; +} + +div { + background-image: url('/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png'); +} \ No newline at end of file diff --git a/tests/phpunit/local/controllers/fixtures/withurls.css b/tests/phpunit/local/controllers/fixtures/withurls.css new file mode 100644 index 0000000..7e1e985 --- /dev/null +++ b/tests/phpunit/local/controllers/fixtures/withurls.css @@ -0,0 +1,7 @@ +a { + font-size: 200%; +} + +div { + background-image: url(/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png); +} \ No newline at end of file diff --git a/tests/phpunit/local/controllers/maintenance_static_page_test.php b/tests/phpunit/local/controllers/maintenance_static_page_test.php index 61255c8..61d422d 100644 --- a/tests/phpunit/local/controllers/maintenance_static_page_test.php +++ b/tests/phpunit/local/controllers/maintenance_static_page_test.php @@ -87,6 +87,51 @@ class maintenance_static_page_test extends auth_outage_base_testcase { self::assertContains($external_css_link, $generated); } + public function test_updatelinkstylesheet_urls() { + $local_css_link = $this->get_fixture_path('withurls.css'); + $html = "\n". + 'Title'. + 'Content'; + $page = maintenance_static_page::create_from_html($html); + $page->generate(); + + // Check for css file. + self::assertFileExists($page->get_resources_folder().'/622ef6e83acfcb274cdf37bdb3bffa0923f9a7ad.dGV4dC9wbGFpbg'); + + // Check for catalyst.png file referenced in url(..) of css. + self::assertFileExists($page->get_resources_folder().'/ff7f7f87a26a908fc72930eaefb6b57306361d16.aW1hZ2UvcG5n'); + } + + public function test_updatelinkstylesheet_urls_quoted() { + $local_css_link = $this->get_fixture_path('withurls-quoted.css'); + $html = "\n". + 'Title'. + 'Content'; + $page = maintenance_static_page::create_from_html($html); + $page->generate(); + + // Check for css file. + self::assertFileExists($page->get_resources_folder().'/1d84b6d321fef780237f84834b7316c079221a31.dGV4dC9wbGFpbg'); + + // Check for catalyst.png file referenced in url(..) of css. + self::assertFileExists($page->get_resources_folder().'/ff7f7f87a26a908fc72930eaefb6b57306361d16.aW1hZ2UvcG5n'); + } + + public function test_updatelinkstylesheet_urls_subdir() { + $local_css_link = $this->get_fixture_path('subdir/withurls-subdir.css'); + $html = "\n". + 'Title'. + 'Content'; + $page = maintenance_static_page::create_from_html($html); + $page->generate(); + + // Check for css file. + self::assertFileExists($page->get_resources_folder().'/4ea71b83ab326a15d0d784b34fcda702b6a7427d.dGV4dC9wbGFpbg'); + + // Check for file referenced in url(..) of css. + self::assertFileExists($page->get_resources_folder().'/a02a8a442fa82d5205ffb24722d9df7f35161f56.dGV4dC9wbGFpbg'); + } + public function test_updateimages() { $local_img_link = $this->get_fixture_path('catalyst.png'); $external_img_link = 'http://google.com/coolstyle.css'; @@ -167,9 +212,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase { 'Title'. 'Content'; $page = maintenance_static_page::create_from_html($html); - $page->set_preview(true); $page->generate(); - $generated = trim(file_get_contents($page->get_template_file())); // This checks if content is correct and mime type is correct from the encoded name. $file = $page->get_resources_folder().'/ff7f7f87a26a908fc72930eaefb6b57306361d16.aW1hZ2UvcG5n';