PageRenderTime 78ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 3ms

/lib/moodlelib.php

http://github.com/moodle/moodle
PHP | 10619 lines | 6015 code | 1289 blank | 3315 comment | 1461 complexity | 4960b8f0c2391c9dab38bf0b2328f972 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause

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. * moodlelib.php - Moodle main library
  18. *
  19. * Main library file of miscellaneous general-purpose Moodle functions.
  20. * Other main libraries:
  21. * - weblib.php - functions that produce web output
  22. * - datalib.php - functions that access the database
  23. *
  24. * @package core
  25. * @subpackage lib
  26. * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com
  27. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28. */
  29. defined('MOODLE_INTERNAL') || die();
  30. // CONSTANTS (Encased in phpdoc proper comments).
  31. // Date and time constants.
  32. /**
  33. * Time constant - the number of seconds in a year
  34. */
  35. define('YEARSECS', 31536000);
  36. /**
  37. * Time constant - the number of seconds in a week
  38. */
  39. define('WEEKSECS', 604800);
  40. /**
  41. * Time constant - the number of seconds in a day
  42. */
  43. define('DAYSECS', 86400);
  44. /**
  45. * Time constant - the number of seconds in an hour
  46. */
  47. define('HOURSECS', 3600);
  48. /**
  49. * Time constant - the number of seconds in a minute
  50. */
  51. define('MINSECS', 60);
  52. /**
  53. * Time constant - the number of minutes in a day
  54. */
  55. define('DAYMINS', 1440);
  56. /**
  57. * Time constant - the number of minutes in an hour
  58. */
  59. define('HOURMINS', 60);
  60. // Parameter constants - every call to optional_param(), required_param()
  61. // or clean_param() should have a specified type of parameter.
  62. /**
  63. * PARAM_ALPHA - contains only english ascii letters a-zA-Z.
  64. */
  65. define('PARAM_ALPHA', 'alpha');
  66. /**
  67. * PARAM_ALPHAEXT the same contents as PARAM_ALPHA plus the chars in quotes: "_-" allowed
  68. * NOTE: originally this allowed "/" too, please use PARAM_SAFEPATH if "/" needed
  69. */
  70. define('PARAM_ALPHAEXT', 'alphaext');
  71. /**
  72. * PARAM_ALPHANUM - expected numbers and letters only.
  73. */
  74. define('PARAM_ALPHANUM', 'alphanum');
  75. /**
  76. * PARAM_ALPHANUMEXT - expected numbers, letters only and _-.
  77. */
  78. define('PARAM_ALPHANUMEXT', 'alphanumext');
  79. /**
  80. * PARAM_AUTH - actually checks to make sure the string is a valid auth plugin
  81. */
  82. define('PARAM_AUTH', 'auth');
  83. /**
  84. * PARAM_BASE64 - Base 64 encoded format
  85. */
  86. define('PARAM_BASE64', 'base64');
  87. /**
  88. * PARAM_BOOL - converts input into 0 or 1, use for switches in forms and urls.
  89. */
  90. define('PARAM_BOOL', 'bool');
  91. /**
  92. * PARAM_CAPABILITY - A capability name, like 'moodle/role:manage'. Actually
  93. * checked against the list of capabilities in the database.
  94. */
  95. define('PARAM_CAPABILITY', 'capability');
  96. /**
  97. * PARAM_CLEANHTML - cleans submitted HTML code. Note that you almost never want
  98. * to use this. The normal mode of operation is to use PARAM_RAW when receiving
  99. * the input (required/optional_param or formslib) and then sanitise the HTML
  100. * using format_text on output. This is for the rare cases when you want to
  101. * sanitise the HTML on input. This cleaning may also fix xhtml strictness.
  102. */
  103. define('PARAM_CLEANHTML', 'cleanhtml');
  104. /**
  105. * PARAM_EMAIL - an email address following the RFC
  106. */
  107. define('PARAM_EMAIL', 'email');
  108. /**
  109. * PARAM_FILE - safe file name, all dangerous chars are stripped, protects against XSS, SQL injections and directory traversals
  110. */
  111. define('PARAM_FILE', 'file');
  112. /**
  113. * PARAM_FLOAT - a real/floating point number.
  114. *
  115. * Note that you should not use PARAM_FLOAT for numbers typed in by the user.
  116. * It does not work for languages that use , as a decimal separator.
  117. * Use PARAM_LOCALISEDFLOAT instead.
  118. */
  119. define('PARAM_FLOAT', 'float');
  120. /**
  121. * PARAM_LOCALISEDFLOAT - a localised real/floating point number.
  122. * This is preferred over PARAM_FLOAT for numbers typed in by the user.
  123. * Cleans localised numbers to computer readable numbers; false for invalid numbers.
  124. */
  125. define('PARAM_LOCALISEDFLOAT', 'localisedfloat');
  126. /**
  127. * PARAM_HOST - expected fully qualified domain name (FQDN) or an IPv4 dotted quad (IP address)
  128. */
  129. define('PARAM_HOST', 'host');
  130. /**
  131. * PARAM_INT - integers only, use when expecting only numbers.
  132. */
  133. define('PARAM_INT', 'int');
  134. /**
  135. * PARAM_LANG - checks to see if the string is a valid installed language in the current site.
  136. */
  137. define('PARAM_LANG', 'lang');
  138. /**
  139. * PARAM_LOCALURL - expected properly formatted URL as well as one that refers to the local server itself. (NOT orthogonal to the
  140. * others! Implies PARAM_URL!)
  141. */
  142. define('PARAM_LOCALURL', 'localurl');
  143. /**
  144. * PARAM_NOTAGS - all html tags are stripped from the text. Do not abuse this type.
  145. */
  146. define('PARAM_NOTAGS', 'notags');
  147. /**
  148. * PARAM_PATH - safe relative path name, all dangerous chars are stripped, protects against XSS, SQL injections and directory
  149. * traversals note: the leading slash is not removed, window drive letter is not allowed
  150. */
  151. define('PARAM_PATH', 'path');
  152. /**
  153. * PARAM_PEM - Privacy Enhanced Mail format
  154. */
  155. define('PARAM_PEM', 'pem');
  156. /**
  157. * PARAM_PERMISSION - A permission, one of CAP_INHERIT, CAP_ALLOW, CAP_PREVENT or CAP_PROHIBIT.
  158. */
  159. define('PARAM_PERMISSION', 'permission');
  160. /**
  161. * PARAM_RAW specifies a parameter that is not cleaned/processed in any way except the discarding of the invalid utf-8 characters
  162. */
  163. define('PARAM_RAW', 'raw');
  164. /**
  165. * PARAM_RAW_TRIMMED like PARAM_RAW but leading and trailing whitespace is stripped.
  166. */
  167. define('PARAM_RAW_TRIMMED', 'raw_trimmed');
  168. /**
  169. * PARAM_SAFEDIR - safe directory name, suitable for include() and require()
  170. */
  171. define('PARAM_SAFEDIR', 'safedir');
  172. /**
  173. * PARAM_SAFEPATH - several PARAM_SAFEDIR joined by "/", suitable for include() and require(), plugin paths, etc.
  174. */
  175. define('PARAM_SAFEPATH', 'safepath');
  176. /**
  177. * PARAM_SEQUENCE - expects a sequence of numbers like 8 to 1,5,6,4,6,8,9. Numbers and comma only.
  178. */
  179. define('PARAM_SEQUENCE', 'sequence');
  180. /**
  181. * PARAM_TAG - one tag (interests, blogs, etc.) - mostly international characters and space, <> not supported
  182. */
  183. define('PARAM_TAG', 'tag');
  184. /**
  185. * PARAM_TAGLIST - list of tags separated by commas (interests, blogs, etc.)
  186. */
  187. define('PARAM_TAGLIST', 'taglist');
  188. /**
  189. * PARAM_TEXT - general plain text compatible with multilang filter, no other html tags. Please note '<', or '>' are allowed here.
  190. */
  191. define('PARAM_TEXT', 'text');
  192. /**
  193. * PARAM_THEME - Checks to see if the string is a valid theme name in the current site
  194. */
  195. define('PARAM_THEME', 'theme');
  196. /**
  197. * PARAM_URL - expected properly formatted URL. Please note that domain part is required, http://localhost/ is not accepted but
  198. * http://localhost.localdomain/ is ok.
  199. */
  200. define('PARAM_URL', 'url');
  201. /**
  202. * PARAM_USERNAME - Clean username to only contains allowed characters. This is to be used ONLY when manually creating user
  203. * accounts, do NOT use when syncing with external systems!!
  204. */
  205. define('PARAM_USERNAME', 'username');
  206. /**
  207. * PARAM_STRINGID - used to check if the given string is valid string identifier for get_string()
  208. */
  209. define('PARAM_STRINGID', 'stringid');
  210. // DEPRECATED PARAM TYPES OR ALIASES - DO NOT USE FOR NEW CODE.
  211. /**
  212. * PARAM_CLEAN - obsoleted, please use a more specific type of parameter.
  213. * It was one of the first types, that is why it is abused so much ;-)
  214. * @deprecated since 2.0
  215. */
  216. define('PARAM_CLEAN', 'clean');
  217. /**
  218. * PARAM_INTEGER - deprecated alias for PARAM_INT
  219. * @deprecated since 2.0
  220. */
  221. define('PARAM_INTEGER', 'int');
  222. /**
  223. * PARAM_NUMBER - deprecated alias of PARAM_FLOAT
  224. * @deprecated since 2.0
  225. */
  226. define('PARAM_NUMBER', 'float');
  227. /**
  228. * PARAM_ACTION - deprecated alias for PARAM_ALPHANUMEXT, use for various actions in forms and urls
  229. * NOTE: originally alias for PARAM_APLHA
  230. * @deprecated since 2.0
  231. */
  232. define('PARAM_ACTION', 'alphanumext');
  233. /**
  234. * PARAM_FORMAT - deprecated alias for PARAM_ALPHANUMEXT, use for names of plugins, formats, etc.
  235. * NOTE: originally alias for PARAM_APLHA
  236. * @deprecated since 2.0
  237. */
  238. define('PARAM_FORMAT', 'alphanumext');
  239. /**
  240. * PARAM_MULTILANG - deprecated alias of PARAM_TEXT.
  241. * @deprecated since 2.0
  242. */
  243. define('PARAM_MULTILANG', 'text');
  244. /**
  245. * PARAM_TIMEZONE - expected timezone. Timezone can be int +-(0-13) or float +-(0.5-12.5) or
  246. * string separated by '/' and can have '-' &/ '_' (eg. America/North_Dakota/New_Salem
  247. * America/Port-au-Prince)
  248. */
  249. define('PARAM_TIMEZONE', 'timezone');
  250. /**
  251. * PARAM_CLEANFILE - deprecated alias of PARAM_FILE; originally was removing regional chars too
  252. */
  253. define('PARAM_CLEANFILE', 'file');
  254. /**
  255. * PARAM_COMPONENT is used for full component names (aka frankenstyle) such as 'mod_forum', 'core_rating', 'auth_ldap'.
  256. * Short legacy subsystem names and module names are accepted too ex: 'forum', 'rating', 'user'.
  257. * Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
  258. * NOTE: numbers and underscores are strongly discouraged in plugin names!
  259. */
  260. define('PARAM_COMPONENT', 'component');
  261. /**
  262. * PARAM_AREA is a name of area used when addressing files, comments, ratings, etc.
  263. * It is usually used together with context id and component.
  264. * Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
  265. */
  266. define('PARAM_AREA', 'area');
  267. /**
  268. * PARAM_PLUGIN is used for plugin names such as 'forum', 'glossary', 'ldap', 'paypal', 'completionstatus'.
  269. * Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
  270. * NOTE: numbers and underscores are strongly discouraged in plugin names! Underscores are forbidden in module names.
  271. */
  272. define('PARAM_PLUGIN', 'plugin');
  273. // Web Services.
  274. /**
  275. * VALUE_REQUIRED - if the parameter is not supplied, there is an error
  276. */
  277. define('VALUE_REQUIRED', 1);
  278. /**
  279. * VALUE_OPTIONAL - if the parameter is not supplied, then the param has no value
  280. */
  281. define('VALUE_OPTIONAL', 2);
  282. /**
  283. * VALUE_DEFAULT - if the parameter is not supplied, then the default value is used
  284. */
  285. define('VALUE_DEFAULT', 0);
  286. /**
  287. * NULL_NOT_ALLOWED - the parameter can not be set to null in the database
  288. */
  289. define('NULL_NOT_ALLOWED', false);
  290. /**
  291. * NULL_ALLOWED - the parameter can be set to null in the database
  292. */
  293. define('NULL_ALLOWED', true);
  294. // Page types.
  295. /**
  296. * PAGE_COURSE_VIEW is a definition of a page type. For more information on the page class see moodle/lib/pagelib.php.
  297. */
  298. define('PAGE_COURSE_VIEW', 'course-view');
  299. /** Get remote addr constant */
  300. define('GETREMOTEADDR_SKIP_HTTP_CLIENT_IP', '1');
  301. /** Get remote addr constant */
  302. define('GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR', '2');
  303. // Blog access level constant declaration.
  304. define ('BLOG_USER_LEVEL', 1);
  305. define ('BLOG_GROUP_LEVEL', 2);
  306. define ('BLOG_COURSE_LEVEL', 3);
  307. define ('BLOG_SITE_LEVEL', 4);
  308. define ('BLOG_GLOBAL_LEVEL', 5);
  309. // Tag constants.
  310. /**
  311. * To prevent problems with multibytes strings,Flag updating in nav not working on the review page. this should not exceed the
  312. * length of "varchar(255) / 3 (bytes / utf-8 character) = 85".
  313. * TODO: this is not correct, varchar(255) are 255 unicode chars ;-)
  314. *
  315. * @todo define(TAG_MAX_LENGTH) this is not correct, varchar(255) are 255 unicode chars ;-)
  316. */
  317. define('TAG_MAX_LENGTH', 50);
  318. // Password policy constants.
  319. define ('PASSWORD_LOWER', 'abcdefghijklmnopqrstuvwxyz');
  320. define ('PASSWORD_UPPER', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
  321. define ('PASSWORD_DIGITS', '0123456789');
  322. define ('PASSWORD_NONALPHANUM', '.,;:!?_-+/*@#&$');
  323. // Feature constants.
  324. // Used for plugin_supports() to report features that are, or are not, supported by a module.
  325. /** True if module can provide a grade */
  326. define('FEATURE_GRADE_HAS_GRADE', 'grade_has_grade');
  327. /** True if module supports outcomes */
  328. define('FEATURE_GRADE_OUTCOMES', 'outcomes');
  329. /** True if module supports advanced grading methods */
  330. define('FEATURE_ADVANCED_GRADING', 'grade_advanced_grading');
  331. /** True if module controls the grade visibility over the gradebook */
  332. define('FEATURE_CONTROLS_GRADE_VISIBILITY', 'controlsgradevisbility');
  333. /** True if module supports plagiarism plugins */
  334. define('FEATURE_PLAGIARISM', 'plagiarism');
  335. /** True if module has code to track whether somebody viewed it */
  336. define('FEATURE_COMPLETION_TRACKS_VIEWS', 'completion_tracks_views');
  337. /** True if module has custom completion rules */
  338. define('FEATURE_COMPLETION_HAS_RULES', 'completion_has_rules');
  339. /** True if module has no 'view' page (like label) */
  340. define('FEATURE_NO_VIEW_LINK', 'viewlink');
  341. /** True (which is default) if the module wants support for setting the ID number for grade calculation purposes. */
  342. define('FEATURE_IDNUMBER', 'idnumber');
  343. /** True if module supports groups */
  344. define('FEATURE_GROUPS', 'groups');
  345. /** True if module supports groupings */
  346. define('FEATURE_GROUPINGS', 'groupings');
  347. /**
  348. * True if module supports groupmembersonly (which no longer exists)
  349. * @deprecated Since Moodle 2.8
  350. */
  351. define('FEATURE_GROUPMEMBERSONLY', 'groupmembersonly');
  352. /** Type of module */
  353. define('FEATURE_MOD_ARCHETYPE', 'mod_archetype');
  354. /** True if module supports intro editor */
  355. define('FEATURE_MOD_INTRO', 'mod_intro');
  356. /** True if module has default completion */
  357. define('FEATURE_MODEDIT_DEFAULT_COMPLETION', 'modedit_default_completion');
  358. define('FEATURE_COMMENT', 'comment');
  359. define('FEATURE_RATE', 'rate');
  360. /** True if module supports backup/restore of moodle2 format */
  361. define('FEATURE_BACKUP_MOODLE2', 'backup_moodle2');
  362. /** True if module can show description on course main page */
  363. define('FEATURE_SHOW_DESCRIPTION', 'showdescription');
  364. /** True if module uses the question bank */
  365. define('FEATURE_USES_QUESTIONS', 'usesquestions');
  366. /**
  367. * Maximum filename char size
  368. */
  369. define('MAX_FILENAME_SIZE', 100);
  370. /** Unspecified module archetype */
  371. define('MOD_ARCHETYPE_OTHER', 0);
  372. /** Resource-like type module */
  373. define('MOD_ARCHETYPE_RESOURCE', 1);
  374. /** Assignment module archetype */
  375. define('MOD_ARCHETYPE_ASSIGNMENT', 2);
  376. /** System (not user-addable) module archetype */
  377. define('MOD_ARCHETYPE_SYSTEM', 3);
  378. /**
  379. * Security token used for allowing access
  380. * from external application such as web services.
  381. * Scripts do not use any session, performance is relatively
  382. * low because we need to load access info in each request.
  383. * Scripts are executed in parallel.
  384. */
  385. define('EXTERNAL_TOKEN_PERMANENT', 0);
  386. /**
  387. * Security token used for allowing access
  388. * of embedded applications, the code is executed in the
  389. * active user session. Token is invalidated after user logs out.
  390. * Scripts are executed serially - normal session locking is used.
  391. */
  392. define('EXTERNAL_TOKEN_EMBEDDED', 1);
  393. /**
  394. * The home page should be the site home
  395. */
  396. define('HOMEPAGE_SITE', 0);
  397. /**
  398. * The home page should be the users my page
  399. */
  400. define('HOMEPAGE_MY', 1);
  401. /**
  402. * The home page can be chosen by the user
  403. */
  404. define('HOMEPAGE_USER', 2);
  405. /**
  406. * URL of the Moodle sites registration portal.
  407. */
  408. defined('HUB_MOODLEORGHUBURL') || define('HUB_MOODLEORGHUBURL', 'https://stats.moodle.org');
  409. /**
  410. * Moodle mobile app service name
  411. */
  412. define('MOODLE_OFFICIAL_MOBILE_SERVICE', 'moodle_mobile_app');
  413. /**
  414. * Indicates the user has the capabilities required to ignore activity and course file size restrictions
  415. */
  416. define('USER_CAN_IGNORE_FILE_SIZE_LIMITS', -1);
  417. /**
  418. * Course display settings: display all sections on one page.
  419. */
  420. define('COURSE_DISPLAY_SINGLEPAGE', 0);
  421. /**
  422. * Course display settings: split pages into a page per section.
  423. */
  424. define('COURSE_DISPLAY_MULTIPAGE', 1);
  425. /**
  426. * Authentication constant: String used in password field when password is not stored.
  427. */
  428. define('AUTH_PASSWORD_NOT_CACHED', 'not cached');
  429. /**
  430. * Email from header to never include via information.
  431. */
  432. define('EMAIL_VIA_NEVER', 0);
  433. /**
  434. * Email from header to always include via information.
  435. */
  436. define('EMAIL_VIA_ALWAYS', 1);
  437. /**
  438. * Email from header to only include via information if the address is no-reply.
  439. */
  440. define('EMAIL_VIA_NO_REPLY_ONLY', 2);
  441. // PARAMETER HANDLING.
  442. /**
  443. * Returns a particular value for the named variable, taken from
  444. * POST or GET. If the parameter doesn't exist then an error is
  445. * thrown because we require this variable.
  446. *
  447. * This function should be used to initialise all required values
  448. * in a script that are based on parameters. Usually it will be
  449. * used like this:
  450. * $id = required_param('id', PARAM_INT);
  451. *
  452. * Please note the $type parameter is now required and the value can not be array.
  453. *
  454. * @param string $parname the name of the page parameter we want
  455. * @param string $type expected type of parameter
  456. * @return mixed
  457. * @throws coding_exception
  458. */
  459. function required_param($parname, $type) {
  460. if (func_num_args() != 2 or empty($parname) or empty($type)) {
  461. throw new coding_exception('required_param() requires $parname and $type to be specified (parameter: '.$parname.')');
  462. }
  463. // POST has precedence.
  464. if (isset($_POST[$parname])) {
  465. $param = $_POST[$parname];
  466. } else if (isset($_GET[$parname])) {
  467. $param = $_GET[$parname];
  468. } else {
  469. print_error('missingparam', '', '', $parname);
  470. }
  471. if (is_array($param)) {
  472. debugging('Invalid array parameter detected in required_param(): '.$parname);
  473. // TODO: switch to fatal error in Moodle 2.3.
  474. return required_param_array($parname, $type);
  475. }
  476. return clean_param($param, $type);
  477. }
  478. /**
  479. * Returns a particular array value for the named variable, taken from
  480. * POST or GET. If the parameter doesn't exist then an error is
  481. * thrown because we require this variable.
  482. *
  483. * This function should be used to initialise all required values
  484. * in a script that are based on parameters. Usually it will be
  485. * used like this:
  486. * $ids = required_param_array('ids', PARAM_INT);
  487. *
  488. * Note: arrays of arrays are not supported, only alphanumeric keys with _ and - are supported
  489. *
  490. * @param string $parname the name of the page parameter we want
  491. * @param string $type expected type of parameter
  492. * @return array
  493. * @throws coding_exception
  494. */
  495. function required_param_array($parname, $type) {
  496. if (func_num_args() != 2 or empty($parname) or empty($type)) {
  497. throw new coding_exception('required_param_array() requires $parname and $type to be specified (parameter: '.$parname.')');
  498. }
  499. // POST has precedence.
  500. if (isset($_POST[$parname])) {
  501. $param = $_POST[$parname];
  502. } else if (isset($_GET[$parname])) {
  503. $param = $_GET[$parname];
  504. } else {
  505. print_error('missingparam', '', '', $parname);
  506. }
  507. if (!is_array($param)) {
  508. print_error('missingparam', '', '', $parname);
  509. }
  510. $result = array();
  511. foreach ($param as $key => $value) {
  512. if (!preg_match('/^[a-z0-9_-]+$/i', $key)) {
  513. debugging('Invalid key name in required_param_array() detected: '.$key.', parameter: '.$parname);
  514. continue;
  515. }
  516. $result[$key] = clean_param($value, $type);
  517. }
  518. return $result;
  519. }
  520. /**
  521. * Returns a particular value for the named variable, taken from
  522. * POST or GET, otherwise returning a given default.
  523. *
  524. * This function should be used to initialise all optional values
  525. * in a script that are based on parameters. Usually it will be
  526. * used like this:
  527. * $name = optional_param('name', 'Fred', PARAM_TEXT);
  528. *
  529. * Please note the $type parameter is now required and the value can not be array.
  530. *
  531. * @param string $parname the name of the page parameter we want
  532. * @param mixed $default the default value to return if nothing is found
  533. * @param string $type expected type of parameter
  534. * @return mixed
  535. * @throws coding_exception
  536. */
  537. function optional_param($parname, $default, $type) {
  538. if (func_num_args() != 3 or empty($parname) or empty($type)) {
  539. throw new coding_exception('optional_param requires $parname, $default + $type to be specified (parameter: '.$parname.')');
  540. }
  541. // POST has precedence.
  542. if (isset($_POST[$parname])) {
  543. $param = $_POST[$parname];
  544. } else if (isset($_GET[$parname])) {
  545. $param = $_GET[$parname];
  546. } else {
  547. return $default;
  548. }
  549. if (is_array($param)) {
  550. debugging('Invalid array parameter detected in required_param(): '.$parname);
  551. // TODO: switch to $default in Moodle 2.3.
  552. return optional_param_array($parname, $default, $type);
  553. }
  554. return clean_param($param, $type);
  555. }
  556. /**
  557. * Returns a particular array value for the named variable, taken from
  558. * POST or GET, otherwise returning a given default.
  559. *
  560. * This function should be used to initialise all optional values
  561. * in a script that are based on parameters. Usually it will be
  562. * used like this:
  563. * $ids = optional_param('id', array(), PARAM_INT);
  564. *
  565. * Note: arrays of arrays are not supported, only alphanumeric keys with _ and - are supported
  566. *
  567. * @param string $parname the name of the page parameter we want
  568. * @param mixed $default the default value to return if nothing is found
  569. * @param string $type expected type of parameter
  570. * @return array
  571. * @throws coding_exception
  572. */
  573. function optional_param_array($parname, $default, $type) {
  574. if (func_num_args() != 3 or empty($parname) or empty($type)) {
  575. throw new coding_exception('optional_param_array requires $parname, $default + $type to be specified (parameter: '.$parname.')');
  576. }
  577. // POST has precedence.
  578. if (isset($_POST[$parname])) {
  579. $param = $_POST[$parname];
  580. } else if (isset($_GET[$parname])) {
  581. $param = $_GET[$parname];
  582. } else {
  583. return $default;
  584. }
  585. if (!is_array($param)) {
  586. debugging('optional_param_array() expects array parameters only: '.$parname);
  587. return $default;
  588. }
  589. $result = array();
  590. foreach ($param as $key => $value) {
  591. if (!preg_match('/^[a-z0-9_-]+$/i', $key)) {
  592. debugging('Invalid key name in optional_param_array() detected: '.$key.', parameter: '.$parname);
  593. continue;
  594. }
  595. $result[$key] = clean_param($value, $type);
  596. }
  597. return $result;
  598. }
  599. /**
  600. * Strict validation of parameter values, the values are only converted
  601. * to requested PHP type. Internally it is using clean_param, the values
  602. * before and after cleaning must be equal - otherwise
  603. * an invalid_parameter_exception is thrown.
  604. * Objects and classes are not accepted.
  605. *
  606. * @param mixed $param
  607. * @param string $type PARAM_ constant
  608. * @param bool $allownull are nulls valid value?
  609. * @param string $debuginfo optional debug information
  610. * @return mixed the $param value converted to PHP type
  611. * @throws invalid_parameter_exception if $param is not of given type
  612. */
  613. function validate_param($param, $type, $allownull=NULL_NOT_ALLOWED, $debuginfo='') {
  614. if (is_null($param)) {
  615. if ($allownull == NULL_ALLOWED) {
  616. return null;
  617. } else {
  618. throw new invalid_parameter_exception($debuginfo);
  619. }
  620. }
  621. if (is_array($param) or is_object($param)) {
  622. throw new invalid_parameter_exception($debuginfo);
  623. }
  624. $cleaned = clean_param($param, $type);
  625. if ($type == PARAM_FLOAT) {
  626. // Do not detect precision loss here.
  627. if (is_float($param) or is_int($param)) {
  628. // These always fit.
  629. } else if (!is_numeric($param) or !preg_match('/^[\+-]?[0-9]*\.?[0-9]*(e[-+]?[0-9]+)?$/i', (string)$param)) {
  630. throw new invalid_parameter_exception($debuginfo);
  631. }
  632. } else if ((string)$param !== (string)$cleaned) {
  633. // Conversion to string is usually lossless.
  634. throw new invalid_parameter_exception($debuginfo);
  635. }
  636. return $cleaned;
  637. }
  638. /**
  639. * Makes sure array contains only the allowed types, this function does not validate array key names!
  640. *
  641. * <code>
  642. * $options = clean_param($options, PARAM_INT);
  643. * </code>
  644. *
  645. * @param array $param the variable array we are cleaning
  646. * @param string $type expected format of param after cleaning.
  647. * @param bool $recursive clean recursive arrays
  648. * @return array
  649. * @throws coding_exception
  650. */
  651. function clean_param_array(array $param = null, $type, $recursive = false) {
  652. // Convert null to empty array.
  653. $param = (array)$param;
  654. foreach ($param as $key => $value) {
  655. if (is_array($value)) {
  656. if ($recursive) {
  657. $param[$key] = clean_param_array($value, $type, true);
  658. } else {
  659. throw new coding_exception('clean_param_array can not process multidimensional arrays when $recursive is false.');
  660. }
  661. } else {
  662. $param[$key] = clean_param($value, $type);
  663. }
  664. }
  665. return $param;
  666. }
  667. /**
  668. * Used by {@link optional_param()} and {@link required_param()} to
  669. * clean the variables and/or cast to specific types, based on
  670. * an options field.
  671. * <code>
  672. * $course->format = clean_param($course->format, PARAM_ALPHA);
  673. * $selectedgradeitem = clean_param($selectedgradeitem, PARAM_INT);
  674. * </code>
  675. *
  676. * @param mixed $param the variable we are cleaning
  677. * @param string $type expected format of param after cleaning.
  678. * @return mixed
  679. * @throws coding_exception
  680. */
  681. function clean_param($param, $type) {
  682. global $CFG;
  683. if (is_array($param)) {
  684. throw new coding_exception('clean_param() can not process arrays, please use clean_param_array() instead.');
  685. } else if (is_object($param)) {
  686. if (method_exists($param, '__toString')) {
  687. $param = $param->__toString();
  688. } else {
  689. throw new coding_exception('clean_param() can not process objects, please use clean_param_array() instead.');
  690. }
  691. }
  692. switch ($type) {
  693. case PARAM_RAW:
  694. // No cleaning at all.
  695. $param = fix_utf8($param);
  696. return $param;
  697. case PARAM_RAW_TRIMMED:
  698. // No cleaning, but strip leading and trailing whitespace.
  699. $param = fix_utf8($param);
  700. return trim($param);
  701. case PARAM_CLEAN:
  702. // General HTML cleaning, try to use more specific type if possible this is deprecated!
  703. // Please use more specific type instead.
  704. if (is_numeric($param)) {
  705. return $param;
  706. }
  707. $param = fix_utf8($param);
  708. // Sweep for scripts, etc.
  709. return clean_text($param);
  710. case PARAM_CLEANHTML:
  711. // Clean html fragment.
  712. $param = fix_utf8($param);
  713. // Sweep for scripts, etc.
  714. $param = clean_text($param, FORMAT_HTML);
  715. return trim($param);
  716. case PARAM_INT:
  717. // Convert to integer.
  718. return (int)$param;
  719. case PARAM_FLOAT:
  720. // Convert to float.
  721. return (float)$param;
  722. case PARAM_LOCALISEDFLOAT:
  723. // Convert to float.
  724. return unformat_float($param, true);
  725. case PARAM_ALPHA:
  726. // Remove everything not `a-z`.
  727. return preg_replace('/[^a-zA-Z]/i', '', $param);
  728. case PARAM_ALPHAEXT:
  729. // Remove everything not `a-zA-Z_-` (originally allowed "/" too).
  730. return preg_replace('/[^a-zA-Z_-]/i', '', $param);
  731. case PARAM_ALPHANUM:
  732. // Remove everything not `a-zA-Z0-9`.
  733. return preg_replace('/[^A-Za-z0-9]/i', '', $param);
  734. case PARAM_ALPHANUMEXT:
  735. // Remove everything not `a-zA-Z0-9_-`.
  736. return preg_replace('/[^A-Za-z0-9_-]/i', '', $param);
  737. case PARAM_SEQUENCE:
  738. // Remove everything not `0-9,`.
  739. return preg_replace('/[^0-9,]/i', '', $param);
  740. case PARAM_BOOL:
  741. // Convert to 1 or 0.
  742. $tempstr = strtolower($param);
  743. if ($tempstr === 'on' or $tempstr === 'yes' or $tempstr === 'true') {
  744. $param = 1;
  745. } else if ($tempstr === 'off' or $tempstr === 'no' or $tempstr === 'false') {
  746. $param = 0;
  747. } else {
  748. $param = empty($param) ? 0 : 1;
  749. }
  750. return $param;
  751. case PARAM_NOTAGS:
  752. // Strip all tags.
  753. $param = fix_utf8($param);
  754. return strip_tags($param);
  755. case PARAM_TEXT:
  756. // Leave only tags needed for multilang.
  757. $param = fix_utf8($param);
  758. // If the multilang syntax is not correct we strip all tags because it would break xhtml strict which is required
  759. // for accessibility standards please note this cleaning does not strip unbalanced '>' for BC compatibility reasons.
  760. do {
  761. if (strpos($param, '</lang>') !== false) {
  762. // Old and future mutilang syntax.
  763. $param = strip_tags($param, '<lang>');
  764. if (!preg_match_all('/<.*>/suU', $param, $matches)) {
  765. break;
  766. }
  767. $open = false;
  768. foreach ($matches[0] as $match) {
  769. if ($match === '</lang>') {
  770. if ($open) {
  771. $open = false;
  772. continue;
  773. } else {
  774. break 2;
  775. }
  776. }
  777. if (!preg_match('/^<lang lang="[a-zA-Z0-9_-]+"\s*>$/u', $match)) {
  778. break 2;
  779. } else {
  780. $open = true;
  781. }
  782. }
  783. if ($open) {
  784. break;
  785. }
  786. return $param;
  787. } else if (strpos($param, '</span>') !== false) {
  788. // Current problematic multilang syntax.
  789. $param = strip_tags($param, '<span>');
  790. if (!preg_match_all('/<.*>/suU', $param, $matches)) {
  791. break;
  792. }
  793. $open = false;
  794. foreach ($matches[0] as $match) {
  795. if ($match === '</span>') {
  796. if ($open) {
  797. $open = false;
  798. continue;
  799. } else {
  800. break 2;
  801. }
  802. }
  803. if (!preg_match('/^<span(\s+lang="[a-zA-Z0-9_-]+"|\s+class="multilang"){2}\s*>$/u', $match)) {
  804. break 2;
  805. } else {
  806. $open = true;
  807. }
  808. }
  809. if ($open) {
  810. break;
  811. }
  812. return $param;
  813. }
  814. } while (false);
  815. // Easy, just strip all tags, if we ever want to fix orphaned '&' we have to do that in format_string().
  816. return strip_tags($param);
  817. case PARAM_COMPONENT:
  818. // We do not want any guessing here, either the name is correct or not
  819. // please note only normalised component names are accepted.
  820. if (!preg_match('/^[a-z][a-z0-9]*(_[a-z][a-z0-9_]*)?[a-z0-9]+$/', $param)) {
  821. return '';
  822. }
  823. if (strpos($param, '__') !== false) {
  824. return '';
  825. }
  826. if (strpos($param, 'mod_') === 0) {
  827. // Module names must not contain underscores because we need to differentiate them from invalid plugin types.
  828. if (substr_count($param, '_') != 1) {
  829. return '';
  830. }
  831. }
  832. return $param;
  833. case PARAM_PLUGIN:
  834. case PARAM_AREA:
  835. // We do not want any guessing here, either the name is correct or not.
  836. if (!is_valid_plugin_name($param)) {
  837. return '';
  838. }
  839. return $param;
  840. case PARAM_SAFEDIR:
  841. // Remove everything not a-zA-Z0-9_- .
  842. return preg_replace('/[^a-zA-Z0-9_-]/i', '', $param);
  843. case PARAM_SAFEPATH:
  844. // Remove everything not a-zA-Z0-9/_- .
  845. return preg_replace('/[^a-zA-Z0-9\/_-]/i', '', $param);
  846. case PARAM_FILE:
  847. // Strip all suspicious characters from filename.
  848. $param = fix_utf8($param);
  849. $param = preg_replace('~[[:cntrl:]]|[&<>"`\|\':\\\\/]~u', '', $param);
  850. if ($param === '.' || $param === '..') {
  851. $param = '';
  852. }
  853. return $param;
  854. case PARAM_PATH:
  855. // Strip all suspicious characters from file path.
  856. $param = fix_utf8($param);
  857. $param = str_replace('\\', '/', $param);
  858. // Explode the path and clean each element using the PARAM_FILE rules.
  859. $breadcrumb = explode('/', $param);
  860. foreach ($breadcrumb as $key => $crumb) {
  861. if ($crumb === '.' && $key === 0) {
  862. // Special condition to allow for relative current path such as ./currentdirfile.txt.
  863. } else {
  864. $crumb = clean_param($crumb, PARAM_FILE);
  865. }
  866. $breadcrumb[$key] = $crumb;
  867. }
  868. $param = implode('/', $breadcrumb);
  869. // Remove multiple current path (./././) and multiple slashes (///).
  870. $param = preg_replace('~//+~', '/', $param);
  871. $param = preg_replace('~/(\./)+~', '/', $param);
  872. return $param;
  873. case PARAM_HOST:
  874. // Allow FQDN or IPv4 dotted quad.
  875. $param = preg_replace('/[^\.\d\w-]/', '', $param );
  876. // Match ipv4 dotted quad.
  877. if (preg_match('/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/', $param, $match)) {
  878. // Confirm values are ok.
  879. if ( $match[0] > 255
  880. || $match[1] > 255
  881. || $match[3] > 255
  882. || $match[4] > 255 ) {
  883. // Hmmm, what kind of dotted quad is this?
  884. $param = '';
  885. }
  886. } else if ( preg_match('/^[\w\d\.-]+$/', $param) // Dots, hyphens, numbers.
  887. && !preg_match('/^[\.-]/', $param) // No leading dots/hyphens.
  888. && !preg_match('/[\.-]$/', $param) // No trailing dots/hyphens.
  889. ) {
  890. // All is ok - $param is respected.
  891. } else {
  892. // All is not ok...
  893. $param='';
  894. }
  895. return $param;
  896. case PARAM_URL:
  897. // Allow safe urls.
  898. $param = fix_utf8($param);
  899. include_once($CFG->dirroot . '/lib/validateurlsyntax.php');
  900. if (!empty($param) && validateUrlSyntax($param, 's?H?S?F?E-u-P-a?I?p?f?q?r?')) {
  901. // All is ok, param is respected.
  902. } else {
  903. // Not really ok.
  904. $param ='';
  905. }
  906. return $param;
  907. case PARAM_LOCALURL:
  908. // Allow http absolute, root relative and relative URLs within wwwroot.
  909. $param = clean_param($param, PARAM_URL);
  910. if (!empty($param)) {
  911. if ($param === $CFG->wwwroot) {
  912. // Exact match;
  913. } else if (preg_match(':^/:', $param)) {
  914. // Root-relative, ok!
  915. } else if (preg_match('/^' . preg_quote($CFG->wwwroot . '/', '/') . '/i', $param)) {
  916. // Absolute, and matches our wwwroot.
  917. } else {
  918. // Relative - let's make sure there are no tricks.
  919. if (validateUrlSyntax('/' . $param, 's-u-P-a-p-f+q?r?')) {
  920. // Looks ok.
  921. } else {
  922. $param = '';
  923. }
  924. }
  925. }
  926. return $param;
  927. case PARAM_PEM:
  928. $param = trim($param);
  929. // PEM formatted strings may contain letters/numbers and the symbols:
  930. // forward slash: /
  931. // plus sign: +
  932. // equal sign: =
  933. // , surrounded by BEGIN and END CERTIFICATE prefix and suffixes.
  934. if (preg_match('/^-----BEGIN CERTIFICATE-----([\s\w\/\+=]+)-----END CERTIFICATE-----$/', trim($param), $matches)) {
  935. list($wholething, $body) = $matches;
  936. unset($wholething, $matches);
  937. $b64 = clean_param($body, PARAM_BASE64);
  938. if (!empty($b64)) {
  939. return "-----BEGIN CERTIFICATE-----\n$b64\n-----END CERTIFICATE-----\n";
  940. } else {
  941. return '';
  942. }
  943. }
  944. return '';
  945. case PARAM_BASE64:
  946. if (!empty($param)) {
  947. // PEM formatted strings may contain letters/numbers and the symbols
  948. // forward slash: /
  949. // plus sign: +
  950. // equal sign: =.
  951. if (0 >= preg_match('/^([\s\w\/\+=]+)$/', trim($param))) {
  952. return '';
  953. }
  954. $lines = preg_split('/[\s]+/', $param, -1, PREG_SPLIT_NO_EMPTY);
  955. // Each line of base64 encoded data must be 64 characters in length, except for the last line which may be less
  956. // than (or equal to) 64 characters long.
  957. for ($i=0, $j=count($lines); $i < $j; $i++) {
  958. if ($i + 1 == $j) {
  959. if (64 < strlen($lines[$i])) {
  960. return '';
  961. }
  962. continue;
  963. }
  964. if (64 != strlen($lines[$i])) {
  965. return '';
  966. }
  967. }
  968. return implode("\n", $lines);
  969. } else {
  970. return '';
  971. }
  972. case PARAM_TAG:
  973. $param = fix_utf8($param);
  974. // Please note it is not safe to use the tag name directly anywhere,
  975. // it must be processed with s(), urlencode() before embedding anywhere.
  976. // Remove some nasties.
  977. $param = preg_replace('~[[:cntrl:]]|[<>`]~u', '', $param);
  978. // Convert many whitespace chars into one.
  979. $param = preg_replace('/\s+/u', ' ', $param);
  980. $param = core_text::substr(trim($param), 0, TAG_MAX_LENGTH);
  981. return $param;
  982. case PARAM_TAGLIST:
  983. $param = fix_utf8($param);
  984. $tags = explode(',', $param);
  985. $result = array();
  986. foreach ($tags as $tag) {
  987. $res = clean_param($tag, PARAM_TAG);
  988. if ($res !== '') {
  989. $result[] = $res;
  990. }
  991. }
  992. if ($result) {
  993. return implode(',', $result);
  994. } else {
  995. return '';
  996. }
  997. case PARAM_CAPABILITY:
  998. if (get_capability_info($param)) {
  999. return $param;
  1000. } else {
  1001. return '';
  1002. }
  1003. case PARAM_PERMISSION:
  1004. $param = (int)$param;
  1005. if (in_array($param, array(CAP_INHERIT, CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT))) {
  1006. return $param;
  1007. } else {
  1008. return CAP_INHERIT;
  1009. }
  1010. case PARAM_AUTH:
  1011. $param = clean_param($param, PARAM_PLUGIN);
  1012. if (empty($param)) {
  1013. return '';
  1014. } else if (exists_auth_plugin($param)) {
  1015. return $param;
  1016. } else {
  1017. return '';
  1018. }
  1019. case PARAM_LANG:
  1020. $param = clean_param($param, PARAM_SAFEDIR);
  1021. if (get_string_manager()->translation_exists($param)) {
  1022. return $param;
  1023. } else {
  1024. // Specified language is not installed or param malformed.
  1025. return '';
  1026. }
  1027. case PARAM_THEME:
  1028. $param = clean_param($param, PARAM_PLUGIN);
  1029. if (empty($param)) {
  1030. return '';
  1031. } else if (file_exists("$CFG->dirroot/theme/$param/config.php")) {
  1032. return $param;
  1033. } else if (!empty($CFG->themedir) and file_exists("$CFG->themedir/$param/config.php")) {
  1034. return $param;
  1035. } else {
  1036. // Specified theme is not installed.
  1037. return '';
  1038. }
  1039. case PARAM_USERNAME:
  1040. $param = fix_utf8($param);
  1041. $param = trim($param);
  1042. // Convert uppercase to lowercase MDL-16919.
  1043. $param = core_text::strtolower($param);
  1044. if (empty($CFG->extendedusernamechars)) {
  1045. $param = str_replace(" " , "", $param);
  1046. // Regular expression, eliminate all chars EXCEPT:
  1047. // alphanum, dash (-), underscore (_), at sign (@) and period (.) characters.
  1048. $param = preg_replace('/[^-\.@_a-z0-9]/', '', $param);
  1049. }
  1050. return $param;
  1051. case PARAM_EMAIL:
  1052. $param = fix_utf8($param);
  1053. if (validate_email($param)) {
  1054. return $param;
  1055. } else {
  1056. return '';
  1057. }
  1058. case PARAM_STRINGID:
  1059. if (preg_match('|^[a-zA-Z][a-zA-Z0-9\.:/_-]*$|', $param)) {
  1060. return $param;
  1061. } else {
  1062. return '';
  1063. }
  1064. case PARAM_TIMEZONE:
  1065. // Can be int, float(with .5 or .0) or string seperated by '/' and can have '-_'.
  1066. $param = fix_utf8($param);
  1067. $timezonepattern = '/^(([+-]?(0?[0-9](\.[5|0])?|1[0-3](\.0)?|1[0-2]\.5))|(99)|[[:alnum:]]+(\/?[[:alpha:]_-])+)$/';
  1068. if (preg_match($timezonepattern, $param)) {
  1069. return $param;
  1070. } else {
  1071. return '';
  1072. }
  1073. default:
  1074. // Doh! throw error, switched parameters in optional_param or another serious problem.
  1075. print_error("unknownparamtype", '', '', $type);
  1076. }
  1077. }
  1078. /**
  1079. * Whether the PARAM_* type is compatible in RTL.
  1080. *
  1081. * Being compatible with RTL means that the data they contain can flow
  1082. * from right-to-left or left-to-right without compromising the user experience.
  1083. *
  1084. * Take URLs for example, they are not RTL compatible as they should always
  1085. * flow from the left to the right. This also applies to numbers, email addresses,
  1086. * configuration snippets, base64 strings, etc...
  1087. *
  1088. * This function tries to best guess which parameters can contain localised strings.
  1089. *
  1090. * @param string $paramtype Constant PARAM_*.
  1091. * @return bool
  1092. */
  1093. function is_rtl_compatible($paramtype) {
  1094. return $paramtype == PARAM_TEXT || $paramtype == PARAM_NOTAGS;
  1095. }
  1096. /**
  1097. * Makes sure the data is using valid utf8, invalid characters are discarded.
  1098. *
  1099. * Note: this function is not intended for full objects with methods and private properties.
  1100. *
  1101. * @param mixed $value
  1102. * @return mixed with proper utf-8 encoding
  1103. */
  1104. function fix_utf8($value) {
  1105. if (is_null($value) or $value === '') {
  1106. return $value;
  1107. } else if (is_string($value)) {
  1108. if ((string)(int)$value === $value) {
  1109. // Shortcut.
  1110. return $value;
  1111. }
  1112. // No null bytes expected in our data, so let's remove it.
  1113. $value = str_replace("\0", '', $value);
  1114. // Note: this duplicates min_fix_utf8() intentionally.
  1115. static $buggyiconv = null;
  1116. if ($buggyiconv === null) {
  1117. $buggyiconv = (!function_exists('iconv') or @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
  1118. }
  1119. if ($buggyiconv) {
  1120. if (function_exists('mb_convert_encoding')) {
  1121. $subst = mb_substitute_character();
  1122. mb_substitute_character('');
  1123. $result = mb_convert_encoding($value, 'utf-8', 'utf-8');
  1124. mb_substitute_character($subst);
  1125. } else {
  1126. // Warn admins on admin/index.php page.
  1127. $result = $value;
  1128. }
  1129. } else {
  1130. $result = @iconv('UTF-8', 'UTF-8//IGNORE', $value);
  1131. }
  1132. return $result;
  1133. } else if (is_array($value)) {
  1134. foreach ($value as $k => $v) {
  1135. $value[$k] = fix_utf8($v);
  1136. }
  1137. return $value;
  1138. } else if (is_object($value)) {
  1139. // Do not modify original.
  1140. $value = clone($value);
  1141. foreach ($value as $k => $v) {
  1142. $value->$k = fix_utf8($v);
  1143. }
  1144. return $value;
  1145. } else {
  1146. // This is some other type, no utf-8 here.
  1147. return $value;
  1148. }
  1149. }
  1150. /**
  1151. * Return true if given value is integer or string with integer value
  1152. *
  1153. * @param mixed $value String or Int
  1154. * @return bool true if number, false if not
  1155. */
  1156. function is_number($value) {
  1157. if (is_int($value)) {
  1158. return true;
  1159. } else if (is_string($value)) {
  1160. return ((string)(int)$value) === $value;
  1161. } else {
  1162. return false;
  1163. }
  1164. }
  1165. /**
  1166. * Returns host part from url.
  1167. *
  1168. * @param string $url full url
  1169. * @return string host, null if not found
  1170. */
  1171. function get_host_from_url($url) {
  1172. preg_match('|^[a-z]+://([a-zA-Z0-9-.]+)|i', $url, $matches);
  1173. if ($matches) {
  1174. return $matches[1];
  1175. }
  1176. return null;
  1177. }
  1178. /**
  1179. * Tests whether anything was returned by text editor
  1180. *
  1181. * This function is useful for testing whether something you got back from
  1182. * the HTML editor actually contains anything. Sometimes the HTML editor
  1183. * appear to be empty, but actually you get back a <br> tag or something.
  1184. *
  1185. * @param string $string a string containing HTML.
  1186. * @return boolean does the string contain any actual content - that is text,
  1187. * images, objects, etc.
  1188. */
  1189. function html_is_blank($string) {
  1190. return trim(strip_tags($string, '<img><object><applet><input><select><textarea><hr>')) == '';
  1191. }
  1192. /**
  1193. * Set a key in global configuration
  1194. *
  1195. * Set a key/value pair in both this session's {@link $CFG} global variable
  1196. * and in the 'config' database table for future sessions.
  1197. *
  1198. * Can also be used to update keys for plugin-scoped configs in config_plugin table.
  1199. * In that case it doesn't affect $CFG.
  1200. *
  1201. * A NULL value will delete the entry.
  1202. *
  1203. * NOTE: this function is called from lib/db/upgrade.php
  1204. *
  1205. * @param string $name the key to set
  1206. * @param string $value the value to set (without magic quotes)
  1207. * @param string $plugin (optional) the plugin scope, default null
  1208. * @return bool true or exception
  1209. */
  1210. function set_config($name, $value, $plugin=null) {
  1211. global $CFG, $DB;
  1212. if (empty($plugin)) {
  1213. if (!array_key_exists($name, $CFG->config_php_settings)) {
  1214. // So it's defined for this invocation at least.
  1215. if (is_null($value)) {
  1216. unset($CFG->$name);
  1217. } else {
  1218. // Settings from db are always strings.
  1219. $CFG->$name = (string)$value;
  1220. }
  1221. }
  1222. if ($DB->get_field('config', 'name', array('name' => $name))) {
  1223. if ($value === null) {
  1224. $DB->delete_records('config', array('name' => $name));
  1225. } else {
  1226. $DB->set_field('config', 'value', $value, array('name' => $name));
  1227. }
  1228. } else {
  1229. if ($value !== null) {
  1230. $config = new stdClass();
  1231. $config->name = $name;
  1232. $config->value = $value;
  1233. $DB->insert_record('config', $config, false);
  1234. }
  1235. // When setting config during a Behat test (in the CLI script, not in the web browser
  1236. // requests), remember which ones are set so that we can clear them later.
  1237. if (defined('BEHAT_TEST')) {
  1238. if (!property_exists($CFG, 'behat_cli_added_config')) {
  1239. $CFG->behat_cli_added_config = [];
  1240. }
  1241. $CFG->behat_cli_added_config[$name] = true;
  1242. }
  1243. }
  1244. if ($name === 'siteidentifier') {
  1245. cache_helper::update_site_identifier($value);
  1246. }
  1247. cache_helper::invalidate_by_definition('core', 'config', array(), 'core');
  1248. } else {
  1249. // Plugin scope.
  1250. if ($id = $DB->get_field('config_plugins', 'id', array('name' => $name, 'plugin' => $plugin))) {
  1251. if ($value===null) {
  1252. $DB->delete_records('config_plugins', array('name' => $name, 'plugin' => $plugin));
  1253. } else {
  1254. $DB->set_field('config_plugins', 'value', $value, array('id' => $id));
  1255. }
  1256. } else {
  1257. if ($value !== null) {
  1258. $config = new stdClass();
  1259. $config->plugin = $plugin;
  1260. $config->name = $name;
  1261. $config->value = $value;
  1262. $DB->insert_record('config_plugins', $config, false);
  1263. }
  1264. }
  1265. cache_helper::invalidate_by_definition('core', 'config', array(), $plugin);
  1266. }
  1267. return true;
  1268. }
  1269. /**
  1270. * Get configuration values from the global config table
  1271. * or the config_plugins table.
  1272. *
  1273. * If called with one parameter, it will load all the config
  1274. * variables for one plugin, and return them as an object.
  1275. *
  1276. * If called with 2 parameters it will return a string single
  1277. * value or false if the value is not found.
  1278. *
  1279. * NOTE: this function is called from lib/db/upgrade.php
  1280. *
  1281. * @static string|false $siteidentifier The site identifier is not cached. We use this static cache so
  1282. * that we need only fetch it once per request.
  1283. * @param string $plugin full component name
  1284. * @param string $name default null
  1285. * @return mixed hash-like object or single value, return false no config found
  1286. * @throws dml_exception
  1287. */
  1288. function get_con

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