1aca809ab8a086edce047cabb59e21600011d35c
[living-lab-site.git] / system / core / Common.php
1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3  * CodeIgniter
4  *
5  * An open source application development framework for PHP 5.1.6 or newer
6  *
7  * @package             CodeIgniter
8  * @author              ExpressionEngine Dev Team
9  * @copyright   Copyright (c) 2008 - 2011, EllisLab, Inc.
10  * @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 /**
19  * 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 /**
33 * 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
39 * @param        string
40 * @return       bool    TRUE if the current version is $version or higher
41 */
42         function is_php($version = '5.0.0')
43         {
44                 static $_is_php;
45                 $version = (string)$version;
46
47                 if ( ! isset($_is_php[$version]))
48                 {
49                         $_is_php[$version] = (version_compare(PHP_VERSION, $version) < 0) ? FALSE : TRUE;
50                 }
51
52                 return $_is_php[$version];
53         }
54
55 // ------------------------------------------------------------------------
56
57 /**
58  * Tests for file writability
59  *
60  * is_writable() returns TRUE on Windows servers when you really can't write to
61  * the file, based on the read-only attribute.  is_writable() is also unreliable
62  * on Unix servers if safe_mode is on.
63  *
64  * @access      private
65  * @return      void
66  */
67         function is_really_writable($file)
68         {
69                 // 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                 }
74
75                 // 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));
80
81                         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 ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
92                 {
93                         return FALSE;
94                 }
95
96                 fclose($fp);
97                 return TRUE;
98         }
99
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
111 * @param        string  the directory where the class should be found
112 * @param        string  the class name prefix
113 * @return       object
114 */
115         function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
116         {
117                 static $_classes = array();
118
119                 // Does the class exist?  If so, we're done...
120                 if (isset($_classes[$class]))
121                 {
122                         return $_classes[$class];
123                 }
124
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)
130                 {
131                         if (file_exists($path.$directory.'/'.$class.EXT))
132                         {
133                                 $name = $prefix.$class;
134
135                                 if (class_exists($name) === FALSE)
136                                 {
137                                         require($path.$directory.'/'.$class.EXT);
138                                 }
139
140                                 break;
141                         }
142                 }
143
144                 // Is the request a class extension?  If so we load it too
145                 if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.EXT))
146                 {
147                         $name = config_item('subclass_prefix').$class;
148
149                         if (class_exists($name) === FALSE)
150                         {
151                                 require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.EXT);
152                         }
153                 }
154
155                 // Did we find the class?
156                 if ($name === FALSE)
157                 {
158                         // Note: We use exit() rather then show_error() in order to avoid a
159                         // self-referencing loop with the Excptions class
160                         exit('Unable to locate the specified class: '.$class.EXT);
161                 }
162
163                 // Keep track of what we just loaded
164                 is_loaded($class);
165
166                 $_classes[$class] = new $name();
167                 return $_classes[$class];
168         }
169
170 // --------------------------------------------------------------------
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 // ------------------------------------------------------------------------
192
193 /**
194 * Loads the main config.php file
195 *
196 * This function lets us grab the config file even if the Config class
197 * hasn't been instantiated yet
198 *
199 * @access       private
200 * @return       array
201 */
202         function &get_config($replace = array())
203         {
204                 static $_config;
205
206                 if (isset($_config))
207                 {
208                         return $_config[0];
209                 }
210
211                 // Is the config file in the environment folder?
212                 if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config'.EXT))
213                 {
214                         $file_path = APPPATH.'config/config'.EXT;
215                 }
216
217                 // Fetch the config file
218                 if ( ! file_exists($file_path))
219                 {
220                         exit('The configuration file does not exist.');
221                 }
222
223                 require($file_path);
224
225                 // Does the $config array exist in the file?
226                 if ( ! isset($config) OR ! is_array($config))
227                 {
228                         exit('Your config file does not appear to be formatted correctly.');
229                 }
230
231                 // Are any values being dynamically replaced?
232                 if (count($replace) > 0)
233                 {
234                         foreach ($replace as $key => $val)
235                         {
236                                 if (isset($config[$key]))
237                                 {
238                                         $config[$key] = $val;
239                                 }
240                         }
241                 }
242
243                 return $_config[0] =& $config;
244         }
245
246 // ------------------------------------------------------------------------
247
248 /**
249 * Returns the specified config item
250 *
251 * @access       public
252 * @return       mixed
253 */
254         function config_item($item)
255         {
256                 static $_config_item = array();
257
258                 if ( ! isset($_config_item[$item]))
259                 {
260                         $config =& get_config();
261
262                         if ( ! isset($config[$item]))
263                         {
264                                 return FALSE;
265                         }
266                         $_config_item[$item] = $config[$item];
267                 }
268
269                 return $_config_item[$item];
270         }
271
272 // ------------------------------------------------------------------------
273
274 /**
275 * Error Handler
276 *
277 * This function lets us invoke the exception class and
278 * display errors using the standard error template located
279 * in application/errors/errors.php
280 * This function will send the error page directly to the
281 * browser and exit.
282 *
283 * @access       public
284 * @return       void
285 */
286         function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
287         {
288                 $_error =& load_class('Exceptions', 'core');
289                 echo $_error->show_error($heading, $message, 'error_general', $status_code);
290                 exit;
291         }
292
293 // ------------------------------------------------------------------------
294
295 /**
296 * 404 Page Handler
297 *
298 * This function is similar to the show_error() function above
299 * However, instead of the standard error template it displays
300 * 404 errors.
301 *
302 * @access       public
303 * @return       void
304 */
305         function show_404($page = '', $log_error = TRUE)
306         {
307                 $_error =& load_class('Exceptions', 'core');
308                 $_error->show_404($page, $log_error);
309                 exit;
310         }
311
312 // ------------------------------------------------------------------------
313
314 /**
315 * Error Logging Interface
316 *
317 * We use this as a simple mechanism to access the logging
318 * class and send messages to be logged.
319 *
320 * @access       public
321 * @return       void
322 */
323         function log_message($level = 'error', $message, $php_error = FALSE)
324         {
325                 static $_log;
326
327                 if (config_item('log_threshold') == 0)
328                 {
329                         return;
330                 }
331
332                 $_log =& load_class('Log');
333                 $_log->write_log($level, $message, $php_error);
334         }
335
336 // ------------------------------------------------------------------------
337
338 /**
339  * Set HTTP Status Header
340  *
341  * @access      public
342  * @param       int             the status code
343  * @param       string
344  * @return      void
345  */
346         function set_status_header($code = 200, $text = '')
347         {
348                 $stati = array(
349                                                         200     => 'OK',
350                                                         201     => 'Created',
351                                                         202     => 'Accepted',
352                                                         203     => 'Non-Authoritative Information',
353                                                         204     => 'No Content',
354                                                         205     => 'Reset Content',
355                                                         206     => 'Partial Content',
356
357                                                         300     => 'Multiple Choices',
358                                                         301     => 'Moved Permanently',
359                                                         302     => 'Found',
360                                                         304     => 'Not Modified',
361                                                         305     => 'Use Proxy',
362                                                         307     => 'Temporary Redirect',
363
364                                                         400     => 'Bad Request',
365                                                         401     => 'Unauthorized',
366                                                         403     => 'Forbidden',
367                                                         404     => 'Not Found',
368                                                         405     => 'Method Not Allowed',
369                                                         406     => 'Not Acceptable',
370                                                         407     => 'Proxy Authentication Required',
371                                                         408     => 'Request Timeout',
372                                                         409     => 'Conflict',
373                                                         410     => 'Gone',
374                                                         411     => 'Length Required',
375                                                         412     => 'Precondition Failed',
376                                                         413     => 'Request Entity Too Large',
377                                                         414     => 'Request-URI Too Long',
378                                                         415     => 'Unsupported Media Type',
379                                                         416     => 'Requested Range Not Satisfiable',
380                                                         417     => 'Expectation Failed',
381
382                                                         500     => 'Internal Server Error',
383                                                         501     => 'Not Implemented',
384                                                         502     => 'Bad Gateway',
385                                                         503     => 'Service Unavailable',
386                                                         504     => 'Gateway Timeout',
387                                                         505     => 'HTTP Version Not Supported'
388                                                 );
389
390                 if ($code == '' OR ! is_numeric($code))
391                 {
392                         show_error('Status codes must be numeric', 500);
393                 }
394
395                 if (isset($stati[$code]) AND $text == '')
396                 {
397                         $text = $stati[$code];
398                 }
399
400                 if ($text == '')
401                 {
402                         show_error('No status text available.  Please check your status code number or supply your own message text.', 500);
403                 }
404
405                 $server_protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;
406
407                 if (substr(php_sapi_name(), 0, 3) == 'cgi')
408                 {
409                         header("Status: {$code} {$text}", TRUE);
410                 }
411                 elseif ($server_protocol == 'HTTP/1.1' OR $server_protocol == 'HTTP/1.0')
412                 {
413                         header($server_protocol." {$code} {$text}", TRUE, $code);
414                 }
415                 else
416                 {
417                         header("HTTP/1.1 {$code} {$text}", TRUE, $code);
418                 }
419         }
420
421 // --------------------------------------------------------------------
422
423 /**
424 * Exception Handler
425 *
426 * This is the custom exception handler that is declaired at the top
427 * of Codeigniter.php.  The main reason we use this is to permit
428 * PHP errors to be logged in our own log files since the user may
429 * not have access to server logs. Since this function
430 * effectively intercepts PHP errors, however, we also need
431 * to display errors based on the current error_reporting level.
432 * We do that with the use of a PHP error template.
433 *
434 * @access       private
435 * @return       void
436 */
437         function _exception_handler($severity, $message, $filepath, $line)
438         {
439                  // We don't bother with "strict" notices since they tend to fill up
440                  // the log file with excess information that isn't normally very helpful.
441                  // For example, if you are running PHP 5 and you use version 4 style
442                  // class functions (without prefixes like "public", "private", etc.)
443                  // you'll get notices telling you that these have been deprecated.
444                 if ($severity == E_STRICT)
445                 {
446                         return;
447                 }
448
449                 $_error =& load_class('Exceptions', 'core');
450
451                 // Should we display the error? We'll get the current error_reporting
452                 // level and add its bits with the severity bits to find out.
453                 if (($severity & error_reporting()) == $severity)
454                 {
455                         $_error->show_php_error($severity, $message, $filepath, $line);
456                 }
457
458                 // Should we log the error?  No?  We're done...
459                 if (config_item('log_threshold') == 0)
460                 {
461                         return;
462                 }
463
464                 $_error->log_exception($severity, $message, $filepath, $line);
465         }
466
467         // --------------------------------------------------------------------
468
469         /**
470          * Remove Invisible Characters
471          *
472          * This prevents sandwiching null characters
473          * between ascii characters, like Java\0script.
474          *
475          * @access      public
476          * @param       string
477          * @return      string
478          */
479         function remove_invisible_characters($str, $url_encoded = TRUE)
480         {
481                 $non_displayables = array();
482                 
483                 // every control character except newline (dec 10)
484                 // carriage return (dec 13), and horizontal tab (dec 09)
485                 
486                 if ($url_encoded)
487                 {
488                         $non_displayables[] = '/%0[0-8bcef]/';  // url encoded 00-08, 11, 12, 14, 15
489                         $non_displayables[] = '/%1[0-9a-f]/';   // url encoded 16-31
490                 }
491                 
492                 $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';   // 00-08, 11, 12, 14-31, 127
493
494                 do
495                 {
496                         $str = preg_replace($non_displayables, '', $str, -1, $count);
497                 }
498                 while ($count);
499
500                 return $str;
501         }
502
503
504 /* End of file Common.php */
505 /* Location: ./system/core/Common.php */