CodeIgniter.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. <?php
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP
  6. *
  7. * This content is released under the MIT License (MIT)
  8. *
  9. * Copyright (c) 2014 - 2016, British Columbia Institute of Technology
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in
  19. * all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. * THE SOFTWARE.
  28. *
  29. * @package CodeIgniter
  30. * @author EllisLab Dev Team
  31. * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
  32. * @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
  33. * @license http://opensource.org/licenses/MIT MIT License
  34. * @link https://codeigniter.com
  35. * @since Version 1.0.0
  36. * @filesource
  37. */
  38. defined('BASEPATH') OR exit('No direct script access allowed');
  39. /**
  40. * System Initialization File
  41. *
  42. * Loads the base classes and executes the request.
  43. *
  44. * @package CodeIgniter
  45. * @subpackage CodeIgniter
  46. * @category Front-controller
  47. * @author EllisLab Dev Team
  48. * @link https://codeigniter.com/user_guide/
  49. */
  50. /**
  51. * CodeIgniter Version
  52. *
  53. * @var string
  54. *
  55. */
  56. const CI_VERSION = '3.1.2';
  57. /*
  58. * ------------------------------------------------------
  59. * Load the framework constants
  60. * ------------------------------------------------------
  61. */
  62. if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
  63. {
  64. require_once(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
  65. }
  66. require_once(APPPATH.'config/constants.php');
  67. /*
  68. * ------------------------------------------------------
  69. * Load the global functions
  70. * ------------------------------------------------------
  71. */
  72. require_once(BASEPATH.'core/Common.php');
  73. /*
  74. * ------------------------------------------------------
  75. * Security procedures
  76. * ------------------------------------------------------
  77. */
  78. if ( ! is_php('5.4'))
  79. {
  80. ini_set('magic_quotes_runtime', 0);
  81. if ((bool) ini_get('register_globals'))
  82. {
  83. $_protected = array(
  84. '_SERVER',
  85. '_GET',
  86. '_POST',
  87. '_FILES',
  88. '_REQUEST',
  89. '_SESSION',
  90. '_ENV',
  91. '_COOKIE',
  92. 'GLOBALS',
  93. 'HTTP_RAW_POST_DATA',
  94. 'system_path',
  95. 'application_folder',
  96. 'view_folder',
  97. '_protected',
  98. '_registered'
  99. );
  100. $_registered = ini_get('variables_order');
  101. foreach (array('E' => '_ENV', 'G' => '_GET', 'P' => '_POST', 'C' => '_COOKIE', 'S' => '_SERVER') as $key => $superglobal)
  102. {
  103. if (strpos($_registered, $key) === FALSE)
  104. {
  105. continue;
  106. }
  107. foreach (array_keys($$superglobal) as $var)
  108. {
  109. if (isset($GLOBALS[$var]) && ! in_array($var, $_protected, TRUE))
  110. {
  111. $GLOBALS[$var] = NULL;
  112. }
  113. }
  114. }
  115. }
  116. }
  117. /*
  118. * ------------------------------------------------------
  119. * Define a custom error handler so we can log PHP errors
  120. * ------------------------------------------------------
  121. */
  122. set_error_handler('_error_handler');
  123. set_exception_handler('_exception_handler');
  124. register_shutdown_function('_shutdown_handler');
  125. /*
  126. * ------------------------------------------------------
  127. * Set the subclass_prefix
  128. * ------------------------------------------------------
  129. *
  130. * Normally the "subclass_prefix" is set in the config file.
  131. * The subclass prefix allows CI to know if a core class is
  132. * being extended via a library in the local application
  133. * "libraries" folder. Since CI allows config items to be
  134. * overridden via data set in the main index.php file,
  135. * before proceeding we need to know if a subclass_prefix
  136. * override exists. If so, we will set this value now,
  137. * before any classes are loaded
  138. * Note: Since the config file data is cached it doesn't
  139. * hurt to load it here.
  140. */
  141. if ( ! empty($assign_to_config['subclass_prefix']))
  142. {
  143. get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
  144. }
  145. /*
  146. * ------------------------------------------------------
  147. * Should we use a Composer autoloader?
  148. * ------------------------------------------------------
  149. */
  150. if ($composer_autoload = config_item('composer_autoload'))
  151. {
  152. if ($composer_autoload === TRUE)
  153. {
  154. file_exists(APPPATH.'vendor/autoload.php')
  155. ? require_once(APPPATH.'vendor/autoload.php')
  156. : log_message('error', '$config[\'composer_autoload\'] is set to TRUE but '.APPPATH.'vendor/autoload.php was not found.');
  157. }
  158. elseif (file_exists($composer_autoload))
  159. {
  160. require_once($composer_autoload);
  161. }
  162. else
  163. {
  164. log_message('error', 'Could not find the specified $config[\'composer_autoload\'] path: '.$composer_autoload);
  165. }
  166. }
  167. /*
  168. * ------------------------------------------------------
  169. * Start the timer... tick tock tick tock...
  170. * ------------------------------------------------------
  171. */
  172. $BM =& load_class('Benchmark', 'core');
  173. $BM->mark('total_execution_time_start');
  174. $BM->mark('loading_time:_base_classes_start');
  175. /*
  176. * ------------------------------------------------------
  177. * Instantiate the hooks class
  178. * ------------------------------------------------------
  179. */
  180. $EXT =& load_class('Hooks', 'core');
  181. /*
  182. * ------------------------------------------------------
  183. * Is there a "pre_system" hook?
  184. * ------------------------------------------------------
  185. */
  186. $EXT->call_hook('pre_system');
  187. /*
  188. * ------------------------------------------------------
  189. * Instantiate the config class
  190. * ------------------------------------------------------
  191. *
  192. * Note: It is important that Config is loaded first as
  193. * most other classes depend on it either directly or by
  194. * depending on another class that uses it.
  195. *
  196. */
  197. $CFG =& load_class('Config', 'core');
  198. // Do we have any manually set config items in the index.php file?
  199. if (isset($assign_to_config) && is_array($assign_to_config))
  200. {
  201. foreach ($assign_to_config as $key => $value)
  202. {
  203. $CFG->set_item($key, $value);
  204. }
  205. }
  206. /*
  207. * ------------------------------------------------------
  208. * Important charset-related stuff
  209. * ------------------------------------------------------
  210. *
  211. * Configure mbstring and/or iconv if they are enabled
  212. * and set MB_ENABLED and ICONV_ENABLED constants, so
  213. * that we don't repeatedly do extension_loaded() or
  214. * function_exists() calls.
  215. *
  216. * Note: UTF-8 class depends on this. It used to be done
  217. * in it's constructor, but it's _not_ class-specific.
  218. *
  219. */
  220. $charset = strtoupper(config_item('charset'));
  221. ini_set('default_charset', $charset);
  222. if (extension_loaded('mbstring'))
  223. {
  224. define('MB_ENABLED', TRUE);
  225. // mbstring.internal_encoding is deprecated starting with PHP 5.6
  226. // and it's usage triggers E_DEPRECATED messages.
  227. @ini_set('mbstring.internal_encoding', $charset);
  228. // This is required for mb_convert_encoding() to strip invalid characters.
  229. // That's utilized by CI_Utf8, but it's also done for consistency with iconv.
  230. mb_substitute_character('none');
  231. }
  232. else
  233. {
  234. define('MB_ENABLED', FALSE);
  235. }
  236. // There's an ICONV_IMPL constant, but the PHP manual says that using
  237. // iconv's predefined constants is "strongly discouraged".
  238. if (extension_loaded('iconv'))
  239. {
  240. define('ICONV_ENABLED', TRUE);
  241. // iconv.internal_encoding is deprecated starting with PHP 5.6
  242. // and it's usage triggers E_DEPRECATED messages.
  243. @ini_set('iconv.internal_encoding', $charset);
  244. }
  245. else
  246. {
  247. define('ICONV_ENABLED', FALSE);
  248. }
  249. if (is_php('5.6'))
  250. {
  251. ini_set('php.internal_encoding', $charset);
  252. }
  253. /*
  254. * ------------------------------------------------------
  255. * Load compatibility features
  256. * ------------------------------------------------------
  257. */
  258. require_once(BASEPATH.'core/compat/mbstring.php');
  259. require_once(BASEPATH.'core/compat/hash.php');
  260. require_once(BASEPATH.'core/compat/password.php');
  261. require_once(BASEPATH.'core/compat/standard.php');
  262. /*
  263. * ------------------------------------------------------
  264. * Instantiate the UTF-8 class
  265. * ------------------------------------------------------
  266. */
  267. $UNI =& load_class('Utf8', 'core');
  268. /*
  269. * ------------------------------------------------------
  270. * Instantiate the URI class
  271. * ------------------------------------------------------
  272. */
  273. $URI =& load_class('URI', 'core');
  274. /*
  275. * ------------------------------------------------------
  276. * Instantiate the routing class and set the routing
  277. * ------------------------------------------------------
  278. */
  279. $RTR =& load_class('Router', 'core', isset($routing) ? $routing : NULL);
  280. /*
  281. * ------------------------------------------------------
  282. * Instantiate the output class
  283. * ------------------------------------------------------
  284. */
  285. $OUT =& load_class('Output', 'core');
  286. /*
  287. * ------------------------------------------------------
  288. * Is there a valid cache file? If so, we're done...
  289. * ------------------------------------------------------
  290. */
  291. if ($EXT->call_hook('cache_override') === FALSE && $OUT->_display_cache($CFG, $URI) === TRUE)
  292. {
  293. exit;
  294. }
  295. /*
  296. * -----------------------------------------------------
  297. * Load the security class for xss and csrf support
  298. * -----------------------------------------------------
  299. */
  300. $SEC =& load_class('Security', 'core');
  301. /*
  302. * ------------------------------------------------------
  303. * Load the Input class and sanitize globals
  304. * ------------------------------------------------------
  305. */
  306. $IN =& load_class('Input', 'core');
  307. /*
  308. * ------------------------------------------------------
  309. * Load the Language class
  310. * ------------------------------------------------------
  311. */
  312. $LANG =& load_class('Lang', 'core');
  313. /*
  314. * ------------------------------------------------------
  315. * Load the app controller and local controller
  316. * ------------------------------------------------------
  317. *
  318. */
  319. // Load the base controller class
  320. require_once BASEPATH.'core/Controller.php';
  321. /**
  322. * Reference to the CI_Controller method.
  323. *
  324. * Returns current CI instance object
  325. *
  326. * @return CI_Controller
  327. */
  328. function &get_instance()
  329. {
  330. return CI_Controller::get_instance();
  331. }
  332. if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
  333. {
  334. require_once APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
  335. }
  336. // Set a mark point for benchmarking
  337. $BM->mark('loading_time:_base_classes_end');
  338. /*
  339. * ------------------------------------------------------
  340. * Sanity checks
  341. * ------------------------------------------------------
  342. *
  343. * The Router class has already validated the request,
  344. * leaving us with 3 options here:
  345. *
  346. * 1) an empty class name, if we reached the default
  347. * controller, but it didn't exist;
  348. * 2) a query string which doesn't go through a
  349. * file_exists() check
  350. * 3) a regular request for a non-existing page
  351. *
  352. * We handle all of these as a 404 error.
  353. *
  354. * Furthermore, none of the methods in the app controller
  355. * or the loader class can be called via the URI, nor can
  356. * controller methods that begin with an underscore.
  357. */
  358. $e404 = FALSE;
  359. $class = ucfirst($RTR->class);
  360. $method = $RTR->method;
  361. if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php'))
  362. {
  363. $e404 = TRUE;
  364. }
  365. else
  366. {
  367. require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php');
  368. if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
  369. {
  370. $e404 = TRUE;
  371. }
  372. elseif (method_exists($class, '_remap'))
  373. {
  374. $params = array($method, array_slice($URI->rsegments, 2));
  375. $method = '_remap';
  376. }
  377. elseif ( ! method_exists($class, $method))
  378. {
  379. $e404 = TRUE;
  380. }
  381. /**
  382. * DO NOT CHANGE THIS, NOTHING ELSE WORKS!
  383. *
  384. * - method_exists() returns true for non-public methods, which passes the previous elseif
  385. * - is_callable() returns false for PHP 4-style constructors, even if there's a __construct()
  386. * - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited
  387. * - People will only complain if this doesn't work, even though it is documented that it shouldn't.
  388. *
  389. * ReflectionMethod::isConstructor() is the ONLY reliable check,
  390. * knowing which method will be executed as a constructor.
  391. */
  392. elseif ( ! is_callable(array($class, $method)) && strcasecmp($class, $method) === 0)
  393. {
  394. $reflection = new ReflectionMethod($class, $method);
  395. if ( ! $reflection->isPublic() OR $reflection->isConstructor())
  396. {
  397. $e404 = TRUE;
  398. }
  399. }
  400. }
  401. if ($e404)
  402. {
  403. if ( ! empty($RTR->routes['404_override']))
  404. {
  405. if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $error_class, $error_method) !== 2)
  406. {
  407. $error_method = 'index';
  408. }
  409. $error_class = ucfirst($error_class);
  410. if ( ! class_exists($error_class, FALSE))
  411. {
  412. if (file_exists(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php'))
  413. {
  414. require_once(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php');
  415. $e404 = ! class_exists($error_class, FALSE);
  416. }
  417. // Were we in a directory? If so, check for a global override
  418. elseif ( ! empty($RTR->directory) && file_exists(APPPATH.'controllers/'.$error_class.'.php'))
  419. {
  420. require_once(APPPATH.'controllers/'.$error_class.'.php');
  421. if (($e404 = ! class_exists($error_class, FALSE)) === FALSE)
  422. {
  423. $RTR->directory = '';
  424. }
  425. }
  426. }
  427. else
  428. {
  429. $e404 = FALSE;
  430. }
  431. }
  432. // Did we reset the $e404 flag? If so, set the rsegments, starting from index 1
  433. if ( ! $e404)
  434. {
  435. $class = $error_class;
  436. $method = $error_method;
  437. $URI->rsegments = array(
  438. 1 => $class,
  439. 2 => $method
  440. );
  441. }
  442. else
  443. {
  444. show_404($RTR->directory.$class.'/'.$method);
  445. }
  446. }
  447. if ($method !== '_remap')
  448. {
  449. $params = array_slice($URI->rsegments, 2);
  450. }
  451. /*
  452. * ------------------------------------------------------
  453. * Is there a "pre_controller" hook?
  454. * ------------------------------------------------------
  455. */
  456. $EXT->call_hook('pre_controller');
  457. /*
  458. * ------------------------------------------------------
  459. * Instantiate the requested controller
  460. * ------------------------------------------------------
  461. */
  462. // Mark a start point so we can benchmark the controller
  463. $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');
  464. $CI = new $class();
  465. /*
  466. * ------------------------------------------------------
  467. * Is there a "post_controller_constructor" hook?
  468. * ------------------------------------------------------
  469. */
  470. $EXT->call_hook('post_controller_constructor');
  471. /*
  472. * ------------------------------------------------------
  473. * Call the requested method
  474. * ------------------------------------------------------
  475. */
  476. call_user_func_array(array(&$CI, $method), $params);
  477. // Mark a benchmark end point
  478. $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');
  479. /*
  480. * ------------------------------------------------------
  481. * Is there a "post_controller" hook?
  482. * ------------------------------------------------------
  483. */
  484. $EXT->call_hook('post_controller');
  485. /*
  486. * ------------------------------------------------------
  487. * Send the final rendered output to the browser
  488. * ------------------------------------------------------
  489. */
  490. if ($EXT->call_hook('display_override') === FALSE)
  491. {
  492. $OUT->_display();
  493. }
  494. /*
  495. * ------------------------------------------------------
  496. * Is there a "post_system" hook?
  497. * ------------------------------------------------------
  498. */
  499. $EXT->call_hook('post_system');