/** * Redirects the user to another page, after printing a notice. * * This function calls the OUTPUT redirect method, echo's the output and then dies to ensure nothing else happens. * * <strong>Good practice:</strong> You should call this method before starting page * output by using any of the OUTPUT methods. * * @param moodle_url|string $url A moodle_url to redirect to. Strings are not to be trusted! * @param string $message The message to display to the user * @param int $delay The delay before redirecting * @throws moodle_exception */ function redirect($url, $message = '', $delay = -1) { global $OUTPUT, $PAGE, $CFG; if (CLI_SCRIPT or AJAX_SCRIPT) { // This is wrong - developers should not use redirect in these scripts but it should not be very likely. throw new moodle_exception('redirecterrordetected', 'error'); } // Prevent debug errors - make sure context is properly initialised. if ($PAGE) { $PAGE->set_context(null); $PAGE->set_pagelayout('redirect'); // No header and footer needed. $PAGE->set_title(get_string('pageshouldredirect', 'moodle')); } if ($url instanceof moodle_url) { $url = $url->out(false); } $debugdisableredirect = false; do { if (defined('DEBUGGING_PRINTED')) { // Some debugging already printed, no need to look more. $debugdisableredirect = true; break; } if (core_useragent::is_msword()) { // Clicking a URL from MS Word sends a request to the server without cookies. If that // causes a redirect Word will open a browser pointing the new URL. If not, the URL that // was clicked is opened. Because the request from Word is without cookies, it almost // always results in a redirect to the login page, even if the user is logged in in their // browser. This is not what we want, so prevent the redirect for requests from Word. $debugdisableredirect = true; break; } if (empty($CFG->debugdisplay) or empty($CFG->debug)) { // No errors should be displayed. break; } if (!function_exists('error_get_last') or !($lasterror = error_get_last())) { break; } if (!($lasterror['type'] & $CFG->debug)) { // Last error not interesting. break; } // Watch out here, @hidden() errors are returned from error_get_last() too. if (headers_sent()) { // We already started printing something - that means errors likely printed. $debugdisableredirect = true; break; } if (ob_get_level() and ob_get_contents()) { // There is something waiting to be printed, hopefully it is the errors, // but it might be some error hidden by @ too - such as the timezone mess from setup.php. $debugdisableredirect = true; break; } } while (false); // Technically, HTTP/1.1 requires Location: header to contain the absolute path. // (In practice browsers accept relative paths - but still, might as well do it properly.) // This code turns relative into absolute. if (!preg_match('|^[a-z]+:|', $url)) { // Get host name http://www.wherever.com. $hostpart = preg_replace('|^(.*?[^:/])/.*$|', '$1', $CFG->wwwroot); if (preg_match('|^/|', $url)) { // URLs beginning with / are relative to web server root so we just add them in. $url = $hostpart . $url; } else { // URLs not beginning with / are relative to path of current script, so add that on. $url = $hostpart . preg_replace('|\\?.*$|', '', me()) . '/../' . $url; } // Replace all ..s. while (true) { $newurl = preg_replace('|/(?!\\.\\.)[^/]*/\\.\\./|', '/', $url); if ($newurl == $url) { break; } $url = $newurl; } } // Sanitise url - we can not rely on moodle_url or our URL cleaning // because they do not support all valid external URLs. $url = preg_replace('/[\\x00-\\x1F\\x7F]/', '', $url); $url = str_replace('"', '%22', $url); $encodedurl = preg_replace("/\\&(?![a-zA-Z0-9#]{1,8};)/", "&", $url); $encodedurl = preg_replace('/^.*href="([^"]*)".*$/', "\\1", clean_text('<a href="' . $encodedurl . '" />', FORMAT_HTML)); $url = str_replace('&', '&', $encodedurl); if (!empty($message)) { if ($delay === -1 || !is_numeric($delay)) { $delay = 3; } $message = clean_text($message); } else { $message = get_string('pageshouldredirect'); $delay = 0; } // Make sure the session is closed properly, this prevents problems in IIS // and also some potential PHP shutdown issues. \core\session\manager::write_close(); if ($delay == 0 && !$debugdisableredirect && !headers_sent()) { // 302 might not work for POST requests, 303 is ignored by obsolete clients. @header($_SERVER['SERVER_PROTOCOL'] . ' 303 See Other'); @header('Location: ' . $url); echo bootstrap_renderer::plain_redirect_message($encodedurl); exit; } // Include a redirect message, even with a HTTP redirect, because that is recommended practice. if ($PAGE) { $CFG->docroot = false; // To prevent the link to moodle docs from being displayed on redirect page. echo $OUTPUT->redirect_message($encodedurl, $message, $delay, $debugdisableredirect); exit; } else { echo bootstrap_renderer::early_redirect_message($encodedurl, $message, $delay); exit; } }
/** * Redirects the user to another page, after printing a notice * * This function calls the OUTPUT redirect method, echo's the output * and then dies to ensure nothing else happens. * * <strong>Good practice:</strong> You should call this method before starting page * output by using any of the OUTPUT methods. * * @param moodle_url|string $url A moodle_url to redirect to. Strings are not to be trusted! * @param string $message The message to display to the user * @param int $delay The delay before redirecting * @return void - does not return! */ function redirect($url, $message='', $delay=-1) { global $OUTPUT, $PAGE, $SESSION, $CFG; if (CLI_SCRIPT or AJAX_SCRIPT) { // this is wrong - developers should not use redirect in these scripts, // but it should not be very likely throw new moodle_exception('redirecterrordetected', 'error'); } // prevent debug errors - make sure context is properly initialised if ($PAGE) { $PAGE->set_context(null); $PAGE->set_pagelayout('redirect'); // No header and footer needed } if ($url instanceof moodle_url) { $url = $url->out(false); } $debugdisableredirect = false; do { if (defined('DEBUGGING_PRINTED')) { // some debugging already printed, no need to look more $debugdisableredirect = true; break; } if (empty($CFG->debugdisplay) or empty($CFG->debug)) { // no errors should be displayed break; } if (!function_exists('error_get_last') or !$lasterror = error_get_last()) { break; } if (!($lasterror['type'] & $CFG->debug)) { //last error not interesting break; } // watch out here, @hidden() errors are returned from error_get_last() too if (headers_sent()) { //we already started printing something - that means errors likely printed $debugdisableredirect = true; break; } if (ob_get_level() and ob_get_contents()) { // there is something waiting to be printed, hopefully it is the errors, // but it might be some error hidden by @ too - such as the timezone mess from setup.php $debugdisableredirect = true; break; } } while (false); // Technically, HTTP/1.1 requires Location: header to contain the absolute path. // (In practice browsers accept relative paths - but still, might as well do it properly.) // This code turns relative into absolute. if (!preg_match('|^[a-z]+:|', $url)) { // Get host name http://www.wherever.com $hostpart = preg_replace('|^(.*?[^:/])/.*$|', '$1', $CFG->wwwroot); if (preg_match('|^/|', $url)) { // URLs beginning with / are relative to web server root so we just add them in $url = $hostpart.$url; } else { // URLs not beginning with / are relative to path of current script, so add that on. $url = $hostpart.preg_replace('|\?.*$|','',me()).'/../'.$url; } // Replace all ..s while (true) { $newurl = preg_replace('|/(?!\.\.)[^/]*/\.\./|', '/', $url); if ($newurl == $url) { break; } $url = $newurl; } } // Sanitise url - we can not rely on moodle_url or our URL cleaning // because they do not support all valid external URLs $url = preg_replace('/[\x00-\x1F\x7F]/', '', $url); $url = str_replace('"', '%22', $url); $encodedurl = preg_replace("/\&(?![a-zA-Z0-9#]{1,8};)/", "&", $url); $encodedurl = preg_replace('/^.*href="([^"]*)".*$/', "\\1", clean_text('<a href="'.$encodedurl.'" />', FORMAT_HTML)); $url = str_replace('&', '&', $encodedurl); if (!empty($message)) { if ($delay === -1 || !is_numeric($delay)) { $delay = 3; } $message = clean_text($message); } else { $message = get_string('pageshouldredirect'); $delay = 0; } if (defined('MDL_PERF') || (!empty($CFG->perfdebug) and $CFG->perfdebug > 7)) { if (defined('MDL_PERFTOLOG') && !function_exists('register_shutdown_function')) { $perf = get_performance_info(); error_log("PERF: " . $perf['txt']); } } if ($delay == 0 && !$debugdisableredirect && !headers_sent()) { // workaround for IIS bug http://support.microsoft.com/kb/q176113/ if (session_id()) { session_get_instance()->write_close(); } //302 might not work for POST requests, 303 is ignored by obsolete clients. @header($_SERVER['SERVER_PROTOCOL'] . ' 303 See Other'); @header('Location: '.$url); echo bootstrap_renderer::plain_redirect_message($encodedurl); exit; } // Include a redirect message, even with a HTTP redirect, because that is recommended practice. if ($PAGE) { $CFG->docroot = false; // to prevent the link to moodle docs from being displayed on redirect page. echo $OUTPUT->redirect_message($encodedurl, $message, $delay, $debugdisableredirect); exit; } else { echo bootstrap_renderer::early_redirect_message($encodedurl, $message, $delay); exit; } }