/** * Convert data attribute to a string * * @param \core_renderer $output * @return string */ protected function data_to_string(\core_renderer $output) { if ($this->data instanceof \Exception) { $info = get_exception_info($this->data); return $output->fatal_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo); } else { return json_encode($this->data); } }
/** * Silent exception handler. * * @return callable exception handler */ public static function get_exception_handler() { return function ($ex) { $info = get_exception_info($ex); $logerrmsg = "enrol_paypal IPN exception handler: " . $info->message; if (debugging('', DEBUG_NORMAL)) { $logerrmsg .= ' Debug: ' . $info->debuginfo . "\n" . format_backtrace($info->backtrace, true); } error_log($logerrmsg); exit(0); }; }
/** * upgrade logging functions */ function upgrade_handle_exception($ex, $plugin = null) { global $CFG; // rollback everything, we need to log all upgrade problems abort_all_db_transactions(); $info = get_exception_info($ex); // First log upgrade error upgrade_log(UPGRADE_LOG_ERROR, $plugin, 'Exception: ' . get_class($ex), $info->message, $info->backtrace); // Always turn on debugging - admins need to know what is going on set_debugging(DEBUG_DEVELOPER, true); default_exception_handler($ex, true, $plugin); }
function judge_all_unjudged() { while ($task = get_one_unjudged_task()) { verbose(cli_heading('TASK: ' . $task->id, true)); verbose('Judging...'); try { $task = onlinejudge_judge($task); verbose("Successfully judged: {$task->status}"); } catch (Exception $e) { $info = get_exception_info($e); $errmsg = "Judged inner level exception handler: " . $info->message . ' Debug: ' . $info->debuginfo . "\n" . format_backtrace($info->backtrace, true); cli_problem($errmsg); // Continue to get next unjudged task } } }
/** * Call an external function validating all params/returns correctly. * * Note that an external function may modify the state of the current page, so this wrapper * saves and restores tha PAGE and COURSE global variables before/after calling the external function. * * @param string $function A webservice function name. * @param array $args Params array (named params) * @param boolean $ajaxonly If true, an extra check will be peformed to see if ajax is required. * @return array containing keys for error (bool), exception and data. */ public static function call_external_function($function, $args, $ajaxonly = false) { global $PAGE, $COURSE, $CFG, $SITE; require_once $CFG->libdir . "/pagelib.php"; $externalfunctioninfo = self::external_function_info($function); $currentpage = $PAGE; $currentcourse = $COURSE; $response = array(); try { // Taken straight from from setup.php. if (!empty($CFG->moodlepageclass)) { if (!empty($CFG->moodlepageclassfile)) { require_once $CFG->moodlepageclassfile; } $classname = $CFG->moodlepageclass; } else { $classname = 'moodle_page'; } $PAGE = new $classname(); $COURSE = clone $SITE; if ($ajaxonly && !$externalfunctioninfo->allowed_from_ajax) { throw new moodle_exception('servicenotavailable', 'webservice'); } // Do not allow access to write or delete webservices as a public user. if ($externalfunctioninfo->loginrequired) { if (defined('NO_MOODLE_COOKIES') && NO_MOODLE_COOKIES && !PHPUNIT_TEST) { throw new moodle_exception('servicenotavailable', 'webservice'); } if (!isloggedin()) { throw new moodle_exception('servicenotavailable', 'webservice'); } else { require_sesskey(); } } // Validate params, this also sorts the params properly, we need the correct order in the next part. $callable = array($externalfunctioninfo->classname, 'validate_parameters'); $params = call_user_func($callable, $externalfunctioninfo->parameters_desc, $args); // Execute - gulp! $callable = array($externalfunctioninfo->classname, $externalfunctioninfo->methodname); $result = call_user_func_array($callable, array_values($params)); // Validate the return parameters. if ($externalfunctioninfo->returns_desc !== null) { $callable = array($externalfunctioninfo->classname, 'clean_returnvalue'); $result = call_user_func($callable, $externalfunctioninfo->returns_desc, $result); } $response['error'] = false; $response['data'] = $result; } catch (Exception $e) { $exception = get_exception_info($e); unset($exception->a); if (!debugging('', DEBUG_DEVELOPER)) { unset($exception->debuginfo); unset($exception->backtrace); } $response['error'] = true; $response['exception'] = $exception; // Do not process the remaining requests. } $PAGE = $currentpage; $COURSE = $currentcourse; return $response; }
/** * Extend the LTI services through the ltisource plugins * * @param stdClass $data LTI request data * @return bool * @throws coding_exception */ function lti_extend_lti_services($data) { $plugins = get_plugin_list_with_function('ltisource', $data->messagetype); if (!empty($plugins)) { try { // There can only be one if (count($plugins) > 1) { throw new coding_exception('More than one ltisource plugin handler found'); } $callback = current($plugins); call_user_func($callback, $data); } catch (moodle_exception $e) { $error = $e->getMessage(); if (debugging('', DEBUG_DEVELOPER)) { $error .= ' ' . format_backtrace(get_exception_info($e)->backtrace); } $responsexml = lti_get_response_xml('failure', $error, $data->messageid, $data->messagetype); header('HTTP/1.0 400 bad request'); echo $responsexml->asXML(); } return true; } return false; }
/** * Log an LTI response. * * @param string $responsexml The response XML * @param Exception $e If there was an exception, pass that too */ function lti_log_response($responsexml, $e = null) { if ($tempdir = make_temp_directory('mod_lti', false)) { if ($tempfile = tempnam($tempdir, 'mod_lti_response' . date('YmdHis'))) { $content = ''; if ($e instanceof Exception) { $info = get_exception_info($e); $content .= "Exception:\n"; $content .= "Message: {$info->message}\n"; $content .= "Debug info: {$info->debuginfo}\n"; $content .= "Backtrace:\n"; $content .= format_backtrace($info->backtrace, true); $content .= "\n"; } $content .= "Response XML:\n"; $content .= $responsexml; file_put_contents($tempfile, $content); chmod($tempfile, 0644); } } }
function RWSEHdlr($r_ex) { abort_all_db_transactions(); $r_inf = get_exception_info($r_ex); $r_msg = "\r\n-- Exception occurred --"; $r_msg .= "\r\nmessage: {$r_inf->message}"; $r_msg .= "\r\nerrorcode: {$r_inf->errorcode}"; $r_msg .= "\r\nfile: " . $r_ex->getFile(); $r_msg .= "\r\nline: " . $r_ex->getLine(); $r_msg .= "\r\nlink: {$r_inf->link}"; $r_msg .= "\r\nmoreinfourl: {$r_inf->moreinfourl}"; $r_msg .= "\r\na: {$r_inf->a}"; $r_msg .= "\r\ndebuginfo: {$r_inf->debuginfo}\r\n"; RWSELog($r_msg); RWSELog("\r\nstacktrace: " . $r_ex->getTraceAsString()); RWSSErr("2112,{$r_inf->errorcode}"); }
/** * Echo an exception message encapsulated in XML. * * @param \Exception $exception The exception that was thrown */ public function handle(\Exception $exception) { $message = $exception->getMessage(); // Add the exception backtrace for developers. if (debugging('', DEBUG_DEVELOPER)) { $message .= "\n" . format_backtrace(get_exception_info($exception)->backtrace, true); } // Switch to response. $type = str_replace('Request', 'Response', $this->type); // Build the appropriate xml. $response = lti_get_response_xml('failure', $message, $this->id, $type); $xml = $response->asXML(); // Log the request if necessary. if ($this->log) { lti_log_response($xml, $exception); } echo $xml; }
/** * Test if get_exception_info() removes file system paths. */ public function test_exception_info_removes_serverpaths() { global $CFG; // This doesn't test them all possible ones, but these are set for unit tests. $cfgnames = array('dataroot', 'dirroot', 'tempdir', 'cachedir', 'localcachedir'); $fixture = ''; $expected = ''; foreach ($cfgnames as $cfgname) { if (!empty($CFG->{$cfgname})) { $fixture .= $CFG->{$cfgname} . ' '; $expected .= "[{$cfgname}] "; } } $exception = new moodle_exception('generalexceptionmessage', 'error', '', $fixture, $fixture); $exceptioninfo = get_exception_info($exception); $this->assertContains($expected, $exceptioninfo->message, 'Exception message does not contain system paths'); $this->assertContains($expected, $exceptioninfo->debuginfo, 'Exception debug info does not contain system paths'); }
// Do not allow access to write or delete webservices as a public user. if ($externalfunctioninfo->loginrequired) { if (!isloggedin()) { error_log('This external function is not available to public users. Failed to call "' . $methodname . '"'); throw new moodle_exception('servicenotavailable', 'webservice'); } } // Validate params, this also sorts the params properly, we need the correct order in the next part. $callable = array($externalfunctioninfo->classname, 'validate_parameters'); $params = call_user_func($callable, $externalfunctioninfo->parameters_desc, $args); // Execute - gulp! $callable = array($externalfunctioninfo->classname, $externalfunctioninfo->methodname); $result = call_user_func_array($callable, array_values($params)); $response['error'] = false; $response['data'] = $result; $responses[$index] = $response; } catch (Exception $e) { $jsonexception = get_exception_info($e); unset($jsonexception->a); if (!debugging('', DEBUG_DEVELOPER)) { unset($jsonexception->debuginfo); unset($jsonexception->backtrace); } $response['error'] = true; $response['exception'] = $jsonexception; $responses[$index] = $response; // Do not process the remaining requests. break; } } echo json_encode($responses);
/** * Silent exception handler. * * @param Exception $ex * @return void - does not return. Terminates execution! */ function mod_paypal_ipn_exception_handler($ex) { $info = get_exception_info($ex); $logerrmsg = "mod_paypal IPN exception handler: " . $info->message; if (debugging('', DEBUG_NORMAL)) { $logerrmsg .= ' Debug: ' . $info->debuginfo . "\n" . format_backtrace($info->backtrace, true); } error_log($logerrmsg); exit(0); }
function lockdownbrowser_MonitorExceptionHandler($ex) { abort_all_db_transactions(); $info = get_exception_info($ex); $msg = "\r\n-- Exception occurred --" . "\r\nmessage: {$info->message}" . "\r\nerrorcode: {$info->errorcode}" . "\r\nbacktrace: {$info->backtrace}" . "\r\nlink: {$info->link}" . "\r\nmoreinfourl: {$info->moreinfourl}" . "\r\na: {$info->a}" . "\r\ndebuginfo: {$info->debuginfo}\r\n"; lockdownbrowser_MonitorLog($msg); lockdownbrowser_MonitorLog("\r\nstacktrace: " . $ex->getTraceAsString()); lockdownbrowser_MonitorServiceError(2003, "A Moodle or PHP server exception occurred: {$info->errorcode}"); }
/** * Wrapper to call {@link get_exception_info()}. * * @param Exception $ex An exception. * @return stdClass of information. */ public function get_exception_info($ex) { try { throw $ex; } catch (moodle_exception $e) { return get_exception_info($e); } }
/** * Adds and upgrades the selected plugins * * @param array $ingredients * @param string $path Path to the ingredient type file system * @param SimpleXMLElement $xml * @return array Problems during the ingredients deployment */ public function deploy_ingredients($ingredients, $path, SimpleXMLElement $xml) { // Using the $ingredients array keys to maintain coherence with the main deployment method $problems = array(); $pluginman = plugin_manager::instance(); $plugintypespaths = get_plugin_types(); $this->get_flavour_info($xml); foreach ($ingredients as $selection) { // [0] => ingredienttype, [1] => ingredientname $ingredientdata = explode('/', $selection); $type = $ingredientdata[0]; $ingredient = $ingredientdata[1]; if (empty($this->branches[$type]->branches[$ingredient])) { $problems[$selection]['pluginnotfound'] = $selection; continue; } $ingredientdata = $this->branches[$type]->branches[$ingredient]; // Adapter to the restrictions array if (!empty($ingredientdata->restrictions)) { $problems[$selection] = $ingredientdata->restrictions; continue; } if (empty($xml->{$type}) || empty($xml->{$type}->{$ingredient})) { $problems[$selection]['pluginnotfound'] = $selection; continue; } // Deploy then $ingredientpath = $plugintypespaths[$type] . '/' . $ingredient; // Remove old dir if present if (file_exists($ingredientpath)) { // Report if the old plugin directory can't be removed if (!$this->unlink($ingredientpath)) { $problems[$selection]['plugincantremove'] = $selection; continue; } } // Copy the new contents where the flavour says $tmppath = $path . '/' . $xml->{$type}->{$ingredient}->path; if (!$this->copy($tmppath, $ingredientpath)) { debugging('From : ' . $tmppath . ' To: ' . $ingredientpath); $problems[$selection]['plugincopyerror'] = $selection; } } // Execute the moodle upgrade process try { foreach ($plugintypespaths as $type => $location) { upgrade_plugins($type, 'flavours_print_upgrade_void', 'flavours_print_upgrade_void', false); } } catch (Exception $ex) { abort_all_db_transactions(); $info = get_exception_info($ex); upgrade_log(UPGRADE_LOG_ERROR, $ex->module, 'Exception: ' . get_class($ex), $info->message, $info->backtrace); } return $problems; }
/** * Default exception handler, uncaught exceptions are equivalent to error() in 1.9 and earlier * * @param Exception $ex * @return void -does not return. Terminates execution! */ function default_exception_handler($ex) { global $CFG, $DB, $OUTPUT, $USER, $FULLME, $SESSION, $PAGE; // detect active db transactions, rollback and log as error abort_all_db_transactions(); if ($ex instanceof required_capability_exception && !CLI_SCRIPT && !AJAX_SCRIPT && !empty($CFG->autologinguests) && !empty($USER->autologinguest)) { $SESSION->wantsurl = qualified_me(); redirect(get_login_url()); } $info = get_exception_info($ex); if (debugging('', DEBUG_MINIMAL)) { $logerrmsg = "Default exception handler: " . $info->message . ' Debug: ' . $info->debuginfo . "\n" . format_backtrace($info->backtrace, true); error_log($logerrmsg); } if (is_early_init($info->backtrace)) { echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo, $info->errorcode); } else { try { if ($DB) { // If you enable db debugging and exception is thrown, the print footer prints a lot of rubbish $DB->set_debug(0); } echo $OUTPUT->fatal_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo); } catch (Exception $out_ex) { // default exception handler MUST not throw any exceptions!! // the problem here is we do not know if page already started or not, we only know that somebody messed up in outputlib or theme // so we just print at least something instead of "Exception thrown without a stack frame in Unknown on line 0":-( if (CLI_SCRIPT or AJAX_SCRIPT) { // just ignore the error and send something back using the safest method echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo, $info->errorcode); } else { echo bootstrap_renderer::early_error_content($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo); $outinfo = get_exception_info($out_ex); echo bootstrap_renderer::early_error_content($outinfo->message, $outinfo->moreinfourl, $outinfo->link, $outinfo->backtrace, $outinfo->debuginfo); } } } exit(1); // General error code }
function xmldb_block_lockdownbrowser_install() { global $DB; global $CFG; $enable_log = FALSE; // set TRUE to enable logging to temp file $install_log = "ldb_install.log"; $warning_settings = "<p>lockdownbrowser block install warning: could not migrate quiz settings from legacy lockdown module</p>"; $warning_files = "<p>lockdownbrowser block install warning: could not undo changes to quiz module made by legacy lockdown module</p>"; $block_settings_table = "block_lockdownbrowser_sett"; $module_settings_table = "lockdown_settings"; $quiz_table = "quiz"; $quiz_file = "{$CFG->dirroot}/mod/quiz/attempt.php"; $quiz_module_folder = "{$CFG->dirroot}/mod/quiz"; $quiz_backup_folders = "{$CFG->dataroot}/lockdownquiz-[0-1][0-9][0-3][0-9]-[0-1][0-9][0-5][0-9]/backup"; if ($CFG->version >= 2011120500.0) { // Moodle 2.2 $quiz_backup_files = array("attempt.php", "lib.php", "mod_form.php", "review.php", "view.php", "accessmanager.php"); } else { $quiz_backup_files = array("accessrules.php", "attempt.php", "lib.php", "mod_form.php", "review.php"); } $debug_info = "* start: " . date("m-d-Y H:i:s") . "\r\n"; $exception_msg = ""; $migrate_settings = FALSE; $undo_quiz_changes = FALSE; try { $debug_info .= "* migrating settings from legacy ldb module to ldb block\r\n"; $ok = TRUE; $dbman = $DB->get_manager(); $table = new xmldb_table($module_settings_table); $migrate_settings = $dbman->table_exists($table); if (!$migrate_settings) { $debug_info .= "* no need to migrate settings: table {$module_settings_table} does not exist\r\n"; } if ($migrate_settings) { $table = new xmldb_table($block_settings_table); $ok = $dbman->table_exists($table); if (!$ok) { $debug_info .= "* error: table {$block_settings_table} does not exist\r\n"; } } if ($migrate_settings && $ok) { $records = $DB->get_records($module_settings_table); $ok = $records !== FALSE || count($records) != 0; if (!$ok) { $debug_info .= "* error: table {$module_settings_table} has no records\r\n"; } } if ($migrate_settings && $ok) { foreach ($records as $modset) { if ($modset->attempts == 0 && $modset->reviews == 0) { continue; } // not LDB quiz, nothing to migrate $quiz = $DB->get_record($quiz_table, array("id" => $modset->quizid)); if ($quiz === FALSE) { continue; } // quiz gone, no need to migrate $blkset = $DB->get_record($block_settings_table, array("quizid" => $quiz->id)); if ($blkset !== FALSE) { continue; } // quiz settings already migrated $blkset = new stdClass(); $blkset->course = $quiz->course; $blkset->quizid = $quiz->id; $blkset->attempts = 0; $blkset->reviews = 0; $blkset->password = $modset->password; $blkset->monitor = ""; $ok = $DB->insert_record($block_settings_table, $blkset); if (!$ok) { $debug_info .= "* error: could not insert record into table {$block_settings_table}\r\n"; break; } } } if ($migrate_settings && $ok) { $debug_info .= "* settings migration succeeded\r\n"; } } catch (Exception $e) { $info = get_exception_info($e); $msg = "\r\nmessage: {$info->message}" . "\r\nerrorcode: {$info->errorcode}" . "\r\nbacktrace: {$info->backtrace}" . "\r\nlink: {$info->link}" . "\r\nmoreinfourl: {$info->moreinfourl}" . "\r\na: {$info->a}" . "\r\ndebuginfo: {$info->debuginfo}\r\n" . "\r\nstacktrace: " . $e->getTraceAsString(); $debug_info .= "* exception occurred: {$msg}\r\n"; $ok = FALSE; } if ($migrate_settings && !$ok) { $exception_msg .= $warning_settings; } try { $debug_info .= "* restoring file changes made to quiz module by legacy ldb module\r\n"; if (false) { $undo_quiz_changes = TRUE; } else { if (is_readable($quiz_file)) { $contents = file_get_contents($quiz_file); if ($contents !== FALSE) { $pos = strpos($contents, "## LockDown"); $undo_quiz_changes = $pos !== FALSE; } } } if (!$undo_quiz_changes) { $debug_info .= "* no need to restore file changes: could not find edit marker string\r\n"; } if ($undo_quiz_changes) { $folders = glob($quiz_backup_folders, GLOB_ONLYDIR); $ok = is_array($folders) && count($folders) > 0 && strlen($folders[0]) > 0; if (!$ok) { $debug_info .= "* error: could not find quiz backup folder\r\n"; } } if ($undo_quiz_changes && $ok) { if (count($folders) == 1) { $src_folder = $folders[0]; } else { // find most recent folder $latest_time = 0; $latest_path = ""; foreach ($folders as $path) { $time = filectime($path); $ok = $time !== FALSE; if (!$ok) { $debug_info .= "* error: could not determine which quiz backup folder to use\r\n"; break; } if ($time > $latest) { $latest_time = $time; $latest_path = $path; } } if ($ok) { $src_folder = $latest_path; $debug_info .= "* restoring from quiz backup folder {$src_folder}\r\n"; } } } if ($undo_quiz_changes && $ok) { $dest_folder = $quiz_module_folder; $ok = is_dir($dest_folder); if (!$ok) { $debug_info .= "* error: could not find quiz module folder {$dest_folder}\r\n"; } } if ($undo_quiz_changes && $ok) { foreach ($quiz_backup_files as $file) { $ok2 = copy("{$src_folder}/{$file}", "{$dest_folder}/{$file}"); if (!$ok2) { $ok = FALSE; $debug_info .= "* error: could not copy {$file} from {$src_folder} to {$dest_folder}\r\n"; } } } if ($undo_quiz_changes && $ok) { $debug_info .= "* restoring file changes succeeded\r\n"; } } catch (Exception $e) { $info = get_exception_info($e); $msg = "\r\nmessage: {$info->message}" . "\r\nerrorcode: {$info->errorcode}" . "\r\nbacktrace: {$info->backtrace}" . "\r\nlink: {$info->link}" . "\r\nmoreinfourl: {$info->moreinfourl}" . "\r\na: {$info->a}" . "\r\ndebuginfo: {$info->debuginfo}\r\n" . "\r\nstacktrace: " . $e->getTraceAsString(); $debug_info .= "* exception occurred: {$msg}\r\n"; $ok = FALSE; } if ($undo_quiz_changes && !$ok) { $exception_msg .= $warning_files; } // write debug file $debug_info .= "* end\r\n"; if ($enable_log) { if (isset($CFG->tempdir)) { $path = "{$CFG->tempdir}/{$install_log}"; } else { $path = "{$CFG->dataroot}/temp/{$install_log}"; } $handle = fopen($path, "wb"); if ($handle !== FALSE) { fwrite($handle, $debug_info, strlen($debug_info)); fclose($handle); } } // inform user if migration failed if (strlen($exception_msg) > 0) { throw new moodle_exception($exception_msg, "block_lockdownbrowser"); } }