Added error handling so all E_USER_* would be disabled with their E_* counterparts.
[isso.git] / kernel.php
1 <?php
2 /*=====================================================================*\
3 || ################################################################### ||
4 || # Iris Studios Shared Object Framework [#]version[#]
5 || # --------------------------------------------------------------- # ||
6 || # All parts of this file are ©2003-[#]year[#] Iris Studios, Inc. No # ||
7 || # part of this file may be reproduced in any way: part or whole. # ||
8 || # --------------------------------------------------------------- # ||
9 || # ©2003 - [#]year[#] Iris Studios, Inc. | http://www.iris-studios.com # ||
10 || ################################################################### ||
11 \*=====================================================================*/
12
13 define('ERR_FATAL', E_USER_ERROR);
14 define('ERR_ALERT', E_USER_WARNING);
15 define('ERR_WARNING', E_USER_NOTICE);
16
17 if (PHP_VERSION < '4.1.0')
18 {
19 trigger_error('You need PHP version 4.1.0 or newer to run ISSO', ERR_FATAL);
20 exit;
21 }
22
23 if (PHP_VERSION > '5.0.0')
24 {
25 if (ini_get('error_reporting') & E_USER_NOTICE)
26 {
27 error_reporting(ini_get('error_reporting') - E_USER_NOTICE);
28 }
29 }
30
31 if (!(ini_get('error_reporting') & E_NOTICE))
32 {
33 error_reporting(ini_get('error_reporting') - E_USER_NOTICE);
34 }
35
36 if (!(ini_get('error_reporting') & E_WARNING))
37 {
38 error_reporting(ini_get('error_reporting') - E_USER_WARNING);
39 }
40
41 if (!(ini_get('error_reporting') & E_ERROR))
42 {
43 error_reporting(ini_get('error_reporting') - E_USER_ERROR);
44 }
45
46 if ((bool)ini_get('register_globals') === true)
47 {
48 $superglobals = array('_GET', '_COOKIE', '_FILES', '_POST', '_SERVER', '_ENV');
49 foreach ($superglobals AS $global)
50 {
51 if (is_array(${$global}))
52 {
53 foreach (${$global} AS $_key => $_val)
54 {
55 if (isset(${$_key}))
56 {
57 unset(${$_key});
58 }
59 }
60 }
61 }
62 }
63
64 /**
65 * Iris Studios Shared Object Framework (ISSO)
66 *
67 * This framework allows a common backend to be used amongst all Iris
68 * Studios applications and can is built to be abstract and flexible.
69 * The base framework handles all loading and module management.
70 *
71 * @author Iris Studios, Inc.
72 * @copyright Copyright ©2003 - [#]year[#], Iris Studios, Inc.
73 * @version $Revision$
74 *
75 */
76 class Shared_Object_Framework
77 {
78 /**
79 * Global environment variables
80 *
81 * This is where we keep the global variables that are used within the shared framework
82 *
83 * @var version ISSO version
84 * @var sourcepath The location of the framework sources
85 * @var appath The path to the application's location
86 * @var application The name of the application that is using the framework
87 * @var debug Variable for debug mode
88 * @var debuginfo Listing of all debug notices
89 * @var modules An array of loaded framework modules
90 * @var input All input data for the system
91 * @var i Short-hand reference to $isso::input
92 * @var in Short-hand reference to $isso::input
93 * @var magicquotes Status of Magic Quotes GPC
94 */
95 var $version = '[#]version[#]';
96 var $sourcepath = '';
97 var $apppath = '';
98 var $application = '';
99 var $debug = false;
100 var $debuginfo = array();
101 var $modules = array();
102 var $input = array();
103 var $i = array();
104 var $in = array();
105 var $magicquotes = 0;
106
107 /**
108 * Constructor
109 */
110 function Shared_Object_Framework()
111 {
112 // error reporting
113 set_error_handler(array(&$this, '_error_handler'));
114
115 // magic quotes
116 $this->magicquotes = get_magic_quotes_gpc();
117 set_magic_quotes_runtime(0);
118
119 // start input sanitize using variable_order GP
120 $this->input = $this->_sanitize_input_recursive(array_merge($_GET, $_POST));
121 $this->i =& $this->input;
122 $this->in =& $this->input;
123
124 $this->modules['kernel'] = 'Shared Object Framework Core';
125 }
126
127 /**
128 * Prepares a path for being set as the sourcepath
129 *
130 * @param str Source path or URL
131 *
132 * @return str Prepared source path
133 */
134 function fetch_sourcepath($source)
135 {
136 if (substr($source, strlen($source) - 1) != '/')
137 {
138 $source .= '/';
139 }
140 return $source;
141 }
142
143 /**
144 * Loads a framework extension
145 *
146 * @param str Name of the framework
147 */
148 function load($framework)
149 {
150 if (!$this->is_loaded($framework))
151 {
152 $newobj = $this->locate($framework);
153 $this->$newobj['OBJ'] = new $newobj['CLASS']();
154 $GLOBALS["$newobj[OBJ]"] =& $this->$newobj['OBJ'];
155 $this->modules["$framework"] = $newobj['OBJECT'];
156 }
157 }
158
159 /**
160 * Includes a framework module. Module definitions need three variables:
161 * class, object, and obj. Class is the name of the class, object is
162 * the name human-readable name, and obj is the name that the module
163 * should be initialized as; this is used in class extensions.
164 *
165 * @param str Name of the framework
166 *
167 * @return array List of initialization variables
168 */
169 function locate($framework)
170 {
171 if ($this->sourcepath == '')
172 {
173 trigger_error('Invalid sourcepath specified', ERR_FATAL);
174 }
175
176 if (file_exists($this->sourcepath . $framework . '.php'))
177 {
178 require_once($this->sourcepath . $framework . '.php');
179 return array('CLASS' => $CLASS, 'OBJECT' => $OBJECT, 'OBJ' => $OBJ);
180 }
181 else
182 {
183 trigger_error('Could not find the framework ' . $this->sourcepath . $framework . '.php', ERR_FATAL);
184 exit;
185 }
186 }
187
188 /**
189 * Prints a list of all currently loaded framework modules
190 *
191 * @param bool Return the data as an array?
192 *
193 * @return mixed HTML output or an array of loaded modules
194 */
195 function show_modules($return = false)
196 {
197 if ($return)
198 {
199 return $this->modules;
200 }
201 else
202 {
203 $output = "\n\n<ul>\n\t<li>";
204 $output .= implode("</li>\n\t<li>", $this->modules);
205 $output .= "</li>\n</ul>\n\n";
206 $this->_message('Loaded Modules', $output, 1);
207 }
208 }
209
210 /**
211 * Verifies to see if a framework has been loaded
212 *
213 * @param str Framework name
214 *
215 * @return bool Whether or not the framework has been loaded
216 */
217 function is_loaded($framework)
218 {
219 if (isset($this->modules["$framework"]))
220 {
221 return true;
222 }
223 else
224 {
225 return false;
226 }
227 }
228
229 /**
230 * Prints an ISSO message
231 *
232 * @param str The title of the message
233 * @param str The content of the message
234 * @param int Type of message to be printed
235 * @param bool Return the output?
236 *
237 * @return mixed Output or null
238 */
239 function _message($title, $message, $type, $return = false)
240 {
241 switch ($type)
242 {
243 // Message
244 case 1:
245 $prefix = 'Message';
246 $color = '#669900';
247 $font = '#000000';
248 break;
249
250 // Warning
251 case 2:
252 $prefix = 'Warning';
253 $color = '#003399';
254 $font = '#FFFFFF';
255 break;
256
257 case 3:
258 $prefix = 'Error';
259 $color = '#990000';
260 $font = '#EFEFEF';
261 break;
262 }
263
264 $output = "\n<br />\n<table cellpadding=\"4\" cellspacing=\"1\" border=\"0\" width=\"500\" style=\"background-color: $color; font-family: Verdana, sans-serif; font-size: 12px;\">";
265 $output .= "\n<tr style=\"color: $font\">\n\t<td><strong>$prefix: $title</strong></td>\n</tr>";
266 $output .= "\n<tr style=\"background-color: #FFFFFF\">\n\t<td>$message</td>\n</tr>\n</table>\n<br />\n";
267
268 if ($return)
269 {
270 return $output;
271 }
272 else
273 {
274 print($output);
275 }
276 }
277
278 /**
279 * Custom error handler for ISSO
280 *
281 * @param int Error number
282 * @param str Error message string
283 * @param str File that contains the error
284 * @param str The line number of the error
285 * @param str The active symbol table at which point the error occurred
286 */
287 function _error_handler($errno, $errstr, $errfile, $errline)
288 {
289 switch ($errno)
290 {
291 // Fatal
292 case ERR_FATAL:
293 $title = 'Fatal';
294 if (!(ini_get('error_reporting') & ERR_FATAL))
295 {
296 return;
297 }
298 break;
299
300 // Error
301 case ERR_ALERT:
302 $title = 'Alert';
303 if (!(ini_get('error_reporting') & ERR_ALERT))
304 {
305 return;
306 }
307 break;
308
309 // Warning
310 case ERR_WARNING:
311 default:
312 $title = 'Warning';
313 if (!(ini_get('error_reporting') & ERR_WARNING))
314 {
315 return;
316 }
317 break;
318 }
319
320 $errstr .= " in <strong>$errfile</strong> on line <strong>$errline</strong>";
321
322 $this->_message($title, $errstr, 3);
323
324 if ($errno == ERR_FATAL)
325 {
326 exit;
327 }
328 }
329
330 /**
331 * Logs a debug message for verbose output
332 *
333 * @param str Message
334 */
335 function debug($message)
336 {
337 if ($this->debug)
338 {
339 $this->debuginfo[] = $message;
340 }
341 }
342
343 /**
344 * Recursive XSS cleaner
345 *
346 * @param mixed Unsanitized REQUEST data
347 *
348 * @return mixed Sanitized data
349 */
350 function _sanitize_input_recursive($data)
351 {
352 foreach($data AS $key => $value)
353 {
354 if (is_array($value))
355 {
356 $data["$key"] = $this->_sanitize_input_recursive($value);
357 }
358 else
359 {
360 $data["$key"] = $this->sanitize($value);
361 }
362 }
363 return $data;
364 }
365
366 /**
367 * Simple way to protect against HTML attacks with Unicode support
368 *
369 * @param str Unsanitzed text
370 *
371 * @return str Properly protected text that only encodes potential threats
372 */
373 function sanitize($text)
374 {
375 if ($this->magicquotes)
376 {
377 return str_replace(array('<', '>', '\"', '"'), array('&lt;', '&gt;', '&quot;', '&quot;'), $text);
378 }
379 else
380 {
381 return str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $text);
382 }
383 }
384
385 /**
386 * Takes text that has been processed for HTML and unsanitizes it
387 *
388 * @param str Text that needs to be turned back into HTML
389 *
390 * @return str Unsanitized text
391 */
392 function unsanitize($text)
393 {
394 if ($this->magicquotes)
395 {
396 return str_replace(array('&lt;', '&gt;', '&quot;'), array('<', '>', '\"'), $text);
397 }
398 else
399 {
400 return str_replace(array('&lt;', '&gt;', '&quot;'), array('<', '>', '"'), $text);
401 }
402 }
403
404 /**
405 * Smart addslashes() that only applies itself it the Magic Quotes GPC is off
406 *
407 * @param str Some string
408 *
409 * @return str String that has slashes added
410 */
411 function escape($str)
412 {
413 global $_isso;
414
415 if ($this->magicquotes)
416 {
417 return $str;
418 }
419 else
420 {
421 if (isset($_isso->db))
422 {
423 if (is_resource($_isso->db->link_id))
424 {
425 return $_isso->db->escape_string($str);
426 }
427 else
428 {
429 return addslashes($str);
430 }
431 }
432 else
433 {
434 return addslashes($str);
435 }
436 }
437 }
438 }
439
440 /**
441 * Global callback used for module calls back to the kernel
442 */
443 $_isso = new Shared_Object_Framework();
444
445 /**
446 * Wrapper for ternary operator that has to be in the global scope
447 *
448 * @param expr Expression
449 * @param mixed If the expression is true
450 * @param mixed If the expression is false
451 *
452 * @return mixed True or false data
453 */
454 function iff($condition, $iftrue, $iffalse = null)
455 {
456 return ($condition) ? ($iftrue) : ($iffalse);
457 }
458
459 /*=====================================================================*\
460 || ###################################################################
461 || # $HeadURL$
462 || # $Id$
463 || ###################################################################
464 \*=====================================================================*/
465 ?>