Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * HTTPS find and replace Tests 19 * 20 * @package tool_httpsreplace 21 * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace tool_httpsreplace\tests; 26 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 /** 31 * Tests the httpsreplace tool. 32 * 33 * @package tool_httpsreplace 34 * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class httpsreplace_test extends \advanced_testcase { 38 39 /** 40 * Data provider for test_upgrade_http_links 41 */ 42 public function upgrade_http_links_provider() { 43 global $CFG; 44 // Get the http url, since the default test wwwroot is https. 45 $wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot); 46 return [ 47 "Test image from another site should be replaced" => [ 48 "content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">', 49 "outputregex" => '/UPDATE/', 50 "expectedcontent" => '<img src="' . $this->get_converted_http_link('/test.jpg') . '">', 51 ], 52 "Test object from another site should be replaced" => [ 53 "content" => '<object data="' . $this->getExternalTestFileUrl('/test.swf', false) . '">', 54 "outputregex" => '/UPDATE/', 55 "expectedcontent" => '<object data="' . $this->get_converted_http_link('/test.swf') . '">', 56 ], 57 "Test image from a site with international name should be replaced" => [ 58 "content" => '<img src="http://中国互联网络信息中心.中国/logosy/201706/W01.png">', 59 "outputregex" => '/UPDATE/', 60 "expectedcontent" => '<img src="https://中国互联网络信息中心.中国/logosy/201706/W01.png">', 61 ], 62 "Link that is from this site should be replaced" => [ 63 "content" => '<img src="' . $wwwroothttp . '/logo.png">', 64 "outputregex" => '/UPDATE/', 65 "expectedcontent" => '<img src="' . $CFG->wwwroot . '/logo.png">', 66 ], 67 "Link that is from this site, https new so doesn't need replacing" => [ 68 "content" => '<img src="' . $CFG->wwwroot . '/logo.png">', 69 "outputregex" => '/^$/', 70 "expectedcontent" => '<img src="' . $CFG->wwwroot . '/logo.png">', 71 ], 72 "Unavailable image should be replaced" => [ 73 "content" => '<img src="http://intentionally.unavailable/link1.jpg">', 74 "outputregex" => '/UPDATE/', 75 "expectedcontent" => '<img src="https://intentionally.unavailable/link1.jpg">', 76 ], 77 "Https content that has an http url as a param should not be replaced" => [ 78 "content" => '<img src="https://anothersite.com?param=http://asdf.com">', 79 "outputregex" => '/^$/', 80 "expectedcontent" => '<img src="https://anothersite.com?param=http://asdf.com">', 81 ], 82 "Search for params should be case insensitive" => [ 83 "content" => '<object DATA="' . $this->getExternalTestFileUrl('/test.swf', false) . '">', 84 "outputregex" => '/UPDATE/', 85 "expectedcontent" => '<object DATA="' . $this->get_converted_http_link('/test.swf') . '">', 86 ], 87 "URL should be case insensitive" => [ 88 "content" => '<object data="HTTP://some.site/path?query">', 89 "outputregex" => '/UPDATE/', 90 "expectedcontent" => '<object data="https://some.site/path?query">', 91 ], 92 "More params should not interfere" => [ 93 "content" => '<img alt="A picture" src="' . $this->getExternalTestFileUrl('/test.png', false) . 94 '" width="1”><p style="font-size: \'20px\'"></p>', 95 "outputregex" => '/UPDATE/', 96 "expectedcontent" => '<img alt="A picture" src="' . $this->get_converted_http_link('/test.png') . 97 '" width="1”><p style="font-size: \'20px\'"></p>', 98 ], 99 "Broken URL should not be changed" => [ 100 "content" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">', 101 "outputregex" => '/^$/', 102 "expectedcontent" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">', 103 ], 104 "Link URL should not be changed" => [ 105 "content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' . 106 $this->getExternalTestFileUrl('/test.png', false) . '</a>', 107 "outputregex" => '/^$/', 108 "expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' . 109 $this->getExternalTestFileUrl('/test.png', false) . '</a>', 110 ], 111 "Test image from another site should be replaced but link should not" => [ 112 "content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' . 113 $this->getExternalTestFileUrl('/test.jpg', false) . '"></a>', 114 "outputregex" => '/UPDATE/', 115 "expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' . 116 $this->get_converted_http_link('/test.jpg') . '"></a>', 117 ], 118 ]; 119 } 120 121 /** 122 * Convert the HTTP external test file URL to use HTTPS. 123 * 124 * Note: We *must not* use getExternalTestFileUrl with the True option 125 * here, becase it is reasonable to have only one of these set due to 126 * issues with SSL certificates. 127 * 128 * @param string $path Path to be rewritten 129 * @return string 130 */ 131 protected function get_converted_http_link($path) { 132 return preg_replace('/^http:/', 'https:', $this->getExternalTestFileUrl($path, false)); 133 } 134 135 /** 136 * Test upgrade_http_links 137 * @param string $content Example content that we'll attempt to replace. 138 * @param string $ouputregex Regex for what output we expect. 139 * @param string $expectedcontent What content we are expecting afterwards. 140 * @dataProvider upgrade_http_links_provider 141 */ 142 public function test_upgrade_http_links($content, $ouputregex, $expectedcontent) { 143 global $DB; 144 145 $this->resetAfterTest(); 146 $this->expectOutputRegex($ouputregex); 147 148 $finder = new tool_httpreplace_url_finder_test(); 149 150 $generator = $this->getDataGenerator(); 151 $course = $generator->create_course((object) [ 152 'summary' => $content, 153 ]); 154 155 $finder->upgrade_http_links(); 156 157 $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); 158 $this->assertStringContainsString($expectedcontent, $summary); 159 } 160 161 /** 162 * Data provider for test_http_link_stats 163 */ 164 public function http_link_stats_provider() { 165 global $CFG; 166 // Get the http url, since the default test wwwroot is https. 167 $wwwrootdomain = 'www.example.com'; 168 $wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot); 169 $testdomain = $this->get_converted_http_link(''); 170 return [ 171 "Test image from an available site so shouldn't be reported" => [ 172 "content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">', 173 "domain" => $testdomain, 174 "expectedcount" => 0, 175 ], 176 "Link that is from this site shouldn't be reported" => [ 177 "content" => '<img src="' . $wwwroothttp . '/logo.png">', 178 "domain" => $wwwrootdomain, 179 "expectedcount" => 0, 180 ], 181 "Unavailable, but https shouldn't be reported" => [ 182 "content" => '<img src="https://intentionally.unavailable/logo.png">', 183 "domain" => 'intentionally.unavailable', 184 "expectedcount" => 0, 185 ], 186 "Unavailable image should be reported" => [ 187 "content" => '<img src="http://intentionally.unavailable/link1.jpg">', 188 "domain" => 'intentionally.unavailable', 189 "expectedcount" => 1, 190 ], 191 "Unavailable object should be reported" => [ 192 "content" => '<object data="http://intentionally.unavailable/file.swf">', 193 "domain" => 'intentionally.unavailable', 194 "expectedcount" => 1, 195 ], 196 "Link should not be reported" => [ 197 "content" => '<a href="http://intentionally.unavailable/page.php">Link</a>', 198 "domain" => 'intentionally.unavailable', 199 "expectedcount" => 0, 200 ], 201 "Text should not be reported" => [ 202 "content" => 'http://intentionally.unavailable/page.php', 203 "domain" => 'intentionally.unavailable', 204 "expectedcount" => 0, 205 ], 206 ]; 207 } 208 209 /** 210 * Test http_link_stats 211 * @param string $content Example content that we'll attempt to replace. 212 * @param string $domain The domain we will check was replaced. 213 * @param string $expectedcount Number of urls from that domain that we expect to be replaced. 214 * @dataProvider http_link_stats_provider 215 */ 216 public function test_http_link_stats($content, $domain, $expectedcount) { 217 $this->resetAfterTest(); 218 219 $finder = new tool_httpreplace_url_finder_test(); 220 221 $generator = $this->getDataGenerator(); 222 $course = $generator->create_course((object) [ 223 'summary' => $content, 224 ]); 225 226 $results = $finder->http_link_stats(); 227 228 $this->assertEquals($expectedcount, $results[$domain] ?? 0); 229 } 230 231 /** 232 * Test links and text are not changed 233 */ 234 public function test_links_and_text() { 235 global $DB; 236 237 $this->resetAfterTest(); 238 $this->expectOutputRegex('/^$/'); 239 240 $finder = new tool_httpreplace_url_finder_test(); 241 242 $generator = $this->getDataGenerator(); 243 $course = $generator->create_course((object) [ 244 'summary' => '<a href="http://intentionally.unavailable/page.php">Link</a> http://other.unavailable/page.php', 245 ]); 246 247 $results = $finder->http_link_stats(); 248 $this->assertCount(0, $results); 249 250 $finder->upgrade_http_links(); 251 252 $results = $finder->http_link_stats(); 253 $this->assertCount(0, $results); 254 255 $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); 256 $this->assertStringContainsString('http://intentionally.unavailable/page.php', $summary); 257 $this->assertStringContainsString('http://other.unavailable/page.php', $summary); 258 $this->assertStringNotContainsString('https://intentionally.unavailable', $summary); 259 $this->assertStringNotContainsString('https://other.unavailable', $summary); 260 } 261 262 /** 263 * If we have an http wwwroot then we shouldn't report it. 264 */ 265 public function test_httpwwwroot() { 266 global $DB, $CFG; 267 268 $this->resetAfterTest(); 269 $CFG->wwwroot = preg_replace('/^https:/', 'http:', $CFG->wwwroot); 270 $this->expectOutputRegex('/^$/'); 271 272 $finder = new tool_httpreplace_url_finder_test(); 273 274 $generator = $this->getDataGenerator(); 275 $course = $generator->create_course((object) [ 276 'summary' => '<img src="' . $CFG->wwwroot . '/image.png">', 277 ]); 278 279 $results = $finder->http_link_stats(); 280 $this->assertCount(0, $results); 281 282 $finder->upgrade_http_links(); 283 $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); 284 $this->assertStringContainsString($CFG->wwwroot, $summary); 285 } 286 287 /** 288 * Test that links in excluded tables are not replaced 289 */ 290 public function test_upgrade_http_links_excluded_tables() { 291 $this->resetAfterTest(); 292 293 set_config('test_upgrade_http_links', '<img src="http://somesite/someimage.png" />'); 294 295 $finder = new tool_httpreplace_url_finder_test(); 296 ob_start(); 297 $results = $finder->upgrade_http_links(); 298 $output = ob_get_contents(); 299 ob_end_clean(); 300 $this->assertTrue($results); 301 $this->assertStringNotContainsString('https://somesite', $output); 302 $testconf = get_config('core', 'test_upgrade_http_links'); 303 $this->assertStringContainsString('http://somesite', $testconf); 304 $this->assertStringNotContainsString('https://somesite', $testconf); 305 } 306 307 /** 308 * Test renamed domains 309 */ 310 public function test_renames() { 311 global $DB, $CFG; 312 $this->resetAfterTest(); 313 $this->expectOutputRegex('/UPDATE/'); 314 315 $renames = [ 316 'example.com' => 'secure.example.com', 317 ]; 318 319 set_config('renames', json_encode($renames), 'tool_httpsreplace'); 320 321 $finder = new tool_httpreplace_url_finder_test(); 322 323 $generator = $this->getDataGenerator(); 324 $course = $generator->create_course((object) [ 325 'summary' => '<script src="http://example.com/test.js"><img src="http://EXAMPLE.COM/someimage.png">', 326 ]); 327 328 $results = $finder->http_link_stats(); 329 $this->assertCount(0, $results); 330 331 $finder->upgrade_http_links(); 332 333 $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); 334 $this->assertStringContainsString('https://secure.example.com', $summary); 335 $this->assertStringNotContainsString('http://example.com', $summary); 336 $this->assertEquals('<script src="https://secure.example.com/test.js">' . 337 '<img src="https://secure.example.com/someimage.png">', $summary); 338 } 339 340 /** 341 * When there are many different pieces of contents from the same site, we should only run replace once 342 */ 343 public function test_multiple() { 344 global $DB; 345 $this->resetAfterTest(); 346 $original1 = ''; 347 $expected1 = ''; 348 $original2 = ''; 349 $expected2 = ''; 350 for ($i = 0; $i < 15; $i++) { 351 $original1 .= '<img src="http://example.com/image' . $i . '.png">'; 352 $expected1 .= '<img src="https://example.com/image' . $i . '.png">'; 353 $original2 .= '<img src="http://example.com/image' . ($i + 15 ) . '.png">'; 354 $expected2 .= '<img src="https://example.com/image' . ($i + 15) . '.png">'; 355 } 356 $finder = new tool_httpreplace_url_finder_test(); 357 358 $generator = $this->getDataGenerator(); 359 $course1 = $generator->create_course((object) ['summary' => $original1]); 360 $course2 = $generator->create_course((object) ['summary' => $original2]); 361 362 ob_start(); 363 $finder->upgrade_http_links(); 364 $output = ob_get_contents(); 365 ob_end_clean(); 366 367 // Make sure everything is replaced. 368 $summary1 = $DB->get_field('course', 'summary', ['id' => $course1->id]); 369 $this->assertEquals($expected1, $summary1); 370 $summary2 = $DB->get_field('course', 'summary', ['id' => $course2->id]); 371 $this->assertEquals($expected2, $summary2); 372 373 // Make sure only one UPDATE statment was called. 374 $this->assertEquals(1, preg_match_all('/UPDATE/', $output)); 375 } 376 377 /** 378 * Test the tool when the column name is a reserved word in SQL (in this case 'where') 379 */ 380 public function test_reserved_words() { 381 global $DB; 382 383 $this->resetAfterTest(); 384 $this->expectOutputRegex('/UPDATE/'); 385 386 // Create a table with a field that is a reserved SQL word. 387 $dbman = $DB->get_manager(); 388 $table = new \xmldb_table('reserved_words_temp'); 389 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 390 $table->add_field('where', XMLDB_TYPE_TEXT, null, null, null, null, null); 391 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 392 $dbman->create_table($table); 393 394 // Insert a record with an <img> in this table and run tool. 395 $content = '<img src="http://example.com/image.png">'; 396 $expectedcontent = '<img src="https://example.com/image.png">'; 397 $columnamequoted = $dbman->generator->getEncQuoted('where'); 398 $DB->execute("INSERT INTO {reserved_words_temp} ($columnamequoted) VALUES (?)", [$content]); 399 400 $finder = new tool_httpreplace_url_finder_test(); 401 $finder->upgrade_http_links(); 402 403 $record = $DB->get_record('reserved_words_temp', []); 404 $this->assertStringContainsString($expectedcontent, $record->where); 405 406 $dbman->drop_table($table); 407 } 408 } 409 410 /** 411 * Class tool_httpreplace_url_finder_test for testing replace tool without calling curl 412 * 413 * @package tool_httpsreplace 414 * @copyright 2017 Marina Glancy 415 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 416 */ 417 class tool_httpreplace_url_finder_test extends \tool_httpsreplace\url_finder { 418 /** 419 * Check if url is available (check hardcoded for unittests) 420 * 421 * @param string $url 422 * @return bool 423 */ 424 protected function check_domain_availability($url) { 425 return !preg_match('|\.unavailable/$|', $url); 426 } 427 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body