diff --git a/admin/environment.xml b/admin/environment.xml index 55a1aee8825..13c205a665e 100644 --- a/admin/environment.xml +++ b/admin/environment.xml @@ -3729,6 +3729,8 @@ + + diff --git a/admin/index.php b/admin/index.php index 943fea85259..c8c9015d188 100644 --- a/admin/index.php +++ b/admin/index.php @@ -916,6 +916,12 @@ $showfeedbackencouragement = empty($CFG->enableuserfeedback); // Check if the service and support content setting is enabled or not. $servicesandsupportcontent = !isset($CFG->showservicesandsupportcontent) || $CFG->showservicesandsupportcontent; +// Check whether the XML-RPC protocol is enabled or not. +require_once($CFG->libdir . '/environmentlib.php'); +$result = new environment_results('custom_checks'); +$result = check_xmlrpc_usage($result); +$xmlrpcwarning = !is_null($result) ? get_string($result->getFeedbackStr(), 'admin') : ''; + admin_externalpage_setup('adminnotifications'); $output = $PAGE->get_renderer('core', 'admin'); @@ -924,4 +930,5 @@ echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisp $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb, $registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir, $mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent, - $showcampaigncontent, $showfeedbackencouragement, $servicesandsupportcontent); + $showcampaigncontent, $showfeedbackencouragement, $servicesandsupportcontent, + $xmlrpcwarning); diff --git a/admin/mnet/access_control.php b/admin/mnet/access_control.php index a1223012b77..edb3b06d322 100644 --- a/admin/mnet/access_control.php +++ b/admin/mnet/access_control.php @@ -117,6 +117,7 @@ if ($form = data_submitted() and confirm_sesskey()) { } echo $OUTPUT->header(); +echo $OUTPUT->render(mnet_get_deprecation_notice()); // Explain echo $OUTPUT->box(get_string('ssoacldescr','mnet')); diff --git a/admin/mnet/index.php b/admin/mnet/index.php index fff93869420..5e0240b8582 100644 --- a/admin/mnet/index.php +++ b/admin/mnet/index.php @@ -81,6 +81,7 @@ $hosts = $DB->get_records_select('mnet_host', "id <> ? AND deleted = 0", array($CFG->mnet_localhost_id), 'wwwroot ASC'); echo $OUTPUT->header(); + echo $OUTPUT->render(mnet_get_deprecation_notice()); ?>
diff --git a/admin/mnet/peers.php b/admin/mnet/peers.php index 49fd346493a..348a6243f86 100644 --- a/admin/mnet/peers.php +++ b/admin/mnet/peers.php @@ -51,6 +51,8 @@ if ($hostid && $DB->get_field('mnet_host', 'deleted', array('id' => $hostid)) != $PAGE->set_url('/admin/mnet/peers.php'); admin_externalpage_setup($adminsection); +$deprecatenotify = mnet_get_deprecation_notice(); + if (!extension_loaded('openssl')) { print_error('requiresopenssl', 'mnet'); } @@ -90,6 +92,7 @@ if ($formdata = $simpleform->get_data()) { $formdata->oldpublickey = $mnet_peer->public_key; // set this so we can confirm on form post without having to recreate the mnet_peer object $reviewform->set_data($mnet_peer); echo $OUTPUT->header(); + echo $OUTPUT->render($deprecatenotify); echo $OUTPUT->box_start(); $reviewform->display(); echo $OUTPUT->box_end(); @@ -177,6 +180,7 @@ if ($formdata = $reviewform->get_data()) { } } else if ($reviewform->is_submitted()) { // submitted, but errors echo $OUTPUT->header(); + echo $OUTPUT->render($deprecatenotify); echo $OUTPUT->box_start(); $reviewform->display(); echo $OUTPUT->box_end(); @@ -187,6 +191,7 @@ if ($formdata = $reviewform->get_data()) { // normal flow - just display all hosts with links echo $OUTPUT->header(); +echo $OUTPUT->render($deprecatenotify); $hosts = mnet_get_hosts(true); // print the table to display the register all hosts setting diff --git a/admin/mnet/tabs.php b/admin/mnet/tabs.php index 0107d758285..bf0c8ff3e3a 100644 --- a/admin/mnet/tabs.php +++ b/admin/mnet/tabs.php @@ -44,4 +44,5 @@ if (isset($mnet_peer->id) && $mnet_peer->id > 0) { } else { $tabs[] = new tabobject('mnetdetails', '#', $strmnetedithost, $strmnetedithost, false); } +echo $OUTPUT->render(mnet_get_deprecation_notice()); print_tabs(array($tabs), $currenttab); diff --git a/admin/mnet/trustedhosts.html b/admin/mnet/trustedhosts.html index e48a3d3b542..951e8b91852 100644 --- a/admin/mnet/trustedhosts.html +++ b/admin/mnet/trustedhosts.html @@ -1,5 +1,6 @@ header(); +echo $OUTPUT->render(mnet_get_deprecation_notice()); ?>
diff --git a/admin/renderer.php b/admin/renderer.php index cbab1a2af2e..11fa0a16da5 100644 --- a/admin/renderer.php +++ b/admin/renderer.php @@ -285,6 +285,7 @@ class core_admin_renderer extends plugin_renderer_base { * @param bool $showcampaigncontent Whether the campaign content should be visible or not. * @param bool $showfeedbackencouragement Whether the feedback encouragement content should be displayed or not. * @param bool $showservicesandsupport Whether the services and support content should be displayed or not. + * @param string $xmlrpcwarning XML-RPC deprecation warning message. * * @return string HTML to output. */ @@ -293,7 +294,8 @@ class core_admin_renderer extends plugin_renderer_base { $buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0, $themedesignermode = false, $devlibdir = false, $mobileconfigured = false, $overridetossl = false, $invalidforgottenpasswordurl = false, $croninfrequent = false, - $showcampaigncontent = false, bool $showfeedbackencouragement = false, bool $showservicesandsupport = false) { + $showcampaigncontent = false, bool $showfeedbackencouragement = false, bool $showservicesandsupport = false, + $xmlrpcwarning = '') { global $CFG; $output = ''; @@ -317,6 +319,7 @@ class core_admin_renderer extends plugin_renderer_base { $output .= $this->registration_warning($registered); $output .= $this->mobile_configuration_warning($mobileconfigured); $output .= $this->forgotten_password_url_warning($invalidforgottenpasswordurl); + $output .= $this->mnet_deprecation_warning($xmlrpcwarning); $output .= $this->userfeedback_encouragement($showfeedbackencouragement); $output .= $this->services_and_support_content($showservicesandsupport); $output .= $this->campaign_content($showcampaigncontent); @@ -2238,4 +2241,18 @@ class core_admin_renderer extends plugin_renderer_base { return $output; } + + /** + * Display a warning about the deprecation of Mnet. + * + * @param string $xmlrpcwarning The warning message + * @return string HTML to output. + */ + protected function mnet_deprecation_warning($xmlrpcwarning) { + if (empty($xmlrpcwarning)) { + return ''; + } + + return $this->warning($xmlrpcwarning); + } } diff --git a/admin/settings/mnet.php b/admin/settings/mnet.php index 9bb5b15dd4a..f853938c50a 100644 --- a/admin/settings/mnet.php +++ b/admin/settings/mnet.php @@ -49,6 +49,8 @@ $ADMIN->add('mnet', new admin_externalpage('trustedhosts', new lang_string('trus if (isset($CFG->mnet_dispatcher_mode) and $CFG->mnet_dispatcher_mode !== 'off') { $profilefields = new admin_settingpage('mnetprofilefields', new lang_string('profilefields', 'mnet'), 'moodle/site:config'); + $profilefields->add(new admin_setting_heading('mnetprofilefields/xmlrpcmnet', '', + $OUTPUT->render(mnet_get_deprecation_notice()))); $ADMIN->add('mnet', $profilefields); $fields = mnet_profile_field_options(); diff --git a/auth/mnet/settings.php b/auth/mnet/settings.php index b7aa4a4b59a..fae2ab9f4c4 100644 --- a/auth/mnet/settings.php +++ b/auth/mnet/settings.php @@ -27,6 +27,11 @@ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { require_once($CFG->dirroot.'/lib/outputlib.php'); + $notify = new \core\output\notification(get_string('xmlrpcmnetauthenticationenabled', 'admin'), + \core\output\notification::NOTIFY_WARNING); + $settings->add(new admin_setting_heading('auth_mnet/xmlrpcmnet', '', + $OUTPUT->render($notify))); + // Introductory explanation. $settings->add(new admin_setting_heading('auth_mnet/pluginname', '', new lang_string('auth_mnetdescription', 'auth_mnet'))); diff --git a/lang/en/admin.php b/lang/en/admin.php index 4bdd1f9d9c6..63be120f158 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -1524,6 +1524,10 @@ $string['warningiconvbuggy'] = 'Your version of the iconv library does not suppo $string['webproxy'] = 'Web proxy'; $string['webproxyinfo'] = 'Fill in the following options if your Moodle server cannot access the internet directly. Internet access is required for the download of environment data, language packs, RSS feeds, timezones, etc.
The PHP cURL extension is highly recommended.'; $string['xmlrpcrecommended'] = 'The XMLRPC extension is useful for web services and Moodle networking.'; +$string['xmlrpcmaharaenabled'] = 'It has been detected that the Mahara ePortfolio is enabled on your site. This feature relies on the PHP XML-RPC extension which is no longer supported by PHP.'; +$string['xmlrpcmnetauthenticationenabled'] = 'It has been detected that the MNet authentication is enabled on your site. This feature relies on the PHP XML-RPC extension which is no longer supported by PHP.'; +$string['xmlrpcmnetenabled'] = 'It has been detected that the Moodle Networking is enabled on your site. This feature relies on the PHP XML-RPC extension which is no longer supported by PHP.'; +$string['xmlrpcwebserviceenabled'] = 'It has been detected that the XML-RPC Web Service protocol is enabled on your site. This feature relies on the PHP XML-RPC extension which is no longer supported by PHP.'; $string['yuicomboloading'] = 'YUI combo loading'; $string['ziprequired'] = 'The Zip PHP extension is now required by Moodle, info-ZIP binaries or PclZip library are not used anymore.'; $string['manageqbanks'] = 'Manage question bank plugins'; diff --git a/lib/adminlib.php b/lib/adminlib.php index 649f2b283b3..fdc812747e7 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -7138,6 +7138,11 @@ class admin_setting_manageauths extends admin_setting { } $return = $OUTPUT->heading(get_string('actauthhdr', 'auth'), 3, 'main'); + if (in_array('mnet', $authsenabled)) { + $notify = new \core\output\notification(get_string('xmlrpcmnetauthenticationenabled', 'admin'), + \core\output\notification::NOTIFY_WARNING); + $return .= $OUTPUT->render($notify); + } $return .= $OUTPUT->box_start('generalbox authsui'); $table = new html_table(); @@ -10382,16 +10387,21 @@ class admin_setting_managewebserviceprotocols extends admin_setting { $strversion = get_string('version'); $protocols_available = core_component::get_plugin_list('webservice'); - $active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols); + $activeprotocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols); ksort($protocols_available); - foreach ($active_protocols as $key=>$protocol) { + foreach ($activeprotocols as $key => $protocol) { if (empty($protocols_available[$protocol])) { - unset($active_protocols[$key]); + unset($activeprotocols[$key]); } } $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main'); + if (in_array('xmlrpc', $activeprotocols)) { + $notify = new \core\output\notification(get_string('xmlrpcwebserviceenabled', 'admin'), + \core\output\notification::NOTIFY_WARNING); + $return .= $OUTPUT->render($notify); + } $return .= $OUTPUT->box_start('generalbox webservicesui'); $table = new html_table(); @@ -10413,7 +10423,7 @@ class admin_setting_managewebserviceprotocols extends admin_setting { $version = isset($plugin->version) ? $plugin->version : ''; // hide/show link - if (in_array($protocol, $active_protocols)) { + if (in_array($protocol, $activeprotocols)) { $hideshow = ""; $hideshow .= $OUTPUT->pix_icon('t/hide', $strdisable) . ''; $displayname = "$name"; diff --git a/lib/tests/upgradelib_test.php b/lib/tests/upgradelib_test.php index 0e1ce803cd0..80851dcff6e 100644 --- a/lib/tests/upgradelib_test.php +++ b/lib/tests/upgradelib_test.php @@ -1526,4 +1526,97 @@ class upgradelib_test extends advanced_testcase { $this->assertEquals('admin_dir_usage', $result->getInfo()); $this->assertFalse($result->getStatus()); } + + /** + * Test the check_xmlrpc_usage check when the XML-RPC web service method is not set. + * + * @return void + */ + public function test_check_xmlrpc_webservice_is_not_set(): void { + global $CFG; + + $this->resetAfterTest(); + + $result = new environment_results('custom_checks'); + $this->assertNull(check_xmlrpc_usage($result)); + + $CFG->webserviceprotocols = 'rest'; + $result = new environment_results('custom_checks'); + $this->assertNull(check_xmlrpc_usage($result)); + } + + /** + * Test the check_xmlrpc_usage check when the XML-RPC web service method is set. + * + * @return void + */ + public function test_check_xmlrpc_webservice_is_set(): void { + global $CFG; + + $this->resetAfterTest(); + $CFG->webserviceprotocols = 'xmlrpc,rest'; + + $result = new environment_results('custom_checks'); + $this->assertInstanceOf(environment_results::class, check_xmlrpc_usage($result)); + $this->assertEquals('xmlrpc_webservice_usage', $result->getInfo()); + $this->assertFalse($result->getStatus()); + } + + /** + * Test the check_xmlrpc_usage check when the MNet is turned on but no host was set up. + * + * @return void + */ + public function test_check_xmlrpc_mnet_host_is_not_set(): void { + global $CFG; + + $this->resetAfterTest(); + $CFG->mnet_dispatcher_mode = 'strict'; + + $result = new environment_results('custom_checks'); + $this->assertNull(check_xmlrpc_usage($result)); + } + + /** + * Test the check_xmlrpc_usage check when the MNet is turned on and the host was set up. + * + * @return void + */ + public function test_check_xmlrpc_mnet_host_is_set(): void { + global $CFG, $DB; + + $this->resetAfterTest(); + $CFG->mnet_dispatcher_mode = 'strict'; + + // Add a mnet host. + $mnethost = new stdClass(); + $mnethost->name = 'A mnet host'; + $mnethost->public_key = 'A random public key!'; + $mnethost->id = $DB->insert_record('mnet_host', $mnethost); + + $result = new environment_results('custom_checks'); + $this->assertInstanceOf(environment_results::class, check_xmlrpc_usage($result)); + $this->assertEquals('xmlrpc_mnet_usage', $result->getInfo()); + $this->assertFalse($result->getStatus()); + } + + /** + * Test the check_xmlrpc_usage check when the MNet is turned on and the Mahara portfolios was set up. + * + * @return void + */ + public function test_check_xmlrpc_mahara_portfolios_is_set(): void { + global $CFG; + + $this->resetAfterTest(); + $CFG->mnet_dispatcher_mode = 'strict'; + + // Enable the Mahara portfolios. + \core\plugininfo\portfolio::enable_plugin('mahara', 1); + + $result = new environment_results('custom_checks'); + $this->assertInstanceOf(environment_results::class, check_xmlrpc_usage($result)); + $this->assertEquals('xmlrpc_mahara_usage', $result->getInfo()); + $this->assertFalse($result->getStatus()); + } } diff --git a/lib/upgradelib.php b/lib/upgradelib.php index f10b0a3590a..5528879f511 100644 --- a/lib/upgradelib.php +++ b/lib/upgradelib.php @@ -2732,3 +2732,55 @@ function check_admin_dir_usage(environment_results $result): ?environment_result return $result; } + +/** + * Check whether the XML-RPC protocol is enabled and warn if so. + * + * The XML-RPC protocol will be removed in a future version (4.1) as it is no longer supported by PHP. + * + * See MDL-70889 for further information. + * + * @param environment_results $result + * @return null|environment_results + */ +function check_xmlrpc_usage(environment_results $result): ?environment_results { + global $CFG; + + // Checking Web Service protocols. + if (!empty($CFG->webserviceprotocols)) { + $plugins = array_flip(explode(',', $CFG->webserviceprotocols)); + if (array_key_exists('xmlrpc', $plugins)) { + $result->setInfo('xmlrpc_webservice_usage'); + $result->setFeedbackStr('xmlrpcwebserviceenabled'); + return $result; + } + } + + if (isset($CFG->mnet_dispatcher_mode) && $CFG->mnet_dispatcher_mode == 'strict') { + // Checking Mnet hosts. + $mnethosts = mnet_get_hosts(); + if ($mnethosts) { + $actualhost = 0; + foreach ($mnethosts as $mnethost) { + if ($mnethost->id != $CFG->mnet_all_hosts_id) { + $actualhost++; + } + } + if ($actualhost > 0) { + $result->setInfo('xmlrpc_mnet_usage'); + $result->setFeedbackStr('xmlrpcmnetenabled'); + return $result; + } + } + + // Checking Mahara. + $portfolios = \core\plugininfo\portfolio::get_enabled_plugins(); + if (array_key_exists('mahara', $portfolios)) { + $result->setInfo('xmlrpc_mahara_usage'); + $result->setFeedbackStr('xmlrpcmaharaenabled'); + return $result; + } + } + + return null; +} diff --git a/mnet/environment.php b/mnet/environment.php index 236e4b65ef7..ece0387311c 100644 --- a/mnet/environment.php +++ b/mnet/environment.php @@ -145,7 +145,10 @@ class mnet_environment { set_config('openssl', implode('@@@@@@@@', $this->keypair), 'mnet'); $DB->update_record('mnet_host', $this); - error_log('New public key has been generated. It expires ' . date('Y/m/d h:i:s', $this->public_key_expires)); + if (!PHPUNIT_TEST) { + // We don't want to output this log for PHPUnit since it will make the test to fail as risky. + error_log('New public key has been generated. It expires ' . date('Y/m/d h:i:s', $this->public_key_expires)); + } } function get_private_key() { diff --git a/mnet/lib.php b/mnet/lib.php index e62fd865e94..f54f162a2fe 100644 --- a/mnet/lib.php +++ b/mnet/lib.php @@ -924,3 +924,15 @@ function mnet_strip_user($user, $fields) { } return $user; } + +/** + * Return the deprecation notice of the Mnet. + * + * @return \core\output\notification + */ +function mnet_get_deprecation_notice(): \core\output\notification { + $notice = new \core\output\notification(get_string('xmlrpcmnetenabled', 'admin'), + \core\output\notification::NOTIFY_WARNING); + + return $notice; +} diff --git a/mnet/service/enrol/index.php b/mnet/service/enrol/index.php index daa30ecc5b5..1938c6c6e7d 100644 --- a/mnet/service/enrol/index.php +++ b/mnet/service/enrol/index.php @@ -32,6 +32,7 @@ admin_externalpage_setup('mnetenrol'); $service = mnetservice_enrol::get_instance(); echo $OUTPUT->header(); +echo $OUTPUT->render(mnet_get_deprecation_notice()); echo $OUTPUT->heading_with_help(get_string('clientname', 'mnetservice_enrol'), 'clientname', 'mnetservice_enrol'); if (!$service->is_available()) {