|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00018 00030 defined('MOODLE_INTERNAL') || die(); 00031 00033 00034 define('DEBUG_NONE', 0); 00036 define('DEBUG_MINIMAL', 5); 00038 define('DEBUG_NORMAL', 15); 00040 define('DEBUG_ALL', 6143); 00042 define('DEBUG_DEVELOPER', 38911); 00043 00045 define('MEMORY_UNLIMITED', -1); 00047 define('MEMORY_STANDARD', -2); 00052 define('MEMORY_EXTRA', -3); 00054 define('MEMORY_HUGE', -4); 00055 00059 define('MATURITY_ALPHA', 50); // internals can be tested using white box techniques 00060 define('MATURITY_BETA', 100); // feature complete, ready for preview and testing 00061 define('MATURITY_RC', 150); // tested, will be released unless there are fatal bugs 00062 define('MATURITY_STABLE', 200); // ready for production deployment 00063 00067 define('ANY_VERSION', 'any'); 00068 00069 00081 class object extends stdClass {}; 00082 00094 class moodle_exception extends Exception { 00095 public $errorcode; 00096 public $module; 00097 public $a; 00098 public $link; 00099 public $debuginfo; 00100 00109 function __construct($errorcode, $module='', $link='', $a=NULL, $debuginfo=null) { 00110 if (empty($module) || $module == 'moodle' || $module == 'core') { 00111 $module = 'error'; 00112 } 00113 00114 $this->errorcode = $errorcode; 00115 $this->module = $module; 00116 $this->link = $link; 00117 $this->a = $a; 00118 $this->debuginfo = $debuginfo; 00119 00120 if (get_string_manager()->string_exists($errorcode, $module)) { 00121 $message = get_string($errorcode, $module, $a); 00122 } else { 00123 $message = $module . '/' . $errorcode; 00124 } 00125 00126 parent::__construct($message, 0); 00127 } 00128 } 00129 00140 class require_login_exception extends moodle_exception { 00141 function __construct($debuginfo) { 00142 parent::__construct('requireloginerror', 'error', '', NULL, $debuginfo); 00143 } 00144 } 00145 00152 class webservice_parameter_exception extends moodle_exception { 00158 function __construct($errorcode=null, $a = '', $debuginfo = null) { 00159 parent::__construct($errorcode, 'webservice', '', $a, $debuginfo); 00160 } 00161 } 00162 00172 class required_capability_exception extends moodle_exception { 00173 function __construct($context, $capability, $errormessage, $stringfile) { 00174 $capabilityname = get_capability_string($capability); 00175 if ($context->contextlevel == CONTEXT_MODULE and preg_match('/:view$/', $capability)) { 00176 // we can not go to mod/xx/view.php because we most probably do not have cap to view it, let's go to course instead 00177 $paranetcontext = get_context_instance_by_id(get_parent_contextid($context)); 00178 $link = get_context_url($paranetcontext); 00179 } else { 00180 $link = get_context_url($context); 00181 } 00182 parent::__construct($errormessage, $stringfile, $link, $capabilityname); 00183 } 00184 } 00185 00195 class coding_exception extends moodle_exception { 00201 function __construct($hint, $debuginfo=null) { 00202 parent::__construct('codingerror', 'debug', '', $hint, $debuginfo); 00203 } 00204 } 00205 00217 class invalid_parameter_exception extends moodle_exception { 00222 function __construct($debuginfo=null) { 00223 parent::__construct('invalidparameter', 'debug', '', null, $debuginfo); 00224 } 00225 } 00226 00233 class invalid_response_exception extends moodle_exception { 00238 function __construct($debuginfo=null) { 00239 parent::__construct('invalidresponse', 'debug', '', null, $debuginfo); 00240 } 00241 } 00242 00255 class invalid_state_exception extends moodle_exception { 00261 function __construct($hint, $debuginfo=null) { 00262 parent::__construct('invalidstatedetected', 'debug', '', $hint, $debuginfo); 00263 } 00264 } 00265 00274 class invalid_dataroot_permissions extends moodle_exception { 00279 function __construct($debuginfo = NULL) { 00280 parent::__construct('invaliddatarootpermissions', 'error', '', NULL, $debuginfo); 00281 } 00282 } 00283 00292 class file_serving_exception extends moodle_exception { 00297 function __construct($debuginfo = NULL) { 00298 parent::__construct('cannotservefile', 'error', '', NULL, $debuginfo); 00299 } 00300 } 00301 00308 function default_exception_handler($ex) { 00309 global $CFG, $DB, $OUTPUT, $USER, $FULLME, $SESSION; 00310 00311 // detect active db transactions, rollback and log as error 00312 abort_all_db_transactions(); 00313 00314 if (($ex instanceof required_capability_exception) && !CLI_SCRIPT && !AJAX_SCRIPT && !empty($CFG->autologinguests) && !empty($USER->autologinguest)) { 00315 $SESSION->wantsurl = $FULLME; 00316 redirect(get_login_url()); 00317 } 00318 00319 $info = get_exception_info($ex); 00320 00321 if (debugging('', DEBUG_MINIMAL)) { 00322 $logerrmsg = "Default exception handler: ".$info->message.' Debug: '.$info->debuginfo."\n".format_backtrace($info->backtrace, true); 00323 error_log($logerrmsg); 00324 } 00325 00326 if (is_early_init($info->backtrace)) { 00327 echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo); 00328 } else { 00329 try { 00330 if ($DB) { 00331 // If you enable db debugging and exception is thrown, the print footer prints a lot of rubbish 00332 $DB->set_debug(0); 00333 } 00334 echo $OUTPUT->fatal_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo); 00335 } catch (Exception $out_ex) { 00336 // default exception handler MUST not throw any exceptions!! 00337 // 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 00338 // so we just print at least something instead of "Exception thrown without a stack frame in Unknown on line 0":-( 00339 if (CLI_SCRIPT or AJAX_SCRIPT) { 00340 // just ignore the error and send something back using the safest method 00341 echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo); 00342 } else { 00343 echo bootstrap_renderer::early_error_content($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo); 00344 $outinfo = get_exception_info($out_ex); 00345 echo bootstrap_renderer::early_error_content($outinfo->message, $outinfo->moreinfourl, $outinfo->link, $outinfo->backtrace, $outinfo->debuginfo); 00346 } 00347 } 00348 } 00349 00350 exit(1); // General error code 00351 } 00352 00362 function default_error_handler($errno, $errstr, $errfile, $errline, $errcontext) { 00363 if ($errno == 4096) { 00364 //fatal catchable error 00365 throw new coding_exception('PHP catchable fatal error', $errstr); 00366 } 00367 return false; 00368 } 00369 00375 function abort_all_db_transactions() { 00376 global $CFG, $DB, $SCRIPT; 00377 00378 // default exception handler MUST not throw any exceptions!! 00379 00380 if ($DB && $DB->is_transaction_started()) { 00381 error_log('Database transaction aborted automatically in ' . $CFG->dirroot . $SCRIPT); 00382 // note: transaction blocks should never change current $_SESSION 00383 $DB->force_transaction_rollback(); 00384 } 00385 } 00386 00399 function is_early_init($backtrace) { 00400 $dangerouscode = array( 00401 array('function' => 'header', 'type' => '->'), 00402 array('class' => 'bootstrap_renderer'), 00403 array('file' => dirname(__FILE__).'/setup.php'), 00404 ); 00405 foreach ($backtrace as $stackframe) { 00406 foreach ($dangerouscode as $pattern) { 00407 $matches = true; 00408 foreach ($pattern as $property => $value) { 00409 if (!isset($stackframe[$property]) || $stackframe[$property] != $value) { 00410 $matches = false; 00411 } 00412 } 00413 if ($matches) { 00414 return true; 00415 } 00416 } 00417 } 00418 return false; 00419 } 00420 00434 function print_error($errorcode, $module = 'error', $link = '', $a = null, $debuginfo = null) { 00435 throw new moodle_exception($errorcode, $module, $link, $a, $debuginfo); 00436 } 00437 00443 function get_exception_info($ex) { 00444 global $CFG, $DB, $SESSION; 00445 00446 if ($ex instanceof moodle_exception) { 00447 $errorcode = $ex->errorcode; 00448 $module = $ex->module; 00449 $a = $ex->a; 00450 $link = $ex->link; 00451 $debuginfo = $ex->debuginfo; 00452 } else { 00453 $errorcode = 'generalexceptionmessage'; 00454 $module = 'error'; 00455 $a = $ex->getMessage(); 00456 $link = ''; 00457 $debuginfo = null; 00458 } 00459 00460 $backtrace = $ex->getTrace(); 00461 $place = array('file'=>$ex->getFile(), 'line'=>$ex->getLine(), 'exception'=>get_class($ex)); 00462 array_unshift($backtrace, $place); 00463 00464 // Be careful, no guarantee moodlelib.php is loaded. 00465 if (empty($module) || $module == 'moodle' || $module == 'core') { 00466 $module = 'error'; 00467 } 00468 if (function_exists('get_string_manager')) { 00469 if (get_string_manager()->string_exists($errorcode, $module)) { 00470 $message = get_string($errorcode, $module, $a); 00471 } elseif ($module == 'error' && get_string_manager()->string_exists($errorcode, 'moodle')) { 00472 // Search in moodle file if error specified - needed for backwards compatibility 00473 $message = get_string($errorcode, 'moodle', $a); 00474 } else { 00475 $message = $module . '/' . $errorcode; 00476 } 00477 } else { 00478 $message = $module . '/' . $errorcode; 00479 } 00480 00481 // Be careful, no guarantee weblib.php is loaded. 00482 if (function_exists('clean_text')) { 00483 $message = clean_text($message); 00484 } else { 00485 $message = htmlspecialchars($message); 00486 } 00487 00488 if (!empty($CFG->errordocroot)) { 00489 $errordoclink = $CFG->errordocroot . '/en/'; 00490 } else { 00491 $errordoclink = get_docs_url(); 00492 } 00493 00494 if ($module === 'error') { 00495 $modulelink = 'moodle'; 00496 } else { 00497 $modulelink = $module; 00498 } 00499 $moreinfourl = $errordoclink . 'error/' . $modulelink . '/' . $errorcode; 00500 00501 if (empty($link)) { 00502 if (!empty($SESSION->fromurl)) { 00503 $link = $SESSION->fromurl; 00504 unset($SESSION->fromurl); 00505 } else { 00506 $link = $CFG->wwwroot .'/'; 00507 } 00508 } 00509 00510 // when printing an error the continue button should never link offsite 00511 if (stripos($link, $CFG->wwwroot) === false && 00512 stripos($link, $CFG->httpswwwroot) === false) { 00513 $link = $CFG->wwwroot.'/'; 00514 } 00515 00516 $info = new stdClass(); 00517 $info->message = $message; 00518 $info->errorcode = $errorcode; 00519 $info->backtrace = $backtrace; 00520 $info->link = $link; 00521 $info->moreinfourl = $moreinfourl; 00522 $info->a = $a; 00523 $info->debuginfo = $debuginfo; 00524 00525 return $info; 00526 } 00527 00535 function get_docs_url($path=null) { 00536 global $CFG; 00537 // Check that $CFG->release has been set up, during installation it won't be. 00538 if (empty($CFG->release)) { 00539 // It's not there yet so look at version.php 00540 include($CFG->dirroot.'/version.php'); 00541 } else { 00542 // We can use $CFG->release and avoid having to include version.php 00543 $release = $CFG->release; 00544 } 00545 // Attempt to match the branch from the release 00546 if (preg_match('/^(.)\.(.)/', $release, $matches)) { 00547 // We should ALWAYS get here 00548 $branch = $matches[1].$matches[2]; 00549 } else { 00550 // We should never get here but in case we do lets set $branch to . 00551 // the smart one's will know that this is the current directory 00552 // and the smarter ones will know that there is some smart matching 00553 // that will ensure people end up at the latest version of the docs. 00554 $branch = '.'; 00555 } 00556 if (!empty($CFG->docroot)) { 00557 return $CFG->docroot . '/' . $branch . '/' . current_language() . '/' . $path; 00558 } else { 00559 return 'http://docs.moodle.org/'. $branch . '/en/' . $path; 00560 } 00561 } 00562 00570 function format_backtrace($callers, $plaintext = false) { 00571 // do not use $CFG->dirroot because it might not be available in destructors 00572 $dirroot = dirname(dirname(__FILE__)); 00573 00574 if (empty($callers)) { 00575 return ''; 00576 } 00577 00578 $from = $plaintext ? '' : '<ul style="text-align: left">'; 00579 foreach ($callers as $caller) { 00580 if (!isset($caller['line'])) { 00581 $caller['line'] = '?'; // probably call_user_func() 00582 } 00583 if (!isset($caller['file'])) { 00584 $caller['file'] = 'unknownfile'; // probably call_user_func() 00585 } 00586 $from .= $plaintext ? '* ' : '<li>'; 00587 $from .= 'line ' . $caller['line'] . ' of ' . str_replace($dirroot, '', $caller['file']); 00588 if (isset($caller['function'])) { 00589 $from .= ': call to '; 00590 if (isset($caller['class'])) { 00591 $from .= $caller['class'] . $caller['type']; 00592 } 00593 $from .= $caller['function'] . '()'; 00594 } else if (isset($caller['exception'])) { 00595 $from .= ': '.$caller['exception'].' thrown'; 00596 } 00597 $from .= $plaintext ? "\n" : '</li>'; 00598 } 00599 $from .= $plaintext ? '' : '</ul>'; 00600 00601 return $from; 00602 } 00603 00615 function ini_get_bool($ini_get_arg) { 00616 $temp = ini_get($ini_get_arg); 00617 00618 if ($temp == '1' or strtolower($temp) == 'on') { 00619 return true; 00620 } 00621 return false; 00622 } 00623 00628 function setup_validate_php_configuration() { 00629 // this must be very fast - no slow checks here!!! 00630 00631 if (ini_get_bool('register_globals')) { 00632 print_error('globalswarning', 'admin'); 00633 } 00634 if (ini_get_bool('session.auto_start')) { 00635 print_error('sessionautostartwarning', 'admin'); 00636 } 00637 if (ini_get_bool('magic_quotes_runtime')) { 00638 print_error('fatalmagicquotesruntime', 'admin'); 00639 } 00640 } 00641 00646 function initialise_cfg() { 00647 global $CFG, $DB; 00648 00649 try { 00650 if ($DB) { 00651 $localcfg = $DB->get_records_menu('config', array(), '', 'name,value'); 00652 foreach ($localcfg as $name=>$value) { 00653 if (property_exists($CFG, $name)) { 00654 // config.php settings always take precedence 00655 continue; 00656 } 00657 $CFG->{$name} = $value; 00658 } 00659 } 00660 } catch (dml_exception $e) { 00661 // most probably empty db, going to install soon 00662 } 00663 } 00664 00669 function initialise_fullme() { 00670 global $CFG, $FULLME, $ME, $SCRIPT, $FULLSCRIPT; 00671 00672 // Detect common config error. 00673 if (substr($CFG->wwwroot, -1) == '/') { 00674 print_error('wwwrootslash', 'error'); 00675 } 00676 00677 if (CLI_SCRIPT) { 00678 initialise_fullme_cli(); 00679 return; 00680 } 00681 00682 $rurl = setup_get_remote_url(); 00683 $wwwroot = parse_url($CFG->wwwroot.'/'); 00684 00685 if (empty($rurl['host'])) { 00686 // missing host in request header, probably not a real browser, let's ignore them 00687 00688 } else if (!empty($CFG->reverseproxy)) { 00689 // $CFG->reverseproxy specifies if reverse proxy server used 00690 // Used in load balancing scenarios. 00691 // Do not abuse this to try to solve lan/wan access problems!!!!! 00692 00693 } else { 00694 if (($rurl['host'] !== $wwwroot['host']) or (!empty($wwwroot['port']) and $rurl['port'] != $wwwroot['port'])) { 00695 // Explain the problem and redirect them to the right URL 00696 if (!defined('NO_MOODLE_COOKIES')) { 00697 define('NO_MOODLE_COOKIES', true); 00698 } 00699 redirect($CFG->wwwroot, get_string('wwwrootmismatch', 'error', $CFG->wwwroot), 3); 00700 } 00701 } 00702 00703 // Check that URL is under $CFG->wwwroot. 00704 if (strpos($rurl['path'], $wwwroot['path']) === 0) { 00705 $SCRIPT = substr($rurl['path'], strlen($wwwroot['path'])-1); 00706 } else { 00707 // Probably some weird external script 00708 $SCRIPT = $FULLSCRIPT = $FULLME = $ME = null; 00709 return; 00710 } 00711 00712 // $CFG->sslproxy specifies if external SSL appliance is used 00713 // (That is, the Moodle server uses http, with an external box translating everything to https). 00714 if (empty($CFG->sslproxy)) { 00715 if ($rurl['scheme'] === 'http' and $wwwroot['scheme'] === 'https') { 00716 print_error('sslonlyaccess', 'error'); 00717 } 00718 } else { 00719 if ($wwwroot['scheme'] !== 'https') { 00720 throw new coding_exception('Must use https address in wwwroot when ssl proxy enabled!'); 00721 } 00722 $rurl['scheme'] = 'https'; // make moodle believe it runs on https, squid or something else it doing it 00723 } 00724 00725 // hopefully this will stop all those "clever" admins trying to set up moodle 00726 // with two different addresses in intranet and Internet 00727 if (!empty($CFG->reverseproxy) && $rurl['host'] === $wwwroot['host']) { 00728 print_error('reverseproxyabused', 'error'); 00729 } 00730 00731 $hostandport = $rurl['scheme'] . '://' . $wwwroot['host']; 00732 if (!empty($wwwroot['port'])) { 00733 $hostandport .= ':'.$wwwroot['port']; 00734 } 00735 00736 $FULLSCRIPT = $hostandport . $rurl['path']; 00737 $FULLME = $hostandport . $rurl['fullpath']; 00738 $ME = $rurl['fullpath']; 00739 } 00740 00745 function initialise_fullme_cli() { 00746 global $CFG, $FULLME, $ME, $SCRIPT, $FULLSCRIPT; 00747 00748 // Urls do not make much sense in CLI scripts 00749 $backtrace = debug_backtrace(); 00750 $topfile = array_pop($backtrace); 00751 $topfile = realpath($topfile['file']); 00752 $dirroot = realpath($CFG->dirroot); 00753 00754 if (strpos($topfile, $dirroot) !== 0) { 00755 // Probably some weird external script 00756 $SCRIPT = $FULLSCRIPT = $FULLME = $ME = null; 00757 } else { 00758 $relativefile = substr($topfile, strlen($dirroot)); 00759 $relativefile = str_replace('\\', '/', $relativefile); // Win fix 00760 $SCRIPT = $FULLSCRIPT = $relativefile; 00761 $FULLME = $ME = null; 00762 } 00763 } 00764 00771 function setup_get_remote_url() { 00772 $rurl = array(); 00773 if (isset($_SERVER['HTTP_HOST'])) { 00774 list($rurl['host']) = explode(':', $_SERVER['HTTP_HOST']); 00775 } else { 00776 $rurl['host'] = null; 00777 } 00778 $rurl['port'] = $_SERVER['SERVER_PORT']; 00779 $rurl['path'] = $_SERVER['SCRIPT_NAME']; // Script path without slash arguments 00780 $rurl['scheme'] = (empty($_SERVER['HTTPS']) or $_SERVER['HTTPS'] === 'off' or $_SERVER['HTTPS'] === 'Off' or $_SERVER['HTTPS'] === 'OFF') ? 'http' : 'https'; 00781 00782 if (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false) { 00783 //Apache server 00784 $rurl['fullpath'] = $_SERVER['REQUEST_URI']; 00785 00786 } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'iis') !== false) { 00787 //IIS - needs a lot of tweaking to make it work 00788 $rurl['fullpath'] = $_SERVER['SCRIPT_NAME']; 00789 00790 // NOTE: ignore PATH_INFO because it is incorrectly encoded using 8bit filesystem legacy encoding in IIS 00791 // since 2.0 we rely on iis rewrite extenssion like Helicon ISAPI_rewrite 00792 // example rule: RewriteRule ^([^\?]+?\.php)(\/.+)$ $1\?file=$2 [QSA] 00793 00794 if ($_SERVER['QUERY_STRING'] != '') { 00795 $rurl['fullpath'] .= '?'.$_SERVER['QUERY_STRING']; 00796 } 00797 $_SERVER['REQUEST_URI'] = $rurl['fullpath']; // extra IIS compatibility 00798 00799 /* NOTE: following servers are not fully tested! */ 00800 00801 } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false) { 00802 //lighttpd - not officially supported 00803 $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded 00804 00805 } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false) { 00806 //nginx - not officially supported 00807 if (!isset($_SERVER['SCRIPT_NAME'])) { 00808 die('Invalid server configuration detected, please try to add "fastcgi_param SCRIPT_NAME $fastcgi_script_name;" to the nginx server configuration.'); 00809 } 00810 $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded 00811 00812 } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'cherokee') !== false) { 00813 //cherokee - not officially supported 00814 $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded 00815 00816 } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'zeus') !== false) { 00817 //zeus - not officially supported 00818 $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded 00819 00820 } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false) { 00821 //LiteSpeed - not officially supported 00822 $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded 00823 00824 } else if ($_SERVER['SERVER_SOFTWARE'] === 'HTTPD') { 00825 //obscure name found on some servers - this is definitely not supported 00826 $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded 00827 00828 } else { 00829 throw new moodle_exception('unsupportedwebserver', 'error', '', $_SERVER['SERVER_SOFTWARE']); 00830 } 00831 00832 // sanitize the url a bit more, the encoding style may be different in vars above 00833 $rurl['fullpath'] = str_replace('"', '%22', $rurl['fullpath']); 00834 $rurl['fullpath'] = str_replace('\'', '%27', $rurl['fullpath']); 00835 00836 return $rurl; 00837 } 00838 00848 function init_performance_info() { 00849 00850 global $PERF, $CFG, $USER; 00851 00852 $PERF = new stdClass(); 00853 $PERF->logwrites = 0; 00854 if (function_exists('microtime')) { 00855 $PERF->starttime = microtime(); 00856 } 00857 if (function_exists('memory_get_usage')) { 00858 $PERF->startmemory = memory_get_usage(); 00859 } 00860 if (function_exists('posix_times')) { 00861 $PERF->startposixtimes = posix_times(); 00862 } 00863 } 00864 00875 function during_initial_install() { 00876 global $CFG; 00877 return empty($CFG->rolesactive); 00878 } 00879 00893 function raise_memory_limit($newlimit) { 00894 global $CFG; 00895 00896 if ($newlimit == MEMORY_UNLIMITED) { 00897 ini_set('memory_limit', -1); 00898 return true; 00899 00900 } else if ($newlimit == MEMORY_STANDARD) { 00901 if (PHP_INT_SIZE > 4) { 00902 $newlimit = get_real_size('128M'); // 64bit needs more memory 00903 } else { 00904 $newlimit = get_real_size('96M'); 00905 } 00906 00907 } else if ($newlimit == MEMORY_EXTRA) { 00908 if (PHP_INT_SIZE > 4) { 00909 $newlimit = get_real_size('384M'); // 64bit needs more memory 00910 } else { 00911 $newlimit = get_real_size('256M'); 00912 } 00913 if (!empty($CFG->extramemorylimit)) { 00914 $extra = get_real_size($CFG->extramemorylimit); 00915 if ($extra > $newlimit) { 00916 $newlimit = $extra; 00917 } 00918 } 00919 00920 } else if ($newlimit == MEMORY_HUGE) { 00921 $newlimit = get_real_size('2G'); 00922 00923 } else { 00924 $newlimit = get_real_size($newlimit); 00925 } 00926 00927 if ($newlimit <= 0) { 00928 debugging('Invalid memory limit specified.'); 00929 return false; 00930 } 00931 00932 $cur = ini_get('memory_limit'); 00933 if (empty($cur)) { 00934 // if php is compiled without --enable-memory-limits 00935 // apparently memory_limit is set to '' 00936 $cur = 0; 00937 } else { 00938 if ($cur == -1){ 00939 return true; // unlimited mem! 00940 } 00941 $cur = get_real_size($cur); 00942 } 00943 00944 if ($newlimit > $cur) { 00945 ini_set('memory_limit', $newlimit); 00946 return true; 00947 } 00948 return false; 00949 } 00950 00962 function reduce_memory_limit($newlimit) { 00963 if (empty($newlimit)) { 00964 return false; 00965 } 00966 $cur = ini_get('memory_limit'); 00967 if (empty($cur)) { 00968 // if php is compiled without --enable-memory-limits 00969 // apparently memory_limit is set to '' 00970 $cur = 0; 00971 } else { 00972 if ($cur == -1){ 00973 return true; // unlimited mem! 00974 } 00975 $cur = get_real_size($cur); 00976 } 00977 00978 $new = get_real_size($newlimit); 00979 // -1 is smaller, but it means unlimited 00980 if ($new < $cur && $new != -1) { 00981 ini_set('memory_limit', $newlimit); 00982 return true; 00983 } 00984 return false; 00985 } 00986 00993 function get_real_size($size = 0) { 00994 if (!$size) { 00995 return 0; 00996 } 00997 $scan = array(); 00998 $scan['GB'] = 1073741824; 00999 $scan['Gb'] = 1073741824; 01000 $scan['G'] = 1073741824; 01001 $scan['MB'] = 1048576; 01002 $scan['Mb'] = 1048576; 01003 $scan['M'] = 1048576; 01004 $scan['m'] = 1048576; 01005 $scan['KB'] = 1024; 01006 $scan['Kb'] = 1024; 01007 $scan['K'] = 1024; 01008 $scan['k'] = 1024; 01009 01010 while (list($key) = each($scan)) { 01011 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) { 01012 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key]; 01013 break; 01014 } 01015 } 01016 return $size; 01017 } 01018 01026 function disable_output_buffering() { 01027 $olddebug = error_reporting(0); 01028 01029 // disable compression, it would prevent closing of buffers 01030 if (ini_get_bool('zlib.output_compression')) { 01031 ini_set('zlib.output_compression', 'Off'); 01032 } 01033 01034 // try to flush everything all the time 01035 ob_implicit_flush(true); 01036 01037 // close all buffers if possible and discard any existing output 01038 // this can actually work around some whitespace problems in config.php 01039 while(ob_get_level()) { 01040 if (!ob_end_clean()) { 01041 // prevent infinite loop when buffer can not be closed 01042 break; 01043 } 01044 } 01045 01046 error_reporting($olddebug); 01047 } 01048 01055 function redirect_if_major_upgrade_required() { 01056 global $CFG; 01057 $lastmajordbchanges = 2010111700; 01058 if (empty($CFG->version) or (int)$CFG->version < $lastmajordbchanges or 01059 during_initial_install() or !empty($CFG->adminsetuppending)) { 01060 try { 01061 @session_get_instance()->terminate_current(); 01062 } catch (Exception $e) { 01063 // Ignore any errors, redirect to upgrade anyway. 01064 } 01065 $url = $CFG->wwwroot . '/' . $CFG->admin . '/index.php'; 01066 @header($_SERVER['SERVER_PROTOCOL'] . ' 303 See Other'); 01067 @header('Location: ' . $url); 01068 echo bootstrap_renderer::plain_redirect_message(htmlspecialchars($url)); 01069 exit; 01070 } 01071 } 01072 01089 function check_dir_exists($dir, $create = true, $recursive = true) { 01090 global $CFG; 01091 01092 umask(0000); // just in case some evil code changed it 01093 01094 if (is_dir($dir)) { 01095 return true; 01096 } 01097 01098 if (!$create) { 01099 return false; 01100 } 01101 01102 return mkdir($dir, $CFG->directorypermissions, $recursive); 01103 } 01104 01113 function make_writable_directory($dir, $exceptiononerror = true) { 01114 global $CFG; 01115 01116 if (file_exists($dir) and !is_dir($dir)) { 01117 if ($exceptiononerror) { 01118 throw new coding_exception($dir.' directory can not be created, file with the same name already exists.'); 01119 } else { 01120 return false; 01121 } 01122 } 01123 01124 umask(0000); // just in case some evil code changed it 01125 01126 if (!file_exists($dir)) { 01127 if (!mkdir($dir, $CFG->directorypermissions, true)) { 01128 if ($exceptiononerror) { 01129 throw new invalid_dataroot_permissions($dir.' can not be created, check permissions.'); 01130 } else { 01131 return false; 01132 } 01133 } 01134 } 01135 01136 if (!is_writable($dir)) { 01137 if ($exceptiononerror) { 01138 throw new invalid_dataroot_permissions($dir.' is not writable, check permissions.'); 01139 } else { 01140 return false; 01141 } 01142 } 01143 01144 return $dir; 01145 } 01146 01154 function protect_directory($dir) { 01155 // Make sure a .htaccess file is here, JUST IN CASE the files area is in the open and .htaccess is supported 01156 if (!file_exists("$dir/.htaccess")) { 01157 if ($handle = fopen("$dir/.htaccess", 'w')) { // For safety 01158 @fwrite($handle, "deny from all\r\nAllowOverride None\r\nNote: this file is broken intentionally, we do not want anybody to undo it in subdirectory!\r\n"); 01159 @fclose($handle); 01160 } 01161 } 01162 } 01163 01172 function make_upload_directory($directory, $exceptiononerror = true) { 01173 global $CFG; 01174 01175 if (strpos($directory, 'temp/') === 0 or $directory === 'temp') { 01176 debugging('Use make_temp_directory() for creation of temporary directory and $CFG->tempdir to get the location.'); 01177 01178 } else if (strpos($directory, 'cache/') === 0 or $directory === 'cache') { 01179 debugging('Use make_cache_directory() for creation of chache directory and $CFG->cachedir to get the location.'); 01180 } 01181 01182 protect_directory($CFG->dataroot); 01183 return make_writable_directory("$CFG->dataroot/$directory", $exceptiononerror); 01184 } 01185 01194 function make_temp_directory($directory, $exceptiononerror = true) { 01195 global $CFG; 01196 if ($CFG->tempdir !== "$CFG->dataroot/temp") { 01197 check_dir_exists($CFG->tempdir, true, true); 01198 protect_directory($CFG->tempdir); 01199 } else { 01200 protect_directory($CFG->dataroot); 01201 } 01202 return make_writable_directory("$CFG->tempdir/$directory", $exceptiononerror); 01203 } 01204 01212 function make_cache_directory($directory, $exceptiononerror = true) { 01213 global $CFG; 01214 if ($CFG->cachedir !== "$CFG->dataroot/cache") { 01215 check_dir_exists($CFG->cachedir, true, true); 01216 protect_directory($CFG->cachedir); 01217 } else { 01218 protect_directory($CFG->dataroot); 01219 } 01220 return make_writable_directory("$CFG->cachedir/$directory", $exceptiononerror); 01221 } 01222 01223 01224 function init_memcached() { 01225 global $CFG, $MCACHE; 01226 01227 include_once($CFG->libdir . '/memcached.class.php'); 01228 $MCACHE = new memcached; 01229 if ($MCACHE->status()) { 01230 return true; 01231 } 01232 unset($MCACHE); 01233 return false; 01234 } 01235 01236 function init_eaccelerator() { 01237 global $CFG, $MCACHE; 01238 01239 include_once($CFG->libdir . '/eaccelerator.class.php'); 01240 $MCACHE = new eaccelerator; 01241 if ($MCACHE->status()) { 01242 return true; 01243 } 01244 unset($MCACHE); 01245 return false; 01246 } 01247 01260 function is_web_crawler() { 01261 if (!empty($_SERVER['HTTP_USER_AGENT'])) { 01262 if (strpos($_SERVER['HTTP_USER_AGENT'], 'Googlebot') !== false ) { 01263 return true; 01264 } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'google.com') !== false ) { // Google 01265 return true; 01266 } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'Yahoo! Slurp') !== false ) { // Yahoo 01267 return true; 01268 } else if (strpos($_SERVER['HTTP_USER_AGENT'], '[ZSEBOT]') !== false ) { // Zoomspider 01269 return true; 01270 } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSNBOT') !== false ) { // MSN Search 01271 return true; 01272 } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'Yandex') !== false ) { 01273 return true; 01274 } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'AltaVista') !== false ) { 01275 return true; 01276 } 01277 } 01278 return false; 01279 } 01280 01317 class bootstrap_renderer { 01323 protected $initialising = false; 01324 01329 public function has_started() { 01330 return false; 01331 } 01332 01339 public function __call($method, $arguments) { 01340 global $OUTPUT, $PAGE; 01341 01342 $recursing = false; 01343 if ($method == 'notification') { 01344 // Catch infinite recursion caused by debugging output during print_header. 01345 $backtrace = debug_backtrace(); 01346 array_shift($backtrace); 01347 array_shift($backtrace); 01348 $recursing = is_early_init($backtrace); 01349 } 01350 01351 $earlymethods = array( 01352 'fatal_error' => 'early_error', 01353 'notification' => 'early_notification', 01354 ); 01355 01356 // If lib/outputlib.php has been loaded, call it. 01357 if (!empty($PAGE) && !$recursing) { 01358 if (array_key_exists($method, $earlymethods)) { 01359 //prevent PAGE->context warnings - exceptions might appear before we set any context 01360 $PAGE->set_context(null); 01361 } 01362 $PAGE->initialise_theme_and_output(); 01363 return call_user_func_array(array($OUTPUT, $method), $arguments); 01364 } 01365 01366 $this->initialising = true; 01367 01368 // Too soon to initialise $OUTPUT, provide a couple of key methods. 01369 if (array_key_exists($method, $earlymethods)) { 01370 return call_user_func_array(array('bootstrap_renderer', $earlymethods[$method]), $arguments); 01371 } 01372 01373 throw new coding_exception('Attempt to start output before enough information is known to initialise the theme.'); 01374 } 01375 01386 public static function early_error_content($message, $moreinfourl, $link, $backtrace, $debuginfo = null) { 01387 global $CFG; 01388 01389 $content = '<div style="margin-top: 6em; margin-left:auto; margin-right:auto; color:#990000; text-align:center; font-size:large; border-width:1px; 01390 border-color:black; background-color:#ffffee; border-style:solid; border-radius: 20px; border-collapse: collapse; 01391 width: 80%; -moz-border-radius: 20px; padding: 15px"> 01392 ' . $message . ' 01393 </div>'; 01394 if (!empty($CFG->debug) && $CFG->debug >= DEBUG_DEVELOPER) { 01395 if (!empty($debuginfo)) { 01396 $debuginfo = s($debuginfo); // removes all nasty JS 01397 $debuginfo = str_replace("\n", '<br />', $debuginfo); // keep newlines 01398 $content .= '<div class="notifytiny">Debug info: ' . $debuginfo . '</div>'; 01399 } 01400 if (!empty($backtrace)) { 01401 $content .= '<div class="notifytiny">Stack trace: ' . format_backtrace($backtrace, false) . '</div>'; 01402 } 01403 } 01404 01405 return $content; 01406 } 01407 01418 public static function early_error($message, $moreinfourl, $link, $backtrace, $debuginfo = null) { 01419 global $CFG; 01420 01421 if (CLI_SCRIPT) { 01422 echo "!!! $message !!!\n"; 01423 if (!empty($CFG->debug) and $CFG->debug >= DEBUG_DEVELOPER) { 01424 if (!empty($debuginfo)) { 01425 echo "\nDebug info: $debuginfo"; 01426 } 01427 if (!empty($backtrace)) { 01428 echo "\nStack trace: " . format_backtrace($backtrace, true); 01429 } 01430 } 01431 return; 01432 01433 } else if (AJAX_SCRIPT) { 01434 $e = new stdClass(); 01435 $e->error = $message; 01436 $e->stacktrace = NULL; 01437 $e->debuginfo = NULL; 01438 if (!empty($CFG->debug) and $CFG->debug >= DEBUG_DEVELOPER) { 01439 if (!empty($debuginfo)) { 01440 $e->debuginfo = $debuginfo; 01441 } 01442 if (!empty($backtrace)) { 01443 $e->stacktrace = format_backtrace($backtrace, true); 01444 } 01445 } 01446 @header('Content-Type: application/json; charset=utf-8'); 01447 echo json_encode($e); 01448 return; 01449 } 01450 01451 // In the name of protocol correctness, monitoring and performance 01452 // profiling, set the appropriate error headers for machine consumption 01453 if (isset($_SERVER['SERVER_PROTOCOL'])) { 01454 // Avoid it with cron.php. Note that we assume it's HTTP/1.x 01455 // The 503 ode here means our Moodle does not work at all, the error happened too early 01456 @header($_SERVER['SERVER_PROTOCOL'] . ' 503 Service Unavailable'); 01457 } 01458 01459 // better disable any caching 01460 @header('Content-Type: text/html; charset=utf-8'); 01461 @header('Cache-Control: no-store, no-cache, must-revalidate'); 01462 @header('Cache-Control: post-check=0, pre-check=0', false); 01463 @header('Pragma: no-cache'); 01464 @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT'); 01465 @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); 01466 01467 if (function_exists('get_string')) { 01468 $strerror = get_string('error'); 01469 } else { 01470 $strerror = 'Error'; 01471 } 01472 01473 $content = self::early_error_content($message, $moreinfourl, $link, $backtrace, $debuginfo); 01474 01475 return self::plain_page($strerror, $content); 01476 } 01477 01485 public static function early_notification($message, $classes = 'notifyproblem') { 01486 return '<div class="' . $classes . '">' . $message . '</div>'; 01487 } 01488 01495 public static function plain_redirect_message($encodedurl) { 01496 $message = '<div style="margin-top: 3em; margin-left:auto; margin-right:auto; text-align:center;">' . get_string('pageshouldredirect') . '<br /><a href="'. 01497 $encodedurl .'">'. get_string('continue') .'</a></div>'; 01498 return self::plain_page(get_string('redirect'), $message); 01499 } 01500 01509 public static function early_redirect_message($encodedurl, $message, $delay) { 01510 $meta = '<meta http-equiv="refresh" content="'. $delay .'; url='. $encodedurl .'" />'; 01511 $content = self::early_error_content($message, null, null, null); 01512 $content .= self::plain_redirect_message($encodedurl); 01513 01514 return self::plain_page(get_string('redirect'), $content, $meta); 01515 } 01516 01525 protected static function plain_page($title, $content, $meta = '') { 01526 if (function_exists('get_string') && function_exists('get_html_lang')) { 01527 $htmllang = get_html_lang(); 01528 } else { 01529 $htmllang = ''; 01530 } 01531 01532 return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 01533 <html xmlns="http://www.w3.org/1999/xhtml" ' . $htmllang . '> 01534 <head> 01535 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 01536 '.$meta.' 01537 <title>' . $title . '</title> 01538 </head><body>' . $content . '</body></html>'; 01539 } 01540 }