PageRenderTime 67ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/setuplib.php

https://github.com/dongsheng/moodle
PHP | 2179 lines | 1147 code | 232 blank | 800 comment | 302 complexity | 281684e2bfe2ada63945e309135bde81 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, GPL-3.0, Apache-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * These functions are required very early in the Moodle
  18. * setup process, before any of the main libraries are
  19. * loaded.
  20. *
  21. * @package core
  22. * @subpackage lib
  23. * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
  24. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25. */
  26. defined('MOODLE_INTERNAL') || die();
  27. // Debug levels - always keep the values in ascending order!
  28. /** No warnings and errors at all */
  29. define('DEBUG_NONE', 0);
  30. /** Fatal errors only */
  31. define('DEBUG_MINIMAL', E_ERROR | E_PARSE);
  32. /** Errors, warnings and notices */
  33. define('DEBUG_NORMAL', E_ERROR | E_PARSE | E_WARNING | E_NOTICE);
  34. /** All problems except strict PHP warnings */
  35. define('DEBUG_ALL', E_ALL & ~E_STRICT);
  36. /** DEBUG_ALL with all debug messages and strict warnings */
  37. define('DEBUG_DEVELOPER', E_ALL | E_STRICT);
  38. /** Remove any memory limits */
  39. define('MEMORY_UNLIMITED', -1);
  40. /** Standard memory limit for given platform */
  41. define('MEMORY_STANDARD', -2);
  42. /**
  43. * Large memory limit for given platform - used in cron, upgrade, and other places that need a lot of memory.
  44. * Can be overridden with $CFG->extramemorylimit setting.
  45. */
  46. define('MEMORY_EXTRA', -3);
  47. /** Extremely large memory limit - not recommended for standard scripts */
  48. define('MEMORY_HUGE', -4);
  49. /**
  50. * Base Moodle Exception class
  51. *
  52. * Although this class is defined here, you cannot throw a moodle_exception until
  53. * after moodlelib.php has been included (which will happen very soon).
  54. *
  55. * @package core
  56. * @subpackage lib
  57. * @copyright 2008 Petr Skoda {@link http://skodak.org}
  58. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  59. */
  60. class moodle_exception extends Exception {
  61. /**
  62. * @var string The name of the string from error.php to print
  63. */
  64. public $errorcode;
  65. /**
  66. * @var string The name of module
  67. */
  68. public $module;
  69. /**
  70. * @var mixed Extra words and phrases that might be required in the error string
  71. */
  72. public $a;
  73. /**
  74. * @var string The url where the user will be prompted to continue. If no url is provided the user will be directed to the site index page.
  75. */
  76. public $link;
  77. /**
  78. * @var string Optional information to aid the debugging process
  79. */
  80. public $debuginfo;
  81. /**
  82. * Constructor
  83. * @param string $errorcode The name of the string from error.php to print
  84. * @param string $module name of module
  85. * @param string $link The url where the user will be prompted to continue. If no url is provided the user will be directed to the site index page.
  86. * @param mixed $a Extra words and phrases that might be required in the error string
  87. * @param string $debuginfo optional debugging information
  88. */
  89. function __construct($errorcode, $module='', $link='', $a=NULL, $debuginfo=null) {
  90. global $CFG;
  91. if (empty($module) || $module == 'moodle' || $module == 'core') {
  92. $module = 'error';
  93. }
  94. $this->errorcode = $errorcode;
  95. $this->module = $module;
  96. $this->link = $link;
  97. $this->a = $a;
  98. $this->debuginfo = is_null($debuginfo) ? null : (string)$debuginfo;
  99. if (get_string_manager()->string_exists($errorcode, $module)) {
  100. $message = get_string($errorcode, $module, $a);
  101. $haserrorstring = true;
  102. } else {
  103. $message = $module . '/' . $errorcode;
  104. $haserrorstring = false;
  105. }
  106. $isinphpunittest = (defined('PHPUNIT_TEST') && PHPUNIT_TEST);
  107. $hasdebugdeveloper = (
  108. isset($CFG->debugdisplay) &&
  109. isset($CFG->debug) &&
  110. $CFG->debugdisplay &&
  111. $CFG->debug === DEBUG_DEVELOPER
  112. );
  113. if ($debuginfo) {
  114. if ($isinphpunittest || $hasdebugdeveloper) {
  115. $message = "$message ($debuginfo)";
  116. }
  117. }
  118. if (!$haserrorstring and $isinphpunittest) {
  119. // Append the contents of $a to $debuginfo so helpful information isn't lost.
  120. // This emulates what {@link get_exception_info()} does. Unfortunately that
  121. // function is not used by phpunit.
  122. $message .= PHP_EOL.'$a contents: '.print_r($a, true);
  123. }
  124. parent::__construct($message, 0);
  125. }
  126. }
  127. /**
  128. * Course/activity access exception.
  129. *
  130. * This exception is thrown from require_login()
  131. *
  132. * @package core_access
  133. * @copyright 2010 Petr Skoda {@link http://skodak.org}
  134. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  135. */
  136. class require_login_exception extends moodle_exception {
  137. /**
  138. * Constructor
  139. * @param string $debuginfo Information to aid the debugging process
  140. */
  141. function __construct($debuginfo) {
  142. parent::__construct('requireloginerror', 'error', '', NULL, $debuginfo);
  143. }
  144. }
  145. /**
  146. * Session timeout exception.
  147. *
  148. * This exception is thrown from require_login()
  149. *
  150. * @package core_access
  151. * @copyright 2015 Andrew Nicols <andrew@nicols.co.uk>
  152. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  153. */
  154. class require_login_session_timeout_exception extends require_login_exception {
  155. /**
  156. * Constructor
  157. */
  158. public function __construct() {
  159. moodle_exception::__construct('sessionerroruser', 'error');
  160. }
  161. }
  162. /**
  163. * Web service parameter exception class
  164. * @deprecated since Moodle 2.2 - use moodle exception instead
  165. * This exception must be thrown to the web service client when a web service parameter is invalid
  166. * The error string is gotten from webservice.php
  167. */
  168. class webservice_parameter_exception extends moodle_exception {
  169. /**
  170. * Constructor
  171. * @param string $errorcode The name of the string from webservice.php to print
  172. * @param string $a The name of the parameter
  173. * @param string $debuginfo Optional information to aid debugging
  174. */
  175. function __construct($errorcode=null, $a = '', $debuginfo = null) {
  176. parent::__construct($errorcode, 'webservice', '', $a, $debuginfo);
  177. }
  178. }
  179. /**
  180. * Exceptions indicating user does not have permissions to do something
  181. * and the execution can not continue.
  182. *
  183. * @package core_access
  184. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  185. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  186. */
  187. class required_capability_exception extends moodle_exception {
  188. /**
  189. * Constructor
  190. * @param context $context The context used for the capability check
  191. * @param string $capability The required capability
  192. * @param string $errormessage The error message to show the user
  193. * @param string $stringfile
  194. */
  195. function __construct($context, $capability, $errormessage, $stringfile) {
  196. $capabilityname = get_capability_string($capability);
  197. if ($context->contextlevel == CONTEXT_MODULE and preg_match('/:view$/', $capability)) {
  198. // 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
  199. $parentcontext = $context->get_parent_context();
  200. $link = $parentcontext->get_url();
  201. } else {
  202. $link = $context->get_url();
  203. }
  204. parent::__construct($errormessage, $stringfile, $link, $capabilityname);
  205. }
  206. }
  207. /**
  208. * Exception indicating programming error, must be fixed by a programer. For example
  209. * a core API might throw this type of exception if a plugin calls it incorrectly.
  210. *
  211. * @package core
  212. * @subpackage lib
  213. * @copyright 2008 Petr Skoda {@link http://skodak.org}
  214. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  215. */
  216. class coding_exception extends moodle_exception {
  217. /**
  218. * Constructor
  219. * @param string $hint short description of problem
  220. * @param string $debuginfo detailed information how to fix problem
  221. */
  222. function __construct($hint, $debuginfo=null) {
  223. parent::__construct('codingerror', 'debug', '', $hint, $debuginfo);
  224. }
  225. }
  226. /**
  227. * Exception indicating malformed parameter problem.
  228. * This exception is not supposed to be thrown when processing
  229. * user submitted data in forms. It is more suitable
  230. * for WS and other low level stuff.
  231. *
  232. * @package core
  233. * @subpackage lib
  234. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  235. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  236. */
  237. class invalid_parameter_exception extends moodle_exception {
  238. /**
  239. * Constructor
  240. * @param string $debuginfo some detailed information
  241. */
  242. function __construct($debuginfo=null) {
  243. parent::__construct('invalidparameter', 'debug', '', null, $debuginfo);
  244. }
  245. }
  246. /**
  247. * Exception indicating malformed response problem.
  248. * This exception is not supposed to be thrown when processing
  249. * user submitted data in forms. It is more suitable
  250. * for WS and other low level stuff.
  251. */
  252. class invalid_response_exception extends moodle_exception {
  253. /**
  254. * Constructor
  255. * @param string $debuginfo some detailed information
  256. */
  257. function __construct($debuginfo=null) {
  258. parent::__construct('invalidresponse', 'debug', '', null, $debuginfo);
  259. }
  260. }
  261. /**
  262. * An exception that indicates something really weird happened. For example,
  263. * if you do switch ($context->contextlevel), and have one case for each
  264. * CONTEXT_... constant. You might throw an invalid_state_exception in the
  265. * default case, to just in case something really weird is going on, and
  266. * $context->contextlevel is invalid - rather than ignoring this possibility.
  267. *
  268. * @package core
  269. * @subpackage lib
  270. * @copyright 2009 onwards Martin Dougiamas {@link http://moodle.com}
  271. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  272. */
  273. class invalid_state_exception extends moodle_exception {
  274. /**
  275. * Constructor
  276. * @param string $hint short description of problem
  277. * @param string $debuginfo optional more detailed information
  278. */
  279. function __construct($hint, $debuginfo=null) {
  280. parent::__construct('invalidstatedetected', 'debug', '', $hint, $debuginfo);
  281. }
  282. }
  283. /**
  284. * An exception that indicates incorrect permissions in $CFG->dataroot
  285. *
  286. * @package core
  287. * @subpackage lib
  288. * @copyright 2010 Petr Skoda {@link http://skodak.org}
  289. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  290. */
  291. class invalid_dataroot_permissions extends moodle_exception {
  292. /**
  293. * Constructor
  294. * @param string $debuginfo optional more detailed information
  295. */
  296. function __construct($debuginfo = NULL) {
  297. parent::__construct('invaliddatarootpermissions', 'error', '', NULL, $debuginfo);
  298. }
  299. }
  300. /**
  301. * An exception that indicates that file can not be served
  302. *
  303. * @package core
  304. * @subpackage lib
  305. * @copyright 2010 Petr Skoda {@link http://skodak.org}
  306. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  307. */
  308. class file_serving_exception extends moodle_exception {
  309. /**
  310. * Constructor
  311. * @param string $debuginfo optional more detailed information
  312. */
  313. function __construct($debuginfo = NULL) {
  314. parent::__construct('cannotservefile', 'error', '', NULL, $debuginfo);
  315. }
  316. }
  317. /**
  318. * Default exception handler.
  319. *
  320. * @param Exception $ex
  321. * @return void -does not return. Terminates execution!
  322. */
  323. function default_exception_handler($ex) {
  324. global $CFG, $DB, $OUTPUT, $USER, $FULLME, $SESSION, $PAGE;
  325. // detect active db transactions, rollback and log as error
  326. abort_all_db_transactions();
  327. if (($ex instanceof required_capability_exception) && !CLI_SCRIPT && !AJAX_SCRIPT && !empty($CFG->autologinguests) && !empty($USER->autologinguest)) {
  328. $SESSION->wantsurl = qualified_me();
  329. redirect(get_login_url());
  330. }
  331. $info = get_exception_info($ex);
  332. // If we already tried to send the header remove it, the content length
  333. // should be either empty or the length of the error page.
  334. @header_remove('Content-Length');
  335. if (is_early_init($info->backtrace)) {
  336. echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo, $info->errorcode);
  337. } else {
  338. if (debugging('', DEBUG_MINIMAL)) {
  339. $logerrmsg = "Default exception handler: ".$info->message.' Debug: '.$info->debuginfo."\n".format_backtrace($info->backtrace, true);
  340. error_log($logerrmsg);
  341. }
  342. try {
  343. if ($DB) {
  344. // If you enable db debugging and exception is thrown, the print footer prints a lot of rubbish
  345. $DB->set_debug(0);
  346. }
  347. if (AJAX_SCRIPT) {
  348. // If we are in an AJAX script we don't want to use PREFERRED_RENDERER_TARGET.
  349. // Because we know we will want to use ajax format.
  350. $renderer = new core_renderer_ajax($PAGE, 'ajax');
  351. } else {
  352. $renderer = $OUTPUT;
  353. }
  354. echo $renderer->fatal_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo,
  355. $info->errorcode);
  356. } catch (Exception $e) {
  357. $out_ex = $e;
  358. } catch (Throwable $e) {
  359. // Engine errors in PHP7 throw exceptions of type Throwable (this "catch" will be ignored in PHP5).
  360. $out_ex = $e;
  361. }
  362. if (isset($out_ex)) {
  363. // default exception handler MUST not throw any exceptions!!
  364. // 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
  365. // so we just print at least something instead of "Exception thrown without a stack frame in Unknown on line 0":-(
  366. if (CLI_SCRIPT or AJAX_SCRIPT) {
  367. // just ignore the error and send something back using the safest method
  368. echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo, $info->errorcode);
  369. } else {
  370. echo bootstrap_renderer::early_error_content($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo);
  371. $outinfo = get_exception_info($out_ex);
  372. echo bootstrap_renderer::early_error_content($outinfo->message, $outinfo->moreinfourl, $outinfo->link, $outinfo->backtrace, $outinfo->debuginfo);
  373. }
  374. }
  375. }
  376. exit(1); // General error code
  377. }
  378. /**
  379. * Default error handler, prevents some white screens.
  380. * @param int $errno
  381. * @param string $errstr
  382. * @param string $errfile
  383. * @param int $errline
  384. * @return bool false means use default error handler
  385. */
  386. function default_error_handler($errno, $errstr, $errfile, $errline) {
  387. if ($errno == 4096) {
  388. //fatal catchable error
  389. throw new coding_exception('PHP catchable fatal error', $errstr);
  390. }
  391. return false;
  392. }
  393. /**
  394. * Unconditionally abort all database transactions, this function
  395. * should be called from exception handlers only.
  396. * @return void
  397. */
  398. function abort_all_db_transactions() {
  399. global $CFG, $DB, $SCRIPT;
  400. // default exception handler MUST not throw any exceptions!!
  401. if ($DB && $DB->is_transaction_started()) {
  402. error_log('Database transaction aborted automatically in ' . $CFG->dirroot . $SCRIPT);
  403. // note: transaction blocks should never change current $_SESSION
  404. $DB->force_transaction_rollback();
  405. }
  406. }
  407. /**
  408. * This function encapsulates the tests for whether an exception was thrown in
  409. * early init -- either during setup.php or during init of $OUTPUT.
  410. *
  411. * If another exception is thrown then, and if we do not take special measures,
  412. * we would just get a very cryptic message "Exception thrown without a stack
  413. * frame in Unknown on line 0". That makes debugging very hard, so we do take
  414. * special measures in default_exception_handler, with the help of this function.
  415. *
  416. * @param array $backtrace the stack trace to analyse.
  417. * @return boolean whether the stack trace is somewhere in output initialisation.
  418. */
  419. function is_early_init($backtrace) {
  420. $dangerouscode = array(
  421. array('function' => 'header', 'type' => '->'),
  422. array('class' => 'bootstrap_renderer'),
  423. array('file' => __DIR__.'/setup.php'),
  424. );
  425. foreach ($backtrace as $stackframe) {
  426. foreach ($dangerouscode as $pattern) {
  427. $matches = true;
  428. foreach ($pattern as $property => $value) {
  429. if (!isset($stackframe[$property]) || $stackframe[$property] != $value) {
  430. $matches = false;
  431. }
  432. }
  433. if ($matches) {
  434. return true;
  435. }
  436. }
  437. }
  438. return false;
  439. }
  440. /**
  441. * Abort execution by throwing of a general exception,
  442. * default exception handler displays the error message in most cases.
  443. *
  444. * @param string $errorcode The name of the language string containing the error message.
  445. * Normally this should be in the error.php lang file.
  446. * @param string $module The language file to get the error message from.
  447. * @param string $link The url where the user will be prompted to continue.
  448. * If no url is provided the user will be directed to the site index page.
  449. * @param object $a Extra words and phrases that might be required in the error string
  450. * @param string $debuginfo optional debugging information
  451. * @return void, always throws exception!
  452. */
  453. function print_error($errorcode, $module = 'error', $link = '', $a = null, $debuginfo = null) {
  454. throw new moodle_exception($errorcode, $module, $link, $a, $debuginfo);
  455. }
  456. /**
  457. * Returns detailed information about specified exception.
  458. * @param exception $ex
  459. * @return object
  460. */
  461. function get_exception_info($ex) {
  462. global $CFG, $DB, $SESSION;
  463. if ($ex instanceof moodle_exception) {
  464. $errorcode = $ex->errorcode;
  465. $module = $ex->module;
  466. $a = $ex->a;
  467. $link = $ex->link;
  468. $debuginfo = $ex->debuginfo;
  469. } else {
  470. $errorcode = 'generalexceptionmessage';
  471. $module = 'error';
  472. $a = $ex->getMessage();
  473. $link = '';
  474. $debuginfo = '';
  475. }
  476. // Append the error code to the debug info to make grepping and googling easier
  477. $debuginfo .= PHP_EOL."Error code: $errorcode";
  478. $backtrace = $ex->getTrace();
  479. $place = array('file'=>$ex->getFile(), 'line'=>$ex->getLine(), 'exception'=>get_class($ex));
  480. array_unshift($backtrace, $place);
  481. // Be careful, no guarantee moodlelib.php is loaded.
  482. if (empty($module) || $module == 'moodle' || $module == 'core') {
  483. $module = 'error';
  484. }
  485. // Search for the $errorcode's associated string
  486. // If not found, append the contents of $a to $debuginfo so helpful information isn't lost
  487. if (function_exists('get_string_manager')) {
  488. if (get_string_manager()->string_exists($errorcode, $module)) {
  489. $message = get_string($errorcode, $module, $a);
  490. } elseif ($module == 'error' && get_string_manager()->string_exists($errorcode, 'moodle')) {
  491. // Search in moodle file if error specified - needed for backwards compatibility
  492. $message = get_string($errorcode, 'moodle', $a);
  493. } else {
  494. $message = $module . '/' . $errorcode;
  495. $debuginfo .= PHP_EOL.'$a contents: '.print_r($a, true);
  496. }
  497. } else {
  498. $message = $module . '/' . $errorcode;
  499. $debuginfo .= PHP_EOL.'$a contents: '.print_r($a, true);
  500. }
  501. // Remove some absolute paths from message and debugging info.
  502. $searches = array();
  503. $replaces = array();
  504. $cfgnames = array('backuptempdir', 'tempdir', 'cachedir', 'localcachedir', 'themedir', 'dataroot', 'dirroot');
  505. foreach ($cfgnames as $cfgname) {
  506. if (property_exists($CFG, $cfgname)) {
  507. $searches[] = $CFG->$cfgname;
  508. $replaces[] = "[$cfgname]";
  509. }
  510. }
  511. if (!empty($searches)) {
  512. $message = str_replace($searches, $replaces, $message);
  513. $debuginfo = str_replace($searches, $replaces, $debuginfo);
  514. }
  515. // Be careful, no guarantee weblib.php is loaded.
  516. if (function_exists('clean_text')) {
  517. $message = clean_text($message);
  518. } else {
  519. $message = htmlspecialchars($message);
  520. }
  521. if (!empty($CFG->errordocroot)) {
  522. $errordoclink = $CFG->errordocroot . '/en/';
  523. } else {
  524. // Only if the function is available. May be not for early errors.
  525. if (function_exists('current_language')) {
  526. $errordoclink = get_docs_url();
  527. } else {
  528. $errordoclink = 'https://docs.moodle.org/en/';
  529. }
  530. }
  531. if ($module === 'error') {
  532. $modulelink = 'moodle';
  533. } else {
  534. $modulelink = $module;
  535. }
  536. $moreinfourl = $errordoclink . 'error/' . $modulelink . '/' . $errorcode;
  537. if (empty($link)) {
  538. if (!empty($SESSION->fromurl)) {
  539. $link = $SESSION->fromurl;
  540. unset($SESSION->fromurl);
  541. } else {
  542. $link = $CFG->wwwroot .'/';
  543. }
  544. }
  545. // When printing an error the continue button should never link offsite.
  546. // We cannot use clean_param() here as it is not guaranteed that it has been loaded yet.
  547. if (stripos($link, $CFG->wwwroot) === 0) {
  548. // Internal HTTP, all good.
  549. } else {
  550. // External link spotted!
  551. $link = $CFG->wwwroot . '/';
  552. }
  553. $info = new stdClass();
  554. $info->message = $message;
  555. $info->errorcode = $errorcode;
  556. $info->backtrace = $backtrace;
  557. $info->link = $link;
  558. $info->moreinfourl = $moreinfourl;
  559. $info->a = $a;
  560. $info->debuginfo = $debuginfo;
  561. return $info;
  562. }
  563. /**
  564. * @deprecated since Moodle 3.8 MDL-61038 - please do not use this function any more.
  565. * @see \core\uuid::generate()
  566. */
  567. function generate_uuid() {
  568. throw new coding_exception('generate_uuid() cannot be used anymore. Please use ' .
  569. '\core\uuid::generate() instead.');
  570. }
  571. /**
  572. * Returns the Moodle Docs URL in the users language for a given 'More help' link.
  573. *
  574. * There are three cases:
  575. *
  576. * 1. In the normal case, $path will be a short relative path 'component/thing',
  577. * like 'mod/folder/view' 'group/import'. This gets turned into an link to
  578. * MoodleDocs in the user's language, and for the appropriate Moodle version.
  579. * E.g. 'group/import' may become 'http://docs.moodle.org/2x/en/group/import'.
  580. * The 'http://docs.moodle.org' bit comes from $CFG->docroot.
  581. *
  582. * This is the only option that should be used in standard Moodle code. The other
  583. * two options have been implemented because they are useful for third-party plugins.
  584. *
  585. * 2. $path may be an absolute URL, starting http:// or https://. In this case,
  586. * the link is used as is.
  587. *
  588. * 3. $path may start %%WWWROOT%%, in which case that is replaced by
  589. * $CFG->wwwroot to make the link.
  590. *
  591. * @param string $path the place to link to. See above for details.
  592. * @return string The MoodleDocs URL in the user's language. for example @link http://docs.moodle.org/2x/en/$path}
  593. */
  594. function get_docs_url($path = null) {
  595. global $CFG;
  596. // Absolute URLs are used unmodified.
  597. if (substr($path, 0, 7) === 'http://' || substr($path, 0, 8) === 'https://') {
  598. return $path;
  599. }
  600. // Paths starting %%WWWROOT%% have that replaced by $CFG->wwwroot.
  601. if (substr($path, 0, 11) === '%%WWWROOT%%') {
  602. return $CFG->wwwroot . substr($path, 11);
  603. }
  604. // Otherwise we do the normal case, and construct a MoodleDocs URL relative to $CFG->docroot.
  605. // Check that $CFG->branch has been set up, during installation it won't be.
  606. if (empty($CFG->branch)) {
  607. // It's not there yet so look at version.php.
  608. include($CFG->dirroot.'/version.php');
  609. } else {
  610. // We can use $CFG->branch and avoid having to include version.php.
  611. $branch = $CFG->branch;
  612. }
  613. // ensure branch is valid.
  614. if (!$branch) {
  615. // We should never get here but in case we do lets set $branch to .
  616. // the smart one's will know that this is the current directory
  617. // and the smarter ones will know that there is some smart matching
  618. // that will ensure people end up at the latest version of the docs.
  619. $branch = '.';
  620. }
  621. if (empty($CFG->doclang)) {
  622. $lang = current_language();
  623. } else {
  624. $lang = $CFG->doclang;
  625. }
  626. $end = '/' . $branch . '/' . $lang . '/' . $path;
  627. if (empty($CFG->docroot)) {
  628. return 'http://docs.moodle.org'. $end;
  629. } else {
  630. return $CFG->docroot . $end ;
  631. }
  632. }
  633. /**
  634. * Formats a backtrace ready for output.
  635. *
  636. * This function does not include function arguments because they could contain sensitive information
  637. * not suitable to be exposed in a response.
  638. *
  639. * @param array $callers backtrace array, as returned by debug_backtrace().
  640. * @param boolean $plaintext if false, generates HTML, if true generates plain text.
  641. * @return string formatted backtrace, ready for output.
  642. */
  643. function format_backtrace($callers, $plaintext = false) {
  644. // do not use $CFG->dirroot because it might not be available in destructors
  645. $dirroot = dirname(__DIR__);
  646. if (empty($callers)) {
  647. return '';
  648. }
  649. $from = $plaintext ? '' : '<ul style="text-align: left" data-rel="backtrace">';
  650. foreach ($callers as $caller) {
  651. if (!isset($caller['line'])) {
  652. $caller['line'] = '?'; // probably call_user_func()
  653. }
  654. if (!isset($caller['file'])) {
  655. $caller['file'] = 'unknownfile'; // probably call_user_func()
  656. }
  657. $from .= $plaintext ? '* ' : '<li>';
  658. $from .= 'line ' . $caller['line'] . ' of ' . str_replace($dirroot, '', $caller['file']);
  659. if (isset($caller['function'])) {
  660. $from .= ': call to ';
  661. if (isset($caller['class'])) {
  662. $from .= $caller['class'] . $caller['type'];
  663. }
  664. $from .= $caller['function'] . '()';
  665. } else if (isset($caller['exception'])) {
  666. $from .= ': '.$caller['exception'].' thrown';
  667. }
  668. $from .= $plaintext ? "\n" : '</li>';
  669. }
  670. $from .= $plaintext ? '' : '</ul>';
  671. return $from;
  672. }
  673. /**
  674. * This function makes the return value of ini_get consistent if you are
  675. * setting server directives through the .htaccess file in apache.
  676. *
  677. * Current behavior for value set from php.ini On = 1, Off = [blank]
  678. * Current behavior for value set from .htaccess On = On, Off = Off
  679. * Contributed by jdell @ unr.edu
  680. *
  681. * @param string $ini_get_arg The argument to get
  682. * @return bool True for on false for not
  683. */
  684. function ini_get_bool($ini_get_arg) {
  685. $temp = ini_get($ini_get_arg);
  686. if ($temp == '1' or strtolower($temp) == 'on') {
  687. return true;
  688. }
  689. return false;
  690. }
  691. /**
  692. * This function verifies the sanity of PHP configuration
  693. * and stops execution if anything critical found.
  694. */
  695. function setup_validate_php_configuration() {
  696. // this must be very fast - no slow checks here!!!
  697. if (ini_get_bool('session.auto_start')) {
  698. print_error('sessionautostartwarning', 'admin');
  699. }
  700. }
  701. /**
  702. * Initialise global $CFG variable.
  703. * @private to be used only from lib/setup.php
  704. */
  705. function initialise_cfg() {
  706. global $CFG, $DB;
  707. if (!$DB) {
  708. // This should not happen.
  709. return;
  710. }
  711. try {
  712. $localcfg = get_config('core');
  713. } catch (dml_exception $e) {
  714. // Most probably empty db, going to install soon.
  715. return;
  716. }
  717. foreach ($localcfg as $name => $value) {
  718. // Note that get_config() keeps forced settings
  719. // and normalises values to string if possible.
  720. $CFG->{$name} = $value;
  721. }
  722. }
  723. /**
  724. * Cache any immutable config locally to avoid constant DB lookups.
  725. *
  726. * Only to be used only from lib/setup.php
  727. */
  728. function initialise_local_config_cache() {
  729. global $CFG;
  730. $bootstrapcachefile = $CFG->localcachedir . '/bootstrap.php';
  731. if (!empty($CFG->siteidentifier) && !file_exists($bootstrapcachefile)) {
  732. $contents = "<?php
  733. // ********** This file is generated DO NOT EDIT **********
  734. \$CFG->siteidentifier = '" . addslashes($CFG->siteidentifier) . "';
  735. \$CFG->bootstraphash = '" . hash_local_config_cache() . "';
  736. // Only if the file is not stale and has not been defined.
  737. if (\$CFG->bootstraphash === hash_local_config_cache() && !defined('SYSCONTEXTID')) {
  738. define('SYSCONTEXTID', ".SYSCONTEXTID.");
  739. }
  740. ";
  741. $temp = $bootstrapcachefile . '.tmp' . uniqid();
  742. file_put_contents($temp, $contents);
  743. @chmod($temp, $CFG->filepermissions);
  744. rename($temp, $bootstrapcachefile);
  745. }
  746. }
  747. /**
  748. * Calculate a proper hash to be able to invalidate stale cached configs.
  749. *
  750. * Only to be used to verify bootstrap.php status.
  751. *
  752. * @return string md5 hash of all the sensible bits deciding if cached config is stale or no.
  753. */
  754. function hash_local_config_cache() {
  755. global $CFG;
  756. // This is pretty much {@see moodle_database::get_settings_hash()} that is used
  757. // as identifier for the database meta information MUC cache. Should be enough to
  758. // react against any of the normal changes (new prefix, change of DB type) while
  759. // *incorrectly* keeping the old dataroot directory unmodified with stale data.
  760. // This may need more stuff to be considered if it's discovered that there are
  761. // more variables making the file stale.
  762. return md5($CFG->dbtype . $CFG->dbhost . $CFG->dbuser . $CFG->dbname . $CFG->prefix);
  763. }
  764. /**
  765. * Initialises $FULLME and friends. Private function. Should only be called from
  766. * setup.php.
  767. */
  768. function initialise_fullme() {
  769. global $CFG, $FULLME, $ME, $SCRIPT, $FULLSCRIPT;
  770. // Detect common config error.
  771. if (substr($CFG->wwwroot, -1) == '/') {
  772. print_error('wwwrootslash', 'error');
  773. }
  774. if (CLI_SCRIPT) {
  775. initialise_fullme_cli();
  776. return;
  777. }
  778. if (!empty($CFG->overridetossl)) {
  779. if (strpos($CFG->wwwroot, 'http://') === 0) {
  780. $CFG->wwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
  781. } else {
  782. unset_config('overridetossl');
  783. }
  784. }
  785. $rurl = setup_get_remote_url();
  786. $wwwroot = parse_url($CFG->wwwroot.'/');
  787. if (empty($rurl['host'])) {
  788. // missing host in request header, probably not a real browser, let's ignore them
  789. } else if (!empty($CFG->reverseproxy)) {
  790. // $CFG->reverseproxy specifies if reverse proxy server used
  791. // Used in load balancing scenarios.
  792. // Do not abuse this to try to solve lan/wan access problems!!!!!
  793. } else {
  794. if (($rurl['host'] !== $wwwroot['host']) or
  795. (!empty($wwwroot['port']) and $rurl['port'] != $wwwroot['port']) or
  796. (strpos($rurl['path'], $wwwroot['path']) !== 0)) {
  797. // Explain the problem and redirect them to the right URL
  798. if (!defined('NO_MOODLE_COOKIES')) {
  799. define('NO_MOODLE_COOKIES', true);
  800. }
  801. // The login/token.php script should call the correct url/port.
  802. if (defined('REQUIRE_CORRECT_ACCESS') && REQUIRE_CORRECT_ACCESS) {
  803. $wwwrootport = empty($wwwroot['port'])?'':$wwwroot['port'];
  804. $calledurl = $rurl['host'];
  805. if (!empty($rurl['port'])) {
  806. $calledurl .= ':'. $rurl['port'];
  807. }
  808. $correcturl = $wwwroot['host'];
  809. if (!empty($wwwrootport)) {
  810. $correcturl .= ':'. $wwwrootport;
  811. }
  812. throw new moodle_exception('requirecorrectaccess', 'error', '', null,
  813. 'You called ' . $calledurl .', you should have called ' . $correcturl);
  814. }
  815. redirect($CFG->wwwroot, get_string('wwwrootmismatch', 'error', $CFG->wwwroot), 3);
  816. }
  817. }
  818. // Check that URL is under $CFG->wwwroot.
  819. if (strpos($rurl['path'], $wwwroot['path']) === 0) {
  820. $SCRIPT = substr($rurl['path'], strlen($wwwroot['path'])-1);
  821. } else {
  822. // Probably some weird external script
  823. $SCRIPT = $FULLSCRIPT = $FULLME = $ME = null;
  824. return;
  825. }
  826. // $CFG->sslproxy specifies if external SSL appliance is used
  827. // (That is, the Moodle server uses http, with an external box translating everything to https).
  828. if (empty($CFG->sslproxy)) {
  829. if ($rurl['scheme'] === 'http' and $wwwroot['scheme'] === 'https') {
  830. if (defined('REQUIRE_CORRECT_ACCESS') && REQUIRE_CORRECT_ACCESS) {
  831. print_error('sslonlyaccess', 'error');
  832. } else {
  833. redirect($CFG->wwwroot, get_string('wwwrootmismatch', 'error', $CFG->wwwroot), 3);
  834. }
  835. }
  836. } else {
  837. if ($wwwroot['scheme'] !== 'https') {
  838. throw new coding_exception('Must use https address in wwwroot when ssl proxy enabled!');
  839. }
  840. $rurl['scheme'] = 'https'; // make moodle believe it runs on https, squid or something else it doing it
  841. $_SERVER['HTTPS'] = 'on'; // Override $_SERVER to help external libraries with their HTTPS detection.
  842. $_SERVER['SERVER_PORT'] = 443; // Assume default ssl port for the proxy.
  843. }
  844. // Hopefully this will stop all those "clever" admins trying to set up moodle
  845. // with two different addresses in intranet and Internet.
  846. // Port forwarding is still allowed!
  847. if (!empty($CFG->reverseproxy) && $rurl['host'] === $wwwroot['host'] && (empty($wwwroot['port']) || $rurl['port'] === $wwwroot['port'])) {
  848. print_error('reverseproxyabused', 'error');
  849. }
  850. $hostandport = $rurl['scheme'] . '://' . $wwwroot['host'];
  851. if (!empty($wwwroot['port'])) {
  852. $hostandport .= ':'.$wwwroot['port'];
  853. }
  854. $FULLSCRIPT = $hostandport . $rurl['path'];
  855. $FULLME = $hostandport . $rurl['fullpath'];
  856. $ME = $rurl['fullpath'];
  857. }
  858. /**
  859. * Initialises $FULLME and friends for command line scripts.
  860. * This is a private method for use by initialise_fullme.
  861. */
  862. function initialise_fullme_cli() {
  863. global $CFG, $FULLME, $ME, $SCRIPT, $FULLSCRIPT;
  864. // Urls do not make much sense in CLI scripts
  865. $backtrace = debug_backtrace();
  866. $topfile = array_pop($backtrace);
  867. $topfile = realpath($topfile['file']);
  868. $dirroot = realpath($CFG->dirroot);
  869. if (strpos($topfile, $dirroot) !== 0) {
  870. // Probably some weird external script
  871. $SCRIPT = $FULLSCRIPT = $FULLME = $ME = null;
  872. } else {
  873. $relativefile = substr($topfile, strlen($dirroot));
  874. $relativefile = str_replace('\\', '/', $relativefile); // Win fix
  875. $SCRIPT = $FULLSCRIPT = $relativefile;
  876. $FULLME = $ME = null;
  877. }
  878. }
  879. /**
  880. * Get the URL that PHP/the web server thinks it is serving. Private function
  881. * used by initialise_fullme. In your code, use $PAGE->url, $SCRIPT, etc.
  882. * @return array in the same format that parse_url returns, with the addition of
  883. * a 'fullpath' element, which includes any slasharguments path.
  884. */
  885. function setup_get_remote_url() {
  886. $rurl = array();
  887. if (isset($_SERVER['HTTP_HOST'])) {
  888. list($rurl['host']) = explode(':', $_SERVER['HTTP_HOST']);
  889. } else {
  890. $rurl['host'] = null;
  891. }
  892. $rurl['port'] = (int)$_SERVER['SERVER_PORT'];
  893. $rurl['path'] = $_SERVER['SCRIPT_NAME']; // Script path without slash arguments
  894. $rurl['scheme'] = (empty($_SERVER['HTTPS']) or $_SERVER['HTTPS'] === 'off' or $_SERVER['HTTPS'] === 'Off' or $_SERVER['HTTPS'] === 'OFF') ? 'http' : 'https';
  895. if (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false) {
  896. //Apache server
  897. $rurl['fullpath'] = $_SERVER['REQUEST_URI'];
  898. // Fixing a known issue with:
  899. // - Apache versions lesser than 2.4.11
  900. // - PHP deployed in Apache as PHP-FPM via mod_proxy_fcgi
  901. // - PHP versions lesser than 5.6.3 and 5.5.18.
  902. if (isset($_SERVER['PATH_INFO']) && (php_sapi_name() === 'fpm-fcgi') && isset($_SERVER['SCRIPT_NAME'])) {
  903. $pathinfodec = rawurldecode($_SERVER['PATH_INFO']);
  904. $lenneedle = strlen($pathinfodec);
  905. // Checks whether SCRIPT_NAME ends with PATH_INFO, URL-decoded.
  906. if (substr($_SERVER['SCRIPT_NAME'], -$lenneedle) === $pathinfodec) {
  907. // This is the "Apache 2.4.10- running PHP-FPM via mod_proxy_fcgi" fingerprint,
  908. // at least on CentOS 7 (Apache/2.4.6 PHP/5.4.16) and Ubuntu 14.04 (Apache/2.4.7 PHP/5.5.9)
  909. // => SCRIPT_NAME contains 'slash arguments' data too, which is wrongly exposed via PATH_INFO as URL-encoded.
  910. // Fix both $_SERVER['PATH_INFO'] and $_SERVER['SCRIPT_NAME'].
  911. $lenhaystack = strlen($_SERVER['SCRIPT_NAME']);
  912. $pos = $lenhaystack - $lenneedle;
  913. // Here $pos is greater than 0 but let's double check it.
  914. if ($pos > 0) {
  915. $_SERVER['PATH_INFO'] = $pathinfodec;
  916. $_SERVER['SCRIPT_NAME'] = substr($_SERVER['SCRIPT_NAME'], 0, $pos);
  917. }
  918. }
  919. }
  920. } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'iis') !== false) {
  921. //IIS - needs a lot of tweaking to make it work
  922. $rurl['fullpath'] = $_SERVER['SCRIPT_NAME'];
  923. // NOTE: we should ignore PATH_INFO because it is incorrectly encoded using 8bit filesystem legacy encoding in IIS.
  924. // Since 2.0, we rely on IIS rewrite extensions like Helicon ISAPI_rewrite
  925. // example rule: RewriteRule ^([^\?]+?\.php)(\/.+)$ $1\?file=$2 [QSA]
  926. // OR
  927. // we rely on a proper IIS 6.0+ configuration: the 'FastCGIUtf8ServerVariables' registry key.
  928. if (isset($_SERVER['PATH_INFO']) and $_SERVER['PATH_INFO'] !== '') {
  929. // Check that PATH_INFO works == must not contain the script name.
  930. if (strpos($_SERVER['PATH_INFO'], $_SERVER['SCRIPT_NAME']) === false) {
  931. $rurl['fullpath'] .= clean_param(urldecode($_SERVER['PATH_INFO']), PARAM_PATH);
  932. }
  933. }
  934. if (isset($_SERVER['QUERY_STRING']) and $_SERVER['QUERY_STRING'] !== '') {
  935. $rurl['fullpath'] .= '?'.$_SERVER['QUERY_STRING'];
  936. }
  937. $_SERVER['REQUEST_URI'] = $rurl['fullpath']; // extra IIS compatibility
  938. /* NOTE: following servers are not fully tested! */
  939. } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false) {
  940. //lighttpd - not officially supported
  941. $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded
  942. } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false) {
  943. //nginx - not officially supported
  944. if (!isset($_SERVER['SCRIPT_NAME'])) {
  945. die('Invalid server configuration detected, please try to add "fastcgi_param SCRIPT_NAME $fastcgi_script_name;" to the nginx server configuration.');
  946. }
  947. $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded
  948. } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'cherokee') !== false) {
  949. //cherokee - not officially supported
  950. $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded
  951. } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'zeus') !== false) {
  952. //zeus - not officially supported
  953. $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded
  954. } else if (stripos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false) {
  955. //LiteSpeed - not officially supported
  956. $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded
  957. } else if ($_SERVER['SERVER_SOFTWARE'] === 'HTTPD') {
  958. //obscure name found on some servers - this is definitely not supported
  959. $rurl['fullpath'] = $_SERVER['REQUEST_URI']; // TODO: verify this is always properly encoded
  960. } else if (strpos($_SERVER['SERVER_SOFTWARE'], 'PHP') === 0) {
  961. // built-in PHP Development Server
  962. $rurl['fullpath'] = $_SERVER['REQUEST_URI'];
  963. } else {
  964. throw new moodle_exception('unsupportedwebserver', 'error', '', $_SERVER['SERVER_SOFTWARE']);
  965. }
  966. // sanitize the url a bit more, the encoding style may be different in vars above
  967. $rurl['fullpath'] = str_replace('"', '%22', $rurl['fullpath']);
  968. $rurl['fullpath'] = str_replace('\'', '%27', $rurl['fullpath']);
  969. return $rurl;
  970. }
  971. /**
  972. * Try to work around the 'max_input_vars' restriction if necessary.
  973. */
  974. function workaround_max_input_vars() {
  975. // Make sure this gets executed only once from lib/setup.php!
  976. static $executed = false;
  977. if ($executed) {
  978. debugging('workaround_max_input_vars() must be called only once!');
  979. return;
  980. }
  981. $executed = true;
  982. if (!isset($_SERVER["CONTENT_TYPE"]) or strpos($_SERVER["CONTENT_TYPE"], 'multipart/form-data') !== false) {
  983. // Not a post or 'multipart/form-data' which is not compatible with "php://input" reading.
  984. return;
  985. }
  986. if (!isloggedin() or isguestuser()) {
  987. // Only real users post huge forms.
  988. return;
  989. }
  990. $max = (int)ini_get('max_input_vars');
  991. if ($max <= 0) {
  992. // Most probably PHP < 5.3.9 that does not implement this limit.
  993. return;
  994. }
  995. if ($max >= 200000) {
  996. // This value should be ok for all our forms, by setting it in php.ini
  997. // admins may prevent any unexpected regressions caused by this hack.
  998. // Note there is no need to worry about DDoS caused by making this limit very high
  999. // because there are very many easier ways to DDoS any Moodle server.
  1000. return;
  1001. }
  1002. // Worst case is advanced checkboxes which use up to two max_input_vars
  1003. // slots for each entry in $_POST, because of sending two fields with the
  1004. // same name. So count everything twice just in case.
  1005. if (count($_POST, COUNT_RECURSIVE) * 2 < $max) {
  1006. return;
  1007. }
  1008. // Large POST request with enctype supported by php://input.
  1009. // Parse php://input in chunks to bypass max_input_vars limit, which also applies to parse_str().
  1010. $str = file_get_contents("php://input");
  1011. if ($str === false or $str === '') {
  1012. // Some weird error.
  1013. return;
  1014. }
  1015. $delim = '&';
  1016. $fun = function($p) use ($delim) {
  1017. return implode($delim, $p);
  1018. };
  1019. $chunks = array_map($fun, array_chunk(explode($delim, $str), $max));
  1020. // Clear everything from existing $_POST array, otherwise it might be included
  1021. // twice (this affects array params primarily).
  1022. foreach ($_POST as $key => $value) {
  1023. unset($_POST[$key]);
  1024. // Also clear from request array - but only the things that are in $_POST,
  1025. // that way it will leave the things from a get request if any.
  1026. unset($_REQUEST[$key]);
  1027. }
  1028. foreach ($chunks as $chunk) {
  1029. $values = array();
  1030. parse_str($chunk, $values);
  1031. merge_query_params($_POST, $values);
  1032. merge_query_params($_REQUEST, $values);
  1033. }
  1034. }
  1035. /**
  1036. * Merge parsed POST chunks.
  1037. *
  1038. * NOTE: this is not perfect, but it should work in most cases hopefully.
  1039. *
  1040. * @param array $target
  1041. * @param array $values
  1042. */
  1043. function merge_query_params(array &$target, array $values) {
  1044. if (isset($values[0]) and isset($target[0])) {
  1045. // This looks like a split [] array, lets verify the keys are continuous starting with 0.
  1046. $keys1 = array_keys($values);
  1047. $keys2 = array_keys($target);
  1048. if ($keys1 === array_keys($keys1) and $keys2 === array_keys($keys2)) {
  1049. foreach ($values as $v) {
  1050. $target[] = $v;
  1051. }
  1052. return;
  1053. }
  1054. }
  1055. foreach ($values as $k => $v) {
  1056. if (!isset($target[$k])) {
  1057. $target[$k] = $v;
  1058. continue;
  1059. }
  1060. if (is_array($target[$k]) and is_array($v)) {
  1061. merge_query_params($target[$k], $v);
  1062. continue;
  1063. }
  1064. // We should not get here unless there are duplicates in params.
  1065. $target[$k] = $v;
  1066. }
  1067. }
  1068. /**
  1069. * Initializes our performance info early.
  1070. *
  1071. * Pairs up with get_performance_info() which is actually
  1072. * in moodlelib.php. This function is here so that we can
  1073. * call it before all the libs are pulled in.
  1074. *
  1075. * @uses $PERF
  1076. */
  1077. function init_performance_info() {
  1078. global $PERF, $CFG, $USER;
  1079. $PERF = new stdClass();
  1080. $PERF->logwrites = 0;
  1081. if (function_exists('microtime')) {
  1082. $PERF->starttime = microtime();
  1083. }
  1084. if (function_exists('memory_get_usage')) {
  1085. $PERF->startmemory = memory_get_usage();
  1086. }
  1087. if (function_exists('posix_times')) {
  1088. $PERF->startposixtimes = posix_times();
  1089. }
  1090. }
  1091. /**
  1092. * Indicates whether we are in the middle of the initial Moodle install.
  1093. *
  1094. * Very occasionally it is necessary avoid running certain bits of code before the
  1095. * Moodle installation has completed. The installed flag is set in admin/index.php
  1096. * after Moodle core and all the plugins have been installed, but just before
  1097. * the person doing the initial install is asked to choose the admin password.
  1098. *
  1099. * @return boolean true if the initial install is not complete.
  1100. */
  1101. function during_initial_install() {
  1102. global $CFG;
  1103. return empty($CFG->rolesactive);
  1104. }
  1105. /**
  1106. * Function to raise the memory limit to a new value.
  1107. * Will respect the memory limit if it is higher, thus allowing
  1108. * settings in php.ini, apache conf or command line switches
  1109. * to override it.
  1110. *
  1111. * The memory limit should be expressed with a constant
  1112. * MEMORY_STANDARD, MEMORY_EXTRA or MEMORY_HUGE.
  1113. * It is possible to use strings or integers too (eg:'128M').
  1114. *
  1115. * @param mixed $newlimit the new memory limit
  1116. * @return bool success
  1117. */
  1118. function raise_memory_limit($newlimit) {
  1119. global $CFG;
  1120. if ($newlimit == MEMORY_UNLIMITED) {
  1121. ini_set('memory_limit', -1);
  1122. return true;
  1123. } else if ($newlimit == MEMORY_STANDARD) {
  1124. if (PHP_INT_SIZE > 4) {
  1125. $newlimit = get_real_size('128M'); // 64bit needs more memory
  1126. } else {
  1127. $newlimit = get_real_size('96M');
  1128. }
  1129. } else if ($newlimit == MEMORY_EXTRA) {
  1130. if (PHP_INT_SIZE > 4) {
  1131. $newlimit = get_real_size('384M'); // 64bit needs more memory
  1132. } else {
  1133. $newlimit = get_real_size('256M');
  1134. }
  1135. if (!empty($CFG->extramemorylimit)) {
  1136. $extra = get_real_size($CFG->extramemorylimit);
  1137. if ($extra > $newlimit) {
  1138. $newlimit = $extra;
  1139. }
  1140. }
  1141. } else if ($newlimit == MEMORY_HUGE) {
  1142. // MEMORY_HUGE uses 2G or MEMORY_EXTRA, whichever is bigger.
  1143. $newlimit = get_real_size('2G');
  1144. if (!empty($CFG->extramemorylimit)) {
  1145. $extra = get_real_size($CFG->extramemorylimit);
  1146. if ($extra > $newlimit) {
  1147. $newlimit = $extra;
  1148. }
  1149. }
  1150. } else {
  1151. $newlimit = get_real_size($newlimit);
  1152. }
  1153. if ($newlimit <= 0) {
  1154. debugging('Invalid memory limit specified.');
  1155. return false;
  1156. }
  1157. $cur = ini_get('memory_limit');
  1158. if (empty($cur)) {
  1159. // if php is compiled without --enable-memory-limits
  1160. // apparently memory_limit is set to ''
  1161. $cur = 0;
  1162. } else {
  1163. if ($cur == -1){
  1164. return true; // unlimited mem!
  1165. }
  1166. $cur = get_real_size($cur);
  1167. }
  1168. if ($newlimit > $cur) {
  1169. ini_set('memory_limit', $newlimit);
  1170. return true;
  1171. }
  1172. return false;
  1173. }
  1174. /**
  1175. * Function to reduce the memory limit to a new value.
  1176. * Will respect the memory limit if it is lower, thus allowing
  1177. * settings in php.ini, apache conf or command line switches
  1178. * to override it
  1179. *
  1180. * The memory limit should be expressed with a string (eg:'64M')
  1181. *
  1182. * @param string $newlimit the new memory limit
  1183. * @return bool
  1184. */
  1185. function reduce_memory_limit($newlimit) {
  1186. if (empty($newlimit)) {
  1187. return false;
  1188. }
  1189. $cur = ini_get('memory_limit');
  1190. if (empty($cur)) {
  1191. // if php is compiled without --enable-memory-limits
  1192. // apparently memory_limit is set to ''
  1193. $cur = 0;
  1194. } else {
  1195. if ($cur == -1){
  1196. return true; // unlimited mem!
  1197. }
  1198. $cur = get_real_size($cur);
  1199. }
  1200. $new = get_real_size($newlimit);
  1201. // -1 is smaller, but it means unlimited
  1202. if ($new < $cur && $new != -1) {
  1203. ini_set('memory_limit', $newlimit);
  1204. return true;
  1205. }
  1206. return false;
  1207. }
  1208. /**
  1209. * Converts numbers like 10M into bytes.
  1210. *
  1211. * @param string $size The size to be converted
  1212. * @return int
  1213. */
  1214. function get_real_size($size = 0) {
  1215. if (!$size) {
  1216. return 0;
  1217. }
  1218. static $binaryprefixes = array(
  1219. 'K' => 1024 ** 1,
  1220. 'k' => 1024 ** 1,
  1221. 'M' => 1024 ** 2,
  1222. 'm' => 1024 ** 2,
  1223. 'G' => 1024 ** 3,
  1224. 'g' => 1024 ** 3,
  1225. 'T' => 1024 ** 4,
  1226. 't' => 1024 ** 4,
  1227. 'P' => 1024 ** 5,
  1228. 'p' => 1024 ** 5,
  1229. );
  1230. if (preg_match('/^([0-9]+)([KMGTP])/i', $size, $matches)) {
  1231. return $matches[1] * $binaryprefixes[$matches[2]];
  1232. }
  1233. return (int) $size;
  1234. }
  1235. /**
  1236. * Try to disable all output buffering and purge
  1237. * all headers.
  1238. *
  1239. * @access private to be called only from lib/setup.php !
  1240. * @return void
  1241. */
  1242. function disable_output_buffering() {
  1243. $olddebug = error_reporting(0);
  1244. // disable …

Large files files are truncated, but you can click here to view the full file