Added magic quotes mimicker, except it actually works well. Added support for isso...
[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 * @var escapestrings Sets whether or not we escape strings automatically
95 */
96 var $version = '[#]version[#]';
97 var $sourcepath = '';
98 var $apppath = '';
99 var $application = '';
100 var $debug = false;
101 var $debuginfo = array();
102 var $modules = array();
103 var $input = array();
104 var $i = array();
105 var $in = array();
106 var $magicquotes = 0;
107 var $escapestrings = false;
108
109 /**
110 * Constructor
111 */
112 function Shared_Object_Framework()
113 {
114 // error reporting
115 set_error_handler(array(&$this, '_error_handler'));
116
117 // magic quotes
118 $this->magicquotes = get_magic_quotes_gpc();
119 set_magic_quotes_runtime(0);
120
121 if (defined('ISSO_ESCAPE_STRINGS'))
122 {
123 $this->escapestrings = (bool)constant('ISSO_ESCAPE_STRINGS');
124 }
125
126 // start input sanitize using variable_order GP
127 if (!$this->escapestrings)
128 {
129 $this->exec_sanitize_data();
130 }
131
132 $this->modules['kernel'] = 'Shared Object Framework Core';
133 }
134
135 /**
136 * Prepares a path for being set as the sourcepath
137 *
138 * @param str Source path or URL
139 *
140 * @return str Prepared source path
141 */
142 function fetch_sourcepath($source)
143 {
144 if (substr($source, strlen($source) - 1) != '/')
145 {
146 $source .= '/';
147 }
148 return $source;
149 }
150
151 /**
152 * Loads a framework extension
153 *
154 * @param str Name of the framework
155 */
156 function load($framework)
157 {
158 if (!$this->is_loaded($framework))
159 {
160 $newobj = $this->locate($framework);
161 $this->$newobj['OBJ'] = new $newobj['CLASS']();
162 $GLOBALS["$newobj[OBJ]"] =& $this->$newobj['OBJ'];
163 $this->modules["$framework"] = $newobj['OBJECT'];
164 }
165 }
166
167 /**
168 * Includes a framework module. Module definitions need three variables:
169 * class, object, and obj. Class is the name of the class, object is
170 * the name human-readable name, and obj is the name that the module
171 * should be initialized as; this is used in class extensions.
172 *
173 * @param str Name of the framework
174 *
175 * @return array List of initialization variables
176 */
177 function locate($framework)
178 {
179 if ($this->sourcepath == '')
180 {
181 trigger_error('Invalid sourcepath specified', ERR_FATAL);
182 }
183
184 if (file_exists($this->sourcepath . $framework . '.php'))
185 {
186 require_once($this->sourcepath . $framework . '.php');
187 return array('CLASS' => $CLASS, 'OBJECT' => $OBJECT, 'OBJ' => $OBJ);
188 }
189 else
190 {
191 trigger_error('Could not find the framework ' . $this->sourcepath . $framework . '.php', ERR_FATAL);
192 exit;
193 }
194 }
195
196 /**
197 * Prints a list of all currently loaded framework modules
198 *
199 * @param bool Return the data as an array?
200 *
201 * @return mixed HTML output or an array of loaded modules
202 */
203 function show_modules($return = false)
204 {
205 if ($return)
206 {
207 return $this->modules;
208 }
209 else
210 {
211 $output = "\n\n<ul>\n\t<li>";
212 $output .= implode("</li>\n\t<li>", $this->modules);
213 $output .= "</li>\n</ul>\n\n";
214 $this->_message('Loaded Modules', $output, 1);
215 }
216 }
217
218 /**
219 * Verifies to see if a framework has been loaded
220 *
221 * @param str Framework name
222 *
223 * @return bool Whether or not the framework has been loaded
224 */
225 function is_loaded($framework)
226 {
227 if (isset($this->modules["$framework"]))
228 {
229 return true;
230 }
231 else
232 {
233 return false;
234 }
235 }
236
237 /**
238 * Prints an ISSO message
239 *
240 * @param str The title of the message
241 * @param str The content of the message
242 * @param int Type of message to be printed
243 * @param bool Return the output?
244 *
245 * @return mixed Output or null
246 */
247 function _message($title, $message, $type, $return = false)
248 {
249 switch ($type)
250 {
251 // Message
252 case 1:
253 $prefix = 'Message';
254 $color = '#669900';
255 $font = '#000000';
256 break;
257
258 // Warning
259 case 2:
260 $prefix = 'Warning';
261 $color = '#003399';
262 $font = '#FFFFFF';
263 break;
264
265 case 3:
266 $prefix = 'Error';
267 $color = '#990000';
268 $font = '#EFEFEF';
269 break;
270 }
271
272 $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;\">";
273 $output .= "\n<tr style=\"color: $font\">\n\t<td><strong>$prefix: $title</strong></td>\n</tr>";
274 $output .= "\n<tr style=\"background-color: #FFFFFF\">\n\t<td>$message</td>\n</tr>\n</table>\n<br />\n";
275
276 if ($return)
277 {
278 return $output;
279 }
280 else
281 {
282 print($output);
283 }
284 }
285
286 /**
287 * Custom error handler for ISSO
288 *
289 * @param int Error number
290 * @param str Error message string
291 * @param str File that contains the error
292 * @param str The line number of the error
293 * @param str The active symbol table at which point the error occurred
294 */
295 function _error_handler($errno, $errstr, $errfile, $errline)
296 {
297 switch ($errno)
298 {
299 // Fatal
300 case ERR_FATAL:
301 $title = 'Fatal';
302 if (!(ini_get('error_reporting') & ERR_FATAL))
303 {
304 return;
305 }
306 break;
307
308 // Error
309 case ERR_ALERT:
310 $title = 'Alert';
311 if (!(ini_get('error_reporting') & ERR_ALERT))
312 {
313 return;
314 }
315 break;
316
317 // Warning
318 case ERR_WARNING:
319 default:
320 $title = 'Warning';
321 if (!(ini_get('error_reporting') & ERR_WARNING))
322 {
323 return;
324 }
325 break;
326 }
327
328 $errstr .= " in <strong>$errfile</strong> on line <strong>$errline</strong>";
329
330 $this->_message($title, $errstr, 3);
331
332 if ($errno == ERR_FATAL)
333 {
334 exit;
335 }
336 }
337
338 /**
339 * Logs a debug message for verbose output
340 *
341 * @param str Message
342 */
343 function debug($message)
344 {
345 if ($this->debug)
346 {
347 $this->debuginfo[] = $message;
348 }
349 }
350
351 /**
352 * Recursive XSS cleaner
353 *
354 * @param mixed Unsanitized REQUEST data
355 *
356 * @return mixed Sanitized data
357 */
358 function _sanitize_input_recursive($data)
359 {
360 foreach($data AS $key => $value)
361 {
362 if (is_array($value))
363 {
364 $data["$key"] = $this->_sanitize_input_recursive($value);
365 }
366 else
367 {
368 if ($this->escapestrings)
369 {
370 $data["$key"] = $this->escape($this->sanitize($value));
371 }
372 else
373 {
374 $data["$key"] = $this->sanitize($value);
375 }
376 }
377 }
378 return $data;
379 }
380
381 /**
382 * Simple way to protect against HTML attacks with Unicode support
383 *
384 * @param str Unsanitzed text
385 *
386 * @return str Properly protected text that only encodes potential threats
387 */
388 function sanitize($text)
389 {
390 if ($this->magicquotes)
391 {
392 return str_replace(array('<', '>', '\"', '"'), array('&lt;', '&gt;', '&quot;', '&quot;'), $text);
393 }
394 else
395 {
396 return str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $text);
397 }
398 }
399
400 /**
401 * Takes text that has been processed for HTML and unsanitizes it
402 *
403 * @param str Text that needs to be turned back into HTML
404 *
405 * @return str Unsanitized text
406 */
407 function unsanitize($text)
408 {
409 if ($this->magicquotes)
410 {
411 return str_replace(array('&lt;', '&gt;', '&quot;'), array('<', '>', '\"'), $text);
412 }
413 else
414 {
415 return str_replace(array('&lt;', '&gt;', '&quot;'), array('<', '>', '"'), $text);
416 }
417 }
418
419 /**
420 * Smart addslashes() that only applies itself it the Magic Quotes GPC is off
421 *
422 * @param str Some string
423 *
424 * @return str String that has slashes added
425 */
426 function escape($str)
427 {
428 global $_isso;
429
430 if ($this->magicquotes)
431 {
432 if (isset($_isso->db))
433 {
434 if (is_resource($_isso->db->link_id))
435 {
436 return $_isso->db->escape_string(stripslashes($str));
437 }
438 else
439 {
440 return $str;
441 }
442 }
443 else
444 {
445 return $str;
446 }
447 }
448 else
449 {
450 if (isset($_isso->db))
451 {
452 if (is_resource($_isso->db->link_id))
453 {
454 return $_isso->db->escape_string($str);
455 }
456 else
457 {
458 return addslashes($str);
459 }
460 }
461 else
462 {
463 return addslashes($str);
464 }
465 }
466 }
467
468 /**
469 * Runs through all of the input data and sanitizes it.
470 */
471 function exec_sanitize_data()
472 {
473 $this->input = $this->_sanitize_input_recursive(array_merge($_GET, $_POST));
474 $this->i =& $this->input;
475 $this->in =& $this->input;
476 // we're now using magic quotes
477 $this->magicquotes = 1;
478 }
479 }
480
481 /**
482 * Global callback used for module calls back to the kernel
483 */
484 $_isso = new Shared_Object_Framework();
485
486 /**
487 * Wrapper for ternary operator that has to be in the global scope
488 *
489 * @param expr Expression
490 * @param mixed If the expression is true
491 * @param mixed If the expression is false
492 *
493 * @return mixed True or false data
494 */
495 function iff($condition, $iftrue, $iffalse = null)
496 {
497 return ($condition) ? ($iftrue) : ($iffalse);
498 }
499
500 /*=====================================================================*\
501 || ###################################################################
502 || # $HeadURL$
503 || # $Id$
504 || ###################################################################
505 \*=====================================================================*/
506 ?>