. ======================================================================*/ /** @mainpage KjwLib-php45 * * KjwLib-45 is a PHP4.3+ and PHP5 compatible library for PHP. * It tries to simplify a couple of common operations, most notably the * use of database storage, early error handling (with backtraces by * mail or as inline-html) and plain mail support that handles UTF-8 * properly. * * @section database_example Database example *
* //define('KJW_STDLOG', fopen('/tmp/debug_log', 'w')); // uncomment to get debug log * require_once 'KjwSql.php'; * $db = kjwsql_from_url('mysql://user:pass\@host/database'); * $db->insertArray('mytable', array('string_column', 'somestring', 'int_column', 1234)); * echo $db->insertId(); ** * This does the following behind the scenes: * - Connect to the MySQL database host 'host' with credentials 'user' * and 'pass'. * - Selects the database 'database'. * - Creates an insert statement with columns `string_column` and `int_column`, * properly escaped for MySQL (using backticks) and 'somestring' escaped by * using php's mysql_real_escape_string. * - Executes the statement and checks for errors. * - Finally it echoes the mysql_insert_id (the new id created by the * AUTO_INCREMENT column, if available. * * @section errorhandling_example Error handling example *
* ini_set('date.timezone', 'Europe/Amsterdam'); // only set this if not set in config already * error_reporting(E_ALL | E_STRICT); // optional, depends on your config * define('KJW_EMAIL_ERRORS_TO', 'your-email\@example.com'); // don't define this if you want your errors on display * require_once 'KjwLib.php'; * $x = $undefined_variable; // <-- THIS TRIGGERS AN ERROR ** * This makes sure that you get a pretty backtrace about where you're * referencing $undefined_variable before it was set, either by mail or on * display. */ require_once(dirname(__FILE__) . '/KjwCompat.php'); require_once(dirname(__FILE__) . '/KjwObject.php'); /** @defgroup globals Library globals * * KjwLib global functions. */ /** @ingroup globals * * Stores a suppressed error. When you use the at-sign (@) to suppress * an error, the error message is stored in this global. * Normally, you do not need to suppress many errors. * Think twice before using it. */ $kjw_suppressed_error = null; /** @ingroup globals * * We don't want to have to use @-error-suppression in our own shutdown * or error handlers. Use this to get dictionary values without having * to trap errors. * * @param $dict The associative array. * @param $key The key of the element to get. * @param $default The value to return when the key does not exist. * Defaults to the empty string. * @return The value or the supplied default. */ function kjw_array_get($dict, $key, $default = '') { if (!isset($dict[$key])) return $default; return $dict[$key]; } /** @ingroup globals * * The KjwLib error handler. This handles all PHP errors which are trapped * by the `error_reporting` ini variable. All non-suppressed errors get sent * to kjw_croak(). If you suppress the error, the error message is stored * in the $kjw_suppressed_error global. * * @param $errno An error number. * @param $errstr An error message. * @param $errfile The full path of the file in which the error occurred. * @param $errline The line in the file where the error occurred. * @param $errcontext The variables local to where the error occurred. * @note You do not call this. PHP calls this. */ function kjw_error_handler($errno, $errstr, $errfile, $errline, $errcontext) { // If error_reporting returns 0, the user suppressed the error (e.g. with '@'). if (($error_reporting = error_reporting()) != 0) { // Only do something if user error_reporting matches if ($error_reporting & $errno) { //// Check exceptions.. this is here for PHP4/5 compatibility (4 doesn't have the static keyword). */ //if (preg_match('/^Non-static method .* should not be called statically$/', $errstr)) // return; //if (preg_match('/^is_a\(\): Deprecated\./', $errstr)) // DAMMIT! // return; // Die die die, with a nice message. kjw_croak('(global)', 'Internal Server Error', "$errstr.", 1); } } else { global $kjw_suppressed_error; $kjw_suppressed_error = $errstr; } } /** @ingroup globals * * Shutdown handler to catch fatal errors. See discussion here: * http://stackoverflow.com/questions/277224/how-do-i-catch-a-php-fatal-error * * @note You do not call this. PHP calls this. */ function kjw_on_shutdown() { $error = error_get_last(); /* * > The following error types cannot be handled with a user defined * > function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, * > E_COMPILE_ERROR, E_COMPILE_WARNING [...]. * I.e. we have to catch them here. We explicitly *ignore* all other errors * here because they *were* handled by our custom error handler already * (or suppressed, in which case they would show up here causing trouble). */ if ($error !== null && in_array($error['type'], array( E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING ))) { kjw_error_handler($error['type'], $error['message'], $error['file'], $error['line'], array()); } } /** @ingroup globals * * Print a message to the resource pointed to by KJW_STDLOG. * If you want to debug SQL queries for example, fopen() a file in write mode * and assign it to the KJW_STDLOG define. Some KjwLib functions and methods * call this. It might be useful for profiling. * * @param $msg The message to print. * @param $level The importance (DEBUG, INFO, NOTICE, WARNING, ERROR). * @param $namespace The tracing object name or context. */ function kjw_trace($msg, $level = 'DEBUG', $namespace = '(global)') { if (defined('KJW_STDLOG')) fwrite(KJW_STDLOG, strftime('%y-%m-%d %H:%M:%S %z: ') . "$level: $namespace: $msg\n"); } /** @ingroup globals * * Report an error and die. This function checks php_sapi_name() to see * if we're running CLI or non-CLI (CGI) mode. In non-CLI mode we add HTML * to the error message for extra readability. * * The KJW_EMAIL_ERRORS_TO decides whether we should print the detailed message as well * or print only the short one and send the detailed message by email. * A call to trace()/kjw_trace() is also made. * * @param $namespace The class/namespace where the croaking was initiated. * @param $shortMsg An accompanying message which contains no information an * attacker might use. * @param $detailedMsg An accompanying message with all the details. * @param $backtraceShift How many functions we should pop from the stack so we don't show * the error handling itself. * @return This function does *not* return. */ function kjw_croak($namespace, $shortMsg, $detailedMsg, $backtraceShift = 0) { // User might expect the error and ignore (@-prefix). // This is not recommended though. if (error_reporting() == 0) { global $kjw_suppressed_error; $kjw_suppressed_error = $detailedMsg; return; } // What will it be? $print_html = php_sapi_name() != 'cli'; // Set message content $shortTextMsg = "** $shortMsg **\n\n" . "An error has occurred. We apologise for the inconvenience and ask you to try again later.\n" . "Most likely, the webmaster is working on fixing this error at this very moment.\n"; $shortHtmlMsg = "
[DETAILS]\n * " . implode("\n * ", $details) . "\n\n[BACKTRACE]\n$backtrace\n"; $totalMsg .= "