���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/httpsreplace.tar
���ѧ٧ѧ�
cli/url_replace.php 0000644 00000006344 15152204710 0010325 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * url_replace cli script. Examines DB for non-https src or data links, and lists broken ones or replaces all links. * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define('CLI_SCRIPT', true); require(__DIR__ . '/../../../../config.php'); require_once($CFG->libdir.'/clilib.php'); list($options, $unrecognized) = cli_get_params( array( 'help' => false, 'list' => false, 'replace' => false, 'confirm' => false, ), array( 'h' => 'help', 'l' => 'list', 'r' => 'replace', ) ); if ($unrecognized) { $unrecognized = implode("\n ", $unrecognized); cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2); } if ($options['help'] || (!$options['list'] && !$options['replace'])) { $help = "Examines DB for non-https src or data links, and lists broken links or replaces all links. Options: -h, --help Print out this help -l, --list List of http (not https) urls on a site in the DB that would become broken. -r, --replace List of http (not https) urls on a site in the DB that would become broken. --confirm Replaces http urls with https across a site's content. Example: \$ sudo -u www-data /usr/bin/php admin/tool/httpsreplace/cli/url_replace.php --list \n"; echo $help; exit(0); } if (!$DB->replace_all_text_supported()) { echo $OUTPUT->notification(get_string('notimplemented', 'tool_httpsreplace')); exit(1); } if (!is_https()) { echo $OUTPUT->notification(get_string('httpwarning', 'tool_httpsreplace'), 'warning'); echo "\n"; } if ($options['replace']) { if ($options['confirm']) { $urlfinder = new \tool_httpsreplace\url_finder(); $urlfinder->upgrade_http_links(); } else { echo "Once this is tool run, changes made can't be reverted. \n" . "A complete backup should be made before running this script. \n\n" . "There is a low risk that the wrong content will be replaced, introducing problems. \n" . "If you are sure you want to continue, add --confirm\n\n"; } } else { $urlfinder = new \tool_httpsreplace\url_finder(); $results = $urlfinder->http_link_stats(); asort($results); $fp = fopen('php://stdout', 'w'); fputcsv($fp, ['clientsite', 'httpdomain', 'urlcount']); foreach ($results as $domain => $count) { fputcsv($fp, [$SITE->shortname, $domain, $count]); } fclose($fp); } tests/httpsreplace_test.php 0000644 00000043262 15152204710 0012160 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * HTTPS find and replace Tests * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace tool_httpsreplace; defined('MOODLE_INTERNAL') || die(); /** * Tests the httpsreplace tool. * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class httpsreplace_test extends \advanced_testcase { /** * Data provider for test_upgrade_http_links */ public function upgrade_http_links_provider() { global $CFG; // Get the http url, since the default test wwwroot is https. $wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot); return [ "Test image from another site should be replaced" => [ "content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">', "outputregex" => '/UPDATE/', "expectedcontent" => '<img src="' . $this->get_converted_http_link('/test.jpg') . '">', ], "Test object from another site should be replaced" => [ "content" => '<object data="' . $this->getExternalTestFileUrl('/test.swf', false) . '">', "outputregex" => '/UPDATE/', "expectedcontent" => '<object data="' . $this->get_converted_http_link('/test.swf') . '">', ], "Test image from a site with international name should be replaced" => [ "content" => '<img src="http://中国互联网络信息中心.中国/logosy/201706/W01.png">', "outputregex" => '/UPDATE/', "expectedcontent" => '<img src="https://中国互联网络信息中心.中国/logosy/201706/W01.png">', ], "Link that is from this site should be replaced" => [ "content" => '<img src="' . $wwwroothttp . '/logo.png">', "outputregex" => '/UPDATE/', "expectedcontent" => '<img src="' . $CFG->wwwroot . '/logo.png">', ], "Link that is from this site, https new so doesn't need replacing" => [ "content" => '<img src="' . $CFG->wwwroot . '/logo.png">', "outputregex" => '/^$/', "expectedcontent" => '<img src="' . $CFG->wwwroot . '/logo.png">', ], "Unavailable image should be replaced" => [ "content" => '<img src="http://intentionally.unavailable/link1.jpg">', "outputregex" => '/UPDATE/', "expectedcontent" => '<img src="https://intentionally.unavailable/link1.jpg">', ], "Https content that has an http url as a param should not be replaced" => [ "content" => '<img src="https://anothersite.com?param=http://asdf.com">', "outputregex" => '/^$/', "expectedcontent" => '<img src="https://anothersite.com?param=http://asdf.com">', ], "Search for params should be case insensitive" => [ "content" => '<object DATA="' . $this->getExternalTestFileUrl('/test.swf', false) . '">', "outputregex" => '/UPDATE/', "expectedcontent" => '<object DATA="' . $this->get_converted_http_link('/test.swf') . '">', ], "URL should be case insensitive" => [ "content" => '<object data="HTTP://some.site/path?query">', "outputregex" => '/UPDATE/', "expectedcontent" => '<object data="https://some.site/path?query">', ], "More params should not interfere" => [ "content" => '<img alt="A picture" src="' . $this->getExternalTestFileUrl('/test.png', false) . '" width="1”><p style="font-size: \'20px\'"></p>', "outputregex" => '/UPDATE/', "expectedcontent" => '<img alt="A picture" src="' . $this->get_converted_http_link('/test.png') . '" width="1”><p style="font-size: \'20px\'"></p>', ], "Broken URL should not be changed" => [ "content" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">', "outputregex" => '/^$/', "expectedcontent" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">', ], "Link URL should not be changed" => [ "content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' . $this->getExternalTestFileUrl('/test.png', false) . '</a>', "outputregex" => '/^$/', "expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' . $this->getExternalTestFileUrl('/test.png', false) . '</a>', ], "Test image from another site should be replaced but link should not" => [ "content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '"></a>', "outputregex" => '/UPDATE/', "expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' . $this->get_converted_http_link('/test.jpg') . '"></a>', ], ]; } /** * Convert the HTTP external test file URL to use HTTPS. * * Note: We *must not* use getExternalTestFileUrl with the True option * here, becase it is reasonable to have only one of these set due to * issues with SSL certificates. * * @param string $path Path to be rewritten * @return string */ protected function get_converted_http_link($path) { return preg_replace('/^http:/', 'https:', $this->getExternalTestFileUrl($path, false)); } /** * Test upgrade_http_links * @param string $content Example content that we'll attempt to replace. * @param string $ouputregex Regex for what output we expect. * @param string $expectedcontent What content we are expecting afterwards. * @dataProvider upgrade_http_links_provider */ public function test_upgrade_http_links($content, $ouputregex, $expectedcontent) { global $DB; $this->resetAfterTest(); $this->expectOutputRegex($ouputregex); $finder = new tool_httpreplace_url_finder_mock(); $generator = $this->getDataGenerator(); $course = $generator->create_course((object) [ 'summary' => $content, ]); $finder->upgrade_http_links(); $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); $this->assertStringContainsString($expectedcontent, $summary); } /** * Data provider for test_http_link_stats */ public function http_link_stats_provider() { global $CFG; // Get the http url, since the default test wwwroot is https. $wwwrootdomain = 'www.example.com'; $wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot); $testdomain = $this->get_converted_http_link(''); return [ "Test image from an available site so shouldn't be reported" => [ "content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">', "domain" => $testdomain, "expectedcount" => 0, ], "Link that is from this site shouldn't be reported" => [ "content" => '<img src="' . $wwwroothttp . '/logo.png">', "domain" => $wwwrootdomain, "expectedcount" => 0, ], "Unavailable, but https shouldn't be reported" => [ "content" => '<img src="https://intentionally.unavailable/logo.png">', "domain" => 'intentionally.unavailable', "expectedcount" => 0, ], "Unavailable image should be reported" => [ "content" => '<img src="http://intentionally.unavailable/link1.jpg">', "domain" => 'intentionally.unavailable', "expectedcount" => 1, ], "Unavailable object should be reported" => [ "content" => '<object data="http://intentionally.unavailable/file.swf">', "domain" => 'intentionally.unavailable', "expectedcount" => 1, ], "Link should not be reported" => [ "content" => '<a href="http://intentionally.unavailable/page.php">Link</a>', "domain" => 'intentionally.unavailable', "expectedcount" => 0, ], "Text should not be reported" => [ "content" => 'http://intentionally.unavailable/page.php', "domain" => 'intentionally.unavailable', "expectedcount" => 0, ], ]; } /** * Test http_link_stats * @param string $content Example content that we'll attempt to replace. * @param string $domain The domain we will check was replaced. * @param string $expectedcount Number of urls from that domain that we expect to be replaced. * @dataProvider http_link_stats_provider */ public function test_http_link_stats($content, $domain, $expectedcount) { $this->resetAfterTest(); $finder = new tool_httpreplace_url_finder_mock(); $generator = $this->getDataGenerator(); $course = $generator->create_course((object) [ 'summary' => $content, ]); $results = $finder->http_link_stats(); $this->assertEquals($expectedcount, $results[$domain] ?? 0); } /** * Test links and text are not changed */ public function test_links_and_text() { global $DB; $this->resetAfterTest(); $this->expectOutputRegex('/^$/'); $finder = new tool_httpreplace_url_finder_mock(); $generator = $this->getDataGenerator(); $course = $generator->create_course((object) [ 'summary' => '<a href="http://intentionally.unavailable/page.php">Link</a> http://other.unavailable/page.php', ]); $results = $finder->http_link_stats(); $this->assertCount(0, $results); $finder->upgrade_http_links(); $results = $finder->http_link_stats(); $this->assertCount(0, $results); $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); $this->assertStringContainsString('http://intentionally.unavailable/page.php', $summary); $this->assertStringContainsString('http://other.unavailable/page.php', $summary); $this->assertStringNotContainsString('https://intentionally.unavailable', $summary); $this->assertStringNotContainsString('https://other.unavailable', $summary); } /** * If we have an http wwwroot then we shouldn't report it. */ public function test_httpwwwroot() { global $DB, $CFG; $this->resetAfterTest(); $CFG->wwwroot = preg_replace('/^https:/', 'http:', $CFG->wwwroot); $this->expectOutputRegex('/^$/'); $finder = new tool_httpreplace_url_finder_mock(); $generator = $this->getDataGenerator(); $course = $generator->create_course((object) [ 'summary' => '<img src="' . $CFG->wwwroot . '/image.png">', ]); $results = $finder->http_link_stats(); $this->assertCount(0, $results); $finder->upgrade_http_links(); $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); $this->assertStringContainsString($CFG->wwwroot, $summary); } /** * Test that links in excluded tables are not replaced */ public function test_upgrade_http_links_excluded_tables() { $this->resetAfterTest(); set_config('test_upgrade_http_links', '<img src="http://somesite/someimage.png" />'); $finder = new tool_httpreplace_url_finder_mock(); ob_start(); $results = $finder->upgrade_http_links(); $output = ob_get_contents(); ob_end_clean(); $this->assertTrue($results); $this->assertStringNotContainsString('https://somesite', $output); $testconf = get_config('core', 'test_upgrade_http_links'); $this->assertStringContainsString('http://somesite', $testconf); $this->assertStringNotContainsString('https://somesite', $testconf); } /** * Test renamed domains */ public function test_renames() { global $DB, $CFG; $this->resetAfterTest(); $this->expectOutputRegex('/UPDATE/'); $renames = [ 'example.com' => 'secure.example.com', ]; set_config('renames', json_encode($renames), 'tool_httpsreplace'); $finder = new tool_httpreplace_url_finder_mock(); $generator = $this->getDataGenerator(); $course = $generator->create_course((object) [ 'summary' => '<script src="http://example.com/test.js"><img src="http://EXAMPLE.COM/someimage.png">', ]); $results = $finder->http_link_stats(); $this->assertCount(0, $results); $finder->upgrade_http_links(); $summary = $DB->get_field('course', 'summary', ['id' => $course->id]); $this->assertStringContainsString('https://secure.example.com', $summary); $this->assertStringNotContainsString('http://example.com', $summary); $this->assertEquals('<script src="https://secure.example.com/test.js">' . '<img src="https://secure.example.com/someimage.png">', $summary); } /** * When there are many different pieces of contents from the same site, we should only run replace once */ public function test_multiple() { global $DB; $this->resetAfterTest(); $original1 = ''; $expected1 = ''; $original2 = ''; $expected2 = ''; for ($i = 0; $i < 15; $i++) { $original1 .= '<img src="http://example.com/image' . $i . '.png">'; $expected1 .= '<img src="https://example.com/image' . $i . '.png">'; $original2 .= '<img src="http://example.com/image' . ($i + 15 ) . '.png">'; $expected2 .= '<img src="https://example.com/image' . ($i + 15) . '.png">'; } $finder = new tool_httpreplace_url_finder_mock(); $generator = $this->getDataGenerator(); $course1 = $generator->create_course((object) ['summary' => $original1]); $course2 = $generator->create_course((object) ['summary' => $original2]); ob_start(); $finder->upgrade_http_links(); $output = ob_get_contents(); ob_end_clean(); // Make sure everything is replaced. $summary1 = $DB->get_field('course', 'summary', ['id' => $course1->id]); $this->assertEquals($expected1, $summary1); $summary2 = $DB->get_field('course', 'summary', ['id' => $course2->id]); $this->assertEquals($expected2, $summary2); // Make sure only one UPDATE statment was called. $this->assertEquals(1, preg_match_all('/UPDATE/', $output)); } /** * Test the tool when the column name is a reserved word in SQL (in this case 'where') */ public function test_reserved_words() { global $DB; $this->resetAfterTest(); $this->expectOutputRegex('/UPDATE/'); // Create a table with a field that is a reserved SQL word. $dbman = $DB->get_manager(); $table = new \xmldb_table('reserved_words_temp'); $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); $table->add_field('where', XMLDB_TYPE_TEXT, null, null, null, null, null); $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); $dbman->create_table($table); // Insert a record with an <img> in this table and run tool. $content = '<img src="http://example.com/image.png">'; $expectedcontent = '<img src="https://example.com/image.png">'; $columnamequoted = $dbman->generator->getEncQuoted('where'); $DB->execute("INSERT INTO {reserved_words_temp} ($columnamequoted) VALUES (?)", [$content]); $finder = new tool_httpreplace_url_finder_mock(); $finder->upgrade_http_links(); $record = $DB->get_record('reserved_words_temp', []); $this->assertStringContainsString($expectedcontent, $record->where); $dbman->drop_table($table); } } /** * Class tool_httpreplace_url_finder_mock for testing replace tool without calling curl * * @package tool_httpsreplace * @copyright 2017 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class tool_httpreplace_url_finder_mock extends \tool_httpsreplace\url_finder { /** * Check if url is available (check hardcoded for unittests) * * @param string $url * @return bool */ protected function check_domain_availability($url) { return !preg_match('|\.unavailable/$|', $url); } } tests/behat/httpsreplace.feature 0000644 00000003017 15152204710 0013042 0 ustar 00 @tool @tool_httpsreplace Feature: View the httpsreplace report In order to switch to https As an admin I need to be able to automatically replace http links Background: Create some http links # This is a slow running feature (more than the default 30 seconds on slow environments) # so we are allowing up to 120 (factor = 4) seconds to the replacement to complete. Given I mark this test as slow setting a timeout factor of 4 And I am on site homepage And the following "courses" exist: | fullname | shortname | category | summary | | Course 1 | C1 | 0 | <img src="http://intentionally.unavailable/test.png"> <img src="http://download.moodle.org/unittest/test.jpg"> | And I log in as "admin" @javascript Scenario: Go to the HTTPS replace report screen. Make sure broken domains are reported. When I navigate to "Security > HTTP security" in site administration And I follow "HTTPS conversion tool" And I press "Continue" Then I should see "intentionally.unavailable" @javascript Scenario: Use the find and replace tool. When I navigate to "Security > HTTP security" in site administration And I follow "HTTPS conversion tool" And I press "Continue" And I set the field "I understand the risks of this operation" to "1" And I press "Perform conversion" Then I should see "intentionally.unavailable" And I should see "download.moodle.org" tool.php 0000644 00000006743 15152204710 0006241 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Search and replace http -> https throughout all texts in the whole database * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define('NO_OUTPUT_BUFFERING', true); require_once(__DIR__ . '/../../../config.php'); require_once($CFG->dirroot . '/course/lib.php'); require_once($CFG->libdir . '/adminlib.php'); admin_externalpage_setup('toolhttpsreplace'); $context = context_system::instance(); $PAGE->set_context($context); $PAGE->set_url(new moodle_url('/admin/tool/httpsreplace/index.php')); $PAGE->set_title(get_string('pageheader', 'tool_httpsreplace')); $PAGE->set_pagelayout('admin'); echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('pageheader', 'tool_httpsreplace')); if (!$DB->replace_all_text_supported()) { echo $OUTPUT->notification(get_string('notimplemented', 'tool_httpsreplace')); echo $OUTPUT->footer(); die; } if (!is_https()) { echo $OUTPUT->notification(get_string('httpwarning', 'tool_httpsreplace'), 'warning'); } $form = new \tool_httpsreplace\form(); $finder = new \tool_httpsreplace\url_finder(); $PAGE->set_cacheable(false); $progressbar = new progress_bar(); if (!$data = $form->get_data()) { echo $progressbar->create(); $results = $finder->http_link_stats($progressbar); $progressbar->update_full(100, get_string('complete', 'tool_httpsreplace')); if (empty($results)) { echo '<p>'.get_string('oktoprocede', 'tool_httpsreplace').'</p>'; } else { arsort($results); $table = new html_table(); $table->id = 'plugins-check'; $table->head = array( get_string('domain', 'tool_httpsreplace'), get_string('count', 'tool_httpsreplace'), ); $data = array(); foreach ($results as $domain => $count) { $cleandomain = format_text($domain, FORMAT_PLAIN); $data[] = [$cleandomain, $count]; } $table->data = $data; echo html_writer::table($table); echo get_string('domainexplainhelp', 'tool_httpsreplace'); } echo $OUTPUT->notification(get_string('takeabackupwarning', 'tool_httpsreplace'), 'warning'); $form->display(); } else { // Scroll to the end when finished. $PAGE->requires->js_init_code("window.scrollTo(0, document.body.scrollHeight);"); echo html_writer::tag('p', get_string('replacing', 'tool_httpsreplace')); echo $progressbar->create(); echo $OUTPUT->box_start(); $finder->upgrade_http_links($progressbar); echo $OUTPUT->box_end(); $progressbar->update_full(100, get_string('complete', 'tool_httpsreplace')); echo $OUTPUT->continue_button(new moodle_url('/admin/settings.php', ['section' => 'httpsecurity'])); } echo $OUTPUT->footer(); settings.php 0000644 00000003103 15152204710 0007107 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Link to http -> https replace script. * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; if ($hassiteconfig) { $pluginname = get_string('pluginname', 'tool_httpsreplace'); $url = $CFG->wwwroot.'/'.$CFG->admin.'/tool/httpsreplace/index.php'; $ADMIN->add('security', new admin_externalpage('toolhttpsreplace', $pluginname, $url, 'moodle/site:config', true)); $httpsreplaceurl = $CFG->wwwroot.'/'.$CFG->admin.'/tool/httpsreplace/index.php'; $ADMIN->locate('httpsecurity')->add( new admin_setting_heading( 'tool_httpsreplaceheader', new lang_string('pluginname', 'tool_httpsreplace'), new lang_string('toolintro', 'tool_httpsreplace', $httpsreplaceurl) ) ); } index.php 0000644 00000003664 15152204710 0006372 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Search and replace http -> https throughout all texts in the whole database * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(__DIR__ . '/../../../config.php'); require_once($CFG->libdir . '/adminlib.php'); admin_externalpage_setup('toolhttpsreplace'); $context = context_system::instance(); $PAGE->set_context($context); $PAGE->set_url(new moodle_url('/admin/tool/httpsreplace/index.php')); $PAGE->set_title(get_string('pageheader', 'tool_httpsreplace')); $PAGE->set_pagelayout('admin'); echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('pageheader', 'tool_httpsreplace')); if (!$DB->replace_all_text_supported()) { echo $OUTPUT->notification(get_string('notimplemented', 'tool_httpsreplace')); echo $OUTPUT->footer(); die; } if (!is_https()) { echo $OUTPUT->notification(get_string('httpwarning', 'tool_httpsreplace'), 'warning'); } echo '<p>'.get_string('domainexplain', 'tool_httpsreplace').'</p>'; echo '<p>'.page_doc_link(get_string('doclink', 'tool_httpsreplace')).'</p>'; echo $OUTPUT->continue_button(new moodle_url('/admin/tool/httpsreplace/tool.php')); echo $OUTPUT->footer(); version.php 0000644 00000002240 15152204710 0006735 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Version details. * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2022111800; // Requires this Moodle version. $plugin->component = 'tool_httpsreplace'; // Full name of the plugin (used for diagnostics). classes/privacy/provider.php 0000644 00000002764 15152204710 0012227 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Privacy Subsystem implementation for tool_httpsreplace. * * @package tool_httpsreplace * @copyright 2018 Zig Tan <zig@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace tool_httpsreplace\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for tool_httpsreplace implementing null_provider. * * @copyright 2018 Zig Tan <zig@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason() : string { return 'privacy:metadata'; } } classes/form.php 0000644 00000003451 15152204710 0007655 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Site wide http -> https search-replace form. * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace tool_httpsreplace; defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/formslib.php"); /** * Site wide http -> https search-replace form. * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class form extends \moodleform { /** * Define the form. */ public function definition() { $mform = $this->_form; $mform->addElement('header', 'confirmhdr', get_string('confirm')); $mform->setExpanded('confirmhdr', true); $mform->addElement('checkbox', 'sure', get_string('disclaimer', 'tool_httpsreplace')); $mform->addRule('sure', get_string('required'), 'required', null, 'client'); $mform->disable_form_change_checker(); $this->add_action_buttons(false, get_string('doit', 'tool_httpsreplace')); } } classes/url_finder.php 0000644 00000023576 15152204710 0011055 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * url_finder class definition. * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace tool_httpsreplace; use database_column_info; use progress_bar; defined('MOODLE_INTERNAL') || die(); /** * Examines DB for non-https src or data links * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class url_finder { /** * Returns a hash of what hosts are referred to over http and would need to be changed. * * @param progress_bar $progress Progress bar keeping track of this process. * @return array Hash of domains with number of references as the value. */ public function http_link_stats($progress = null) { return $this->process(false, $progress); } /** * Changes all resources referred to over http to https. * * @param progress_bar $progress Progress bar keeping track of this process. * @return bool True upon success */ public function upgrade_http_links($progress = null) { return $this->process(true, $progress); } /** * Replace http domains with https equivalent, with two types of exceptions * for less straightforward swaps. * * @param string $table * @param database_column_info $column * @param string $domain * @param string $search search string that has prefix, protocol, domain name and one extra character, * example1: src="http://host.com/ * example2: DATA="HTTP://MYDOMAIN.EDU" * example3: src="HTTP://hello.world? * @return void */ protected function domain_swap($table, $column, $domain, $search) { global $DB; $renames = json_decode(get_config('tool_httpsreplace', 'renames'), true); if (isset($renames[$domain])) { $replace = preg_replace('|http://'.preg_quote($domain).'|i', 'https://' . $renames[$domain], $search); } else { $replace = preg_replace('|http://|i', 'https://', $search); } $DB->set_debug(true); $DB->replace_all_text($table, $column, $search, $replace); $DB->set_debug(false); } /** * Returns SQL to be used to match embedded http links in the given column * * @param string $columnname name of the column (ready to be used in the SQL query) * @return array */ protected function get_select_search_in_column($columnname) { global $DB; if ($DB->sql_regex_supported()) { // Database supports regex, use it for better match. $select = $columnname . ' ' . $DB->sql_regex() . ' ?'; $params = ["(src|data)\ *=\ *[\\\"\']http://"]; } else { // Databases without regex support should use case-insensitive LIKE. // This will have false positive matches and more results than we need, we'll have to filter them in php. $select = $DB->sql_like($columnname, '?', false); $params = ['%=%http://%']; } return [$select, $params]; } /** * Originally forked from core function db_search(). * @param bool $replacing Whether or not to replace the found urls. * @param progress_bar $progress Progress bar keeping track of this process. * @return bool|array If $replacing, return true on success. If not, return hash of http urls to number of times used. */ protected function process($replacing = false, $progress = null) { global $DB, $CFG; require_once($CFG->libdir.'/filelib.php'); // TODO: block_instances have HTML content as base64, need to decode then // search, currently just skipped. See MDL-60024. $skiptables = array( 'block_instances', 'config', 'config_log', 'config_plugins', 'events_queue', 'files', 'filter_config', 'grade_grades_history', 'grade_items_history', 'log', 'logstore_standard_log', 'repository_instance_config', 'sessions', 'upgrade_log', 'grade_categories_history', '', ); // Turn off time limits. \core_php_time_limit::raise(); if (!$tables = $DB->get_tables() ) { // No tables yet at all. return false; } $urls = array(); $numberoftables = count($tables); $tablenumber = 0; foreach ($tables as $table) { if ($progress) { $progress->update($tablenumber, $numberoftables, get_string('searching', 'tool_httpsreplace', $table)); $tablenumber++; } if (in_array($table, $skiptables)) { continue; } if ($columns = $DB->get_columns($table)) { foreach ($columns as $column) { // Only convert columns that are either text or long varchar. if ($column->meta_type == 'X' || ($column->meta_type == 'C' && $column->max_length > 255)) { $columnname = $column->name; $columnnamequoted = $DB->get_manager()->generator->getEncQuoted($columnname); list($select, $params) = $this->get_select_search_in_column($columnnamequoted); $rs = $DB->get_recordset_select($table, $select, $params, '', $columnnamequoted); $found = array(); foreach ($rs as $record) { // Regex to match src=http://etc. and data=http://etc.urls. // Standard warning on expecting regex to perfectly parse HTML // read http://stackoverflow.com/a/1732454 for more info. $regex = '#((src|data)\ *=\ *[\'\"])(http://)([^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))[\'\"]#i'; preg_match_all($regex, $record->$columnname, $match); foreach ($match[0] as $i => $fullmatch) { if (\core_text::strpos($fullmatch, $CFG->wwwroot) !== false) { continue; } $prefix = $match[1][$i]; $protocol = $match[3][$i]; $url = $protocol . $match[4][$i]; $host = \core_text::strtolower(parse_url($url, PHP_URL_HOST)); if (empty($host)) { continue; } if ($replacing) { // For replace string use: prefix, protocol, host and one extra character. $found[$prefix . \core_text::substr($url, 0, \core_text::strlen($host) + 8)] = $host; } else { $entry["table"] = $table; $entry["columnname"] = $columnname; $entry["url"] = $url; $entry["host"] = $host; $entry["raw"] = $record->$columnname; $entry["ssl"] = ''; $urls[] = $entry; } } } $rs->close(); if ($replacing) { foreach ($found as $search => $domain) { $this->domain_swap($table, $column, $domain, $search); } } } } } } if ($replacing) { rebuild_course_cache(0, true); purge_all_caches(); return true; } $domains = array_map(function ($i) { return $i['host']; }, $urls); $uniquedomains = array_unique($domains); $sslfailures = array(); foreach ($uniquedomains as $domain) { if (!$this->check_domain_availability("https://$domain/")) { $sslfailures[] = $domain; } } $results = array(); foreach ($urls as $url) { $host = $url['host']; foreach ($sslfailures as $badhost) { if ($host == $badhost) { if (!isset($results[$host])) { $results[$host] = 1; } else { $results[$host]++; } } } } return $results; } /** * Check if url is available (GET request returns 200) * * @param string $url * @return bool */ protected function check_domain_availability($url) { $curl = new \curl(); $curl->head($url); $info = $curl->get_info(); return !empty($info['http_code']) && $info['http_code'] == 200; } } lang/en/tool_httpsreplace.php 0000644 00000006476 15152204710 0012345 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Strings for component 'tool_httpsreplace' * * @package tool_httpsreplace * @copyright Copyright (c) 2016 Blackboard Inc. (http://www.blackboard.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['complete'] = 'Completed'; $string['count'] = 'Number of embedded content items'; $string['disclaimer'] = 'I understand the risks of this operation'; $string['doclink'] = 'HTTPS conversion tool'; $string['doit'] = 'Perform conversion'; $string['domain'] = 'Problematic domain'; $string['domainexplain'] = 'When a site is moved from HTTP to HTTPS, all embeded HTTP content will stop working. This tool allows you to automatically convert HTTP content to HTTPS. Before performing the conversion, content will be scanned to find any URLs which may not work after conversion. You may want to check each one has HTTPS available, or find alternative resources.'; $string['domainexplainhelp'] = 'These domains are found in your content, but do not appear to support HTTPS content. After switching to HTTPS, the content included from these sites will no longer display within Moodle for users with secure modern browsers. It is possible that these sites are temporarily or permanently unavailable and will not work with either security setting. Proceed only after reviewing these results and determining if this externally-hosted content is non-essential. Note: This content would no longer work upon switching to HTTPS anyway.'; $string['httpwarning'] = 'This instance is still running on HTTP. You can still run this tool and external content will be changed to HTTPS, but internal content will remain on HTTP. You will need to run this script again after switching to HTTPS to convert internal content.'; $string['notimplemented'] = 'Sorry, this feature is not implemented in your database driver.'; $string['oktoprocede'] = 'The scan finds no issues with your content. You can proceed to upgrade any HTTP content to use HTTPS.'; $string['pageheader'] = 'Upgrade externally-hosted content URLs to HTTPS'; $string['pluginname'] = 'HTTPS conversion tool'; $string['replacing'] = 'Replacing HTTP content with HTTPS...'; $string['searching'] = 'Searching {$a}'; $string['takeabackupwarning'] = 'Warning: After running this tool, changes cannot be reverted. It is recommended that a site backup is made before proceeding, as there is a small risk of wrong content being replaced.'; $string['toolintro'] = 'If you are planning on converting your site to HTTPS, you can use the <a href="{$a}">HTTPS conversion tool</a> to convert your embedded content to HTTPS.'; $string['privacy:metadata'] = 'The HTTPS conversion tool plugin does not store any personal data.';
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0.01 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�