blob: b5adfacb3152dadba3a5b46603dff714541a3a89 [file] [log] [blame]
Derek Allard2067d1a2008-11-13 22:59:24 +00001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
Greg Aker0711dc82011-01-05 10:49:40 -06009 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
Derek Allard2067d1a2008-11-13 22:59:24 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060019 * Common Functions
20 *
21 * Loads the base classes and executes the request.
22 *
23 * @package CodeIgniter
24 * @subpackage codeigniter
25 * @category Common Functions
26 * @author ExpressionEngine Dev Team
27 * @link http://codeigniter.com/user_guide/
28 */
29
30// ------------------------------------------------------------------------
31
32/**
Derek Jones086ee5a2009-07-28 14:42:12 +000033* Determines if the current version of PHP is greater then the supplied value
34*
35* Since there are a few places where we conditionally test for PHP > 5
36* we'll set a static variable.
37*
38* @access public
Derek Jones77b513b2009-08-06 14:39:25 +000039* @param string
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060040* @return bool TRUE if the current version is $version or higher
Derek Jones086ee5a2009-07-28 14:42:12 +000041*/
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060042 function is_php($version = '5.0.0')
Derek Jones086ee5a2009-07-28 14:42:12 +000043 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060044 static $_is_php;
45 $version = (string)$version;
Barry Mienydd671972010-10-04 16:33:58 +020046
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060047 if ( ! isset($_is_php[$version]))
48 {
49 $_is_php[$version] = (version_compare(PHP_VERSION, $version) < 0) ? FALSE : TRUE;
50 }
Derek Jones086ee5a2009-07-28 14:42:12 +000051
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060052 return $_is_php[$version];
53 }
Derek Jones5bcfd2e2009-07-28 14:42:42 +000054
Derek Jones086ee5a2009-07-28 14:42:12 +000055// ------------------------------------------------------------------------
56
57/**
Derek Allard2067d1a2008-11-13 22:59:24 +000058 * Tests for file writability
59 *
Barry Mienydd671972010-10-04 16:33:58 +020060 * is_writable() returns TRUE on Windows servers when you really can't write to
Derek Allard2067d1a2008-11-13 22:59:24 +000061 * the file, based on the read-only attribute. is_writable() is also unreliable
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060062 * on Unix servers if safe_mode is on.
Derek Allard2067d1a2008-11-13 22:59:24 +000063 *
64 * @access private
65 * @return void
Barry Mienydd671972010-10-04 16:33:58 +020066 */
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060067 function is_really_writable($file)
Derek Allard2067d1a2008-11-13 22:59:24 +000068 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060069 // If we're on a Unix server with safe_mode off we call is_writable
70 if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE)
71 {
72 return is_writable($file);
73 }
Derek Allard2067d1a2008-11-13 22:59:24 +000074
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060075 // For windows servers and safe_mode "on" installations we'll actually
76 // write a file then read it. Bah...
77 if (is_dir($file))
78 {
79 $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100));
Derek Allard2067d1a2008-11-13 22:59:24 +000080
Derek Jonesdc8e9ea2010-03-02 13:17:19 -060081 if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
82 {
83 return FALSE;
84 }
85
86 fclose($fp);
87 @chmod($file, DIR_WRITE_MODE);
88 @unlink($file);
89 return TRUE;
90 }
91 elseif (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +000092 {
93 return FALSE;
94 }
95
96 fclose($fp);
Derek Allard2067d1a2008-11-13 22:59:24 +000097 return TRUE;
98 }
Derek Allard2067d1a2008-11-13 22:59:24 +000099
100// ------------------------------------------------------------------------
101
102/**
103* Class registry
104*
105* This function acts as a singleton. If the requested class does not
106* exist it is instantiated and set to a static variable. If it has
107* previously been instantiated the variable is returned.
108*
109* @access public
110* @param string the class name being requested
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600111* @param string the directory where the class should be found
112* @param string the class name prefix
Derek Allard2067d1a2008-11-13 22:59:24 +0000113* @return object
114*/
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600115 function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
Derek Allard2067d1a2008-11-13 22:59:24 +0000116 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600117 static $_classes = array();
Barry Mienydd671972010-10-04 16:33:58 +0200118
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600119 // Does the class exist? If so, we're done...
120 if (isset($_classes[$class]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000121 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600122 return $_classes[$class];
Derek Allard2067d1a2008-11-13 22:59:24 +0000123 }
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600124
125 $name = FALSE;
126
127 // Look for the class first in the native system/libraries folder
128 // thenin the local application/libraries folder
129 foreach (array(BASEPATH, APPPATH) as $path)
Barry Mienydd671972010-10-04 16:33:58 +0200130 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600131 if (file_exists($path.$directory.'/'.$class.EXT))
132 {
133 $name = $prefix.$class;
Barry Mienydd671972010-10-04 16:33:58 +0200134
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600135 if (class_exists($name) === FALSE)
136 {
137 require($path.$directory.'/'.$class.EXT);
138 }
Barry Mienydd671972010-10-04 16:33:58 +0200139
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600140 break;
141 }
142 }
143
144 // Is the request a class extension? If so we load it too
Phil Sturgeon3140ad52010-03-12 00:22:42 +0000145 if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.EXT))
Barry Mienydd671972010-10-04 16:33:58 +0200146 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600147 $name = config_item('subclass_prefix').$class;
Barry Mienydd671972010-10-04 16:33:58 +0200148
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600149 if (class_exists($name) === FALSE)
150 {
Phil Sturgeon3140ad52010-03-12 00:22:42 +0000151 require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.EXT);
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600152 }
153 }
154
155 // Did we find the class?
156 if ($name === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000157 {
Barry Mienydd671972010-10-04 16:33:58 +0200158 // Note: We use exit() rather then show_error() in order to avoid a
159 // self-referencing loop with the Excptions class
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600160 exit('Unable to locate the specified class: '.$class.EXT);
Derek Allard2067d1a2008-11-13 22:59:24 +0000161 }
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600162
163 // Keep track of what we just loaded
164 is_loaded($class);
165
Pascal Kriete58560022010-11-10 16:01:20 -0500166 $_classes[$class] = new $name();
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600167 return $_classes[$class];
Derek Allard2067d1a2008-11-13 22:59:24 +0000168 }
169
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600170// --------------------------------------------------------------------
171
172/**
173* Keeps track of which libraries have been loaded. This function is
174* called by the load_class() function above
175*
176* @access public
177* @return array
178*/
179 function is_loaded($class = '')
180 {
181 static $_is_loaded = array();
182
183 if ($class != '')
184 {
185 $_is_loaded[strtolower($class)] = $class;
186 }
187
188 return $_is_loaded;
189 }
190
191// ------------------------------------------------------------------------
Derek Jonesf0a9b332009-07-29 14:19:18 +0000192
193/**
Derek Allard2067d1a2008-11-13 22:59:24 +0000194* Loads the main config.php file
195*
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600196* This function lets us grab the config file even if the Config class
197* hasn't been instantiated yet
198*
Derek Allard2067d1a2008-11-13 22:59:24 +0000199* @access private
200* @return array
201*/
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600202 function &get_config($replace = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000203 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600204 static $_config;
Barry Mienydd671972010-10-04 16:33:58 +0200205
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600206 if (isset($_config))
207 {
208 return $_config[0];
Barry Mienydd671972010-10-04 16:33:58 +0200209 }
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600210
211 // Fetch the config file
Derek Allard2067d1a2008-11-13 22:59:24 +0000212 if ( ! file_exists(APPPATH.'config/config'.EXT))
213 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600214 exit('The configuration file does not exist.');
215 }
216 else
217 {
218 require(APPPATH.'config/config'.EXT);
Derek Allard2067d1a2008-11-13 22:59:24 +0000219 }
220
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600221 // Does the $config array exist in the file?
Derek Allard2067d1a2008-11-13 22:59:24 +0000222 if ( ! isset($config) OR ! is_array($config))
223 {
224 exit('Your config file does not appear to be formatted correctly.');
225 }
226
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600227 // Are any values being dynamically replaced?
228 if (count($replace) > 0)
229 {
230 foreach ($replace as $key => $val)
231 {
232 if (isset($config[$key]))
233 {
234 $config[$key] = $val;
235 }
236 }
237 }
Barry Mienydd671972010-10-04 16:33:58 +0200238
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600239 return $_config[0] =& $config;
Derek Allard2067d1a2008-11-13 22:59:24 +0000240 }
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600241
242// ------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000243
244/**
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600245* Returns the specified config item
Derek Allard2067d1a2008-11-13 22:59:24 +0000246*
247* @access public
248* @return mixed
249*/
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600250 function config_item($item)
Derek Allard2067d1a2008-11-13 22:59:24 +0000251 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600252 static $_config_item = array();
Barry Mienydd671972010-10-04 16:33:58 +0200253
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600254 if ( ! isset($_config_item[$item]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000255 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600256 $config =& get_config();
Barry Mienydd671972010-10-04 16:33:58 +0200257
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600258 if ( ! isset($config[$item]))
259 {
260 return FALSE;
261 }
262 $_config_item[$item] = $config[$item];
Derek Allard2067d1a2008-11-13 22:59:24 +0000263 }
Barry Mienydd671972010-10-04 16:33:58 +0200264
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600265 return $_config_item[$item];
Derek Allard2067d1a2008-11-13 22:59:24 +0000266 }
267
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600268// ------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000269
270/**
271* Error Handler
272*
273* This function lets us invoke the exception class and
274* display errors using the standard error template located
275* in application/errors/errors.php
276* This function will send the error page directly to the
277* browser and exit.
278*
279* @access public
280* @return void
281*/
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600282 function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
283 {
284 $_error =& load_class('Exceptions', 'core');
285 echo $_error->show_error($heading, $message, 'error_general', $status_code);
286 exit;
287 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000288
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600289// ------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000290
291/**
292* 404 Page Handler
293*
294* This function is similar to the show_error() function above
295* However, instead of the standard error template it displays
296* 404 errors.
297*
298* @access public
299* @return void
300*/
Derek Allard2ddc9492010-08-05 10:08:33 -0400301 function show_404($page = '', $log_error = TRUE)
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600302 {
303 $_error =& load_class('Exceptions', 'core');
Derek Allard2ddc9492010-08-05 10:08:33 -0400304 $_error->show_404($page, $log_error);
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600305 exit;
306 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000307
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600308// ------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000309
310/**
311* Error Logging Interface
312*
313* We use this as a simple mechanism to access the logging
314* class and send messages to be logged.
315*
316* @access public
317* @return void
318*/
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600319 function log_message($level = 'error', $message, $php_error = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000320 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600321 static $_log;
322
323 if (config_item('log_threshold') == 0)
324 {
325 return;
326 }
Barry Mienydd671972010-10-04 16:33:58 +0200327
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600328 $_log =& load_class('Log');
329 $_log->write_log($level, $message, $php_error);
Derek Allard2067d1a2008-11-13 22:59:24 +0000330 }
331
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600332// ------------------------------------------------------------------------
Derek Jones817163a2009-07-11 17:05:58 +0000333
334/**
335 * Set HTTP Status Header
336 *
337 * @access public
Barry Mienydd671972010-10-04 16:33:58 +0200338 * @param int the status code
339 * @param string
Derek Jones817163a2009-07-11 17:05:58 +0000340 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200341 */
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600342 function set_status_header($code = 200, $text = '')
Derek Jones817163a2009-07-11 17:05:58 +0000343 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600344 $stati = array(
345 200 => 'OK',
346 201 => 'Created',
347 202 => 'Accepted',
348 203 => 'Non-Authoritative Information',
349 204 => 'No Content',
350 205 => 'Reset Content',
351 206 => 'Partial Content',
Derek Jones817163a2009-07-11 17:05:58 +0000352
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600353 300 => 'Multiple Choices',
354 301 => 'Moved Permanently',
355 302 => 'Found',
356 304 => 'Not Modified',
357 305 => 'Use Proxy',
358 307 => 'Temporary Redirect',
359
360 400 => 'Bad Request',
361 401 => 'Unauthorized',
362 403 => 'Forbidden',
363 404 => 'Not Found',
364 405 => 'Method Not Allowed',
365 406 => 'Not Acceptable',
366 407 => 'Proxy Authentication Required',
367 408 => 'Request Timeout',
368 409 => 'Conflict',
369 410 => 'Gone',
370 411 => 'Length Required',
371 412 => 'Precondition Failed',
372 413 => 'Request Entity Too Large',
373 414 => 'Request-URI Too Long',
374 415 => 'Unsupported Media Type',
375 416 => 'Requested Range Not Satisfiable',
376 417 => 'Expectation Failed',
377
378 500 => 'Internal Server Error',
379 501 => 'Not Implemented',
380 502 => 'Bad Gateway',
381 503 => 'Service Unavailable',
382 504 => 'Gateway Timeout',
383 505 => 'HTTP Version Not Supported'
384 );
385
386 if ($code == '' OR ! is_numeric($code))
387 {
388 show_error('Status codes must be numeric', 500);
389 }
390
391 if (isset($stati[$code]) AND $text == '')
Barry Mienydd671972010-10-04 16:33:58 +0200392 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600393 $text = $stati[$code];
394 }
Barry Mienydd671972010-10-04 16:33:58 +0200395
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600396 if ($text == '')
397 {
398 show_error('No status text available. Please check your status code number or supply your own message text.', 500);
399 }
Barry Mienydd671972010-10-04 16:33:58 +0200400
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600401 $server_protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;
402
403 if (substr(php_sapi_name(), 0, 3) == 'cgi')
404 {
405 header("Status: {$code} {$text}", TRUE);
406 }
407 elseif ($server_protocol == 'HTTP/1.1' OR $server_protocol == 'HTTP/1.0')
408 {
409 header($server_protocol." {$code} {$text}", TRUE, $code);
410 }
411 else
412 {
413 header("HTTP/1.1 {$code} {$text}", TRUE, $code);
414 }
Derek Jones817163a2009-07-11 17:05:58 +0000415 }
Barry Mienydd671972010-10-04 16:33:58 +0200416
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600417// --------------------------------------------------------------------
Derek Jones817163a2009-07-11 17:05:58 +0000418
Derek Allard2067d1a2008-11-13 22:59:24 +0000419/**
420* Exception Handler
421*
422* This is the custom exception handler that is declaired at the top
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600423* of Codeigniter.php. The main reason we use this is to permit
424* PHP errors to be logged in our own log files since the user may
Derek Allard2067d1a2008-11-13 22:59:24 +0000425* not have access to server logs. Since this function
426* effectively intercepts PHP errors, however, we also need
427* to display errors based on the current error_reporting level.
428* We do that with the use of a PHP error template.
429*
430* @access private
431* @return void
432*/
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600433 function _exception_handler($severity, $message, $filepath, $line)
Barry Mienydd671972010-10-04 16:33:58 +0200434 {
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600435 // We don't bother with "strict" notices since they tend to fill up
436 // the log file with excess information that isn't normally very helpful.
Barry Mienydd671972010-10-04 16:33:58 +0200437 // For example, if you are running PHP 5 and you use version 4 style
438 // class functions (without prefixes like "public", "private", etc.)
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600439 // you'll get notices telling you that these have been deprecated.
440 if ($severity == E_STRICT)
441 {
442 return;
443 }
Barry Mienydd671972010-10-04 16:33:58 +0200444
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600445 $_error =& load_class('Exceptions', 'core');
Barry Mienydd671972010-10-04 16:33:58 +0200446
447 // Should we display the error? We'll get the current error_reporting
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600448 // level and add its bits with the severity bits to find out.
449 if (($severity & error_reporting()) == $severity)
450 {
451 $_error->show_php_error($severity, $message, $filepath, $line);
452 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000453
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600454 // Should we log the error? No? We're done...
455 if (config_item('log_threshold') == 0)
456 {
457 return;
458 }
Barry Mienydd671972010-10-04 16:33:58 +0200459
Derek Jonesdc8e9ea2010-03-02 13:17:19 -0600460 $_error->log_exception($severity, $message, $filepath, $line);
461 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000462
Greg Aker757dda62010-04-14 19:06:19 -0500463 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200464
Greg Aker757dda62010-04-14 19:06:19 -0500465 /**
466 * Remove Invisible Characters
467 *
468 * This prevents sandwiching null characters
469 * between ascii characters, like Java\0script.
470 *
471 * @access public
472 * @param string
473 * @return string
474 */
475 function remove_invisible_characters($str)
476 {
477 static $non_displayables;
Barry Mienydd671972010-10-04 16:33:58 +0200478
Greg Aker757dda62010-04-14 19:06:19 -0500479 if ( ! isset($non_displayables))
480 {
481 // every control character except newline (dec 10), carriage return (dec 13), and horizontal tab (dec 09),
482 $non_displayables = array(
483 '/%0[0-8bcef]/', // url encoded 00-08, 11, 12, 14, 15
484 '/%1[0-9a-f]/', // url encoded 16-31
485 '/[\x00-\x08]/', // 00-08
486 '/\x0b/', '/\x0c/', // 11, 12
487 '/[\x0e-\x1f]/' // 14-31
488 );
489 }
490
491 do
492 {
493 $cleaned = $str;
494 $str = preg_replace($non_displayables, '', $str);
495 }
496 while ($cleaned != $str);
497
498 return $str;
499 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000500
501
502/* End of file Common.php */
Derek Jonesc68dfbf2010-03-02 12:59:23 -0600503/* Location: ./system/core/Common.php */