[PHP5] ODEBUGGER PACKAGE 20060928 : Thanks to Sven Drieling, I corrected a bug on Unix, in the odebugger::createlog() method. Replaced : $aTemp = explode ('\\', $sTemp); with $aTemp = preg_split('#/|\\\\#', $sTemp); 20060926 : Code has been updated! Various additions : - Some bug corrections - Options added (path to different files, so that it can be used anyway on a web server) - Options ENABLE or DISABLE (see French readme...sorry, did not have time to translate it properly)/ Basically, used to enable or disable an error level : oDebugger::DISABLE= E_STRICT will disable debugging on E_STRICT errors. By default, all levels are enabled. - Added use of CONTEXT. Beware : context can be heavy...! I'll add an option to disable that, just in case...CONTEXT just shows every variable initialized when an error/exception has ben caught. and some other mnior stuff... :-) I'll come back for a better translation (a new readme.txt file).
THis package is a debugging and helper tool. It overrides the errors and exceptions handling by PHP. Errors are generated, even if error_reporting is set to 0. Errors are translated in a more comprehensive way, and hints for a correction is displayed. Errors can be displayed realtime, and/or logged in an XML file. This tool can be used by beginners, because it gives them a more comprehensive error message, and hint to debug their code. Gurus can personalize it to fit their needs.
It's easy to use, you can find some examples in all the indexN.php pages.
Version 20060612
- Localized in : French, English (ENglish being the default language) - Many errors translated and hinted - Error types translated - 2 different kinds of display : the Realtime mode, and the Stats mode. - Easyly configurable : translations, new error messages, hints, display and so on.
HOW TO : * How to call the debugger :
$oDebugger = new odebugger ('EN');
Where 'EN' is the chosen language. Check the 'xml/' folder to see which languages are currently supported. English being the default language, you can call the debugger this way, too, for English : $oDebugger = new odebugger;
* How to add a new language : In the xml/ folder, you can find surbolders. Each one contains the XML files for a different language. 'EN/' => English 'FR/' => French. If you want to add, for example, German, just create a 'GE/' subfolder, and copy both the xml files : errors.xml and types.xml into the new folder. Then, edit them. All you have to do is change the and nodes in the XML files. And that's it! You can then call the debugger in German : $oDebugger = new odebugger ('GE');
How to add a new error : Well, just edit the chose language errors.xml file (xml/LANGUAGE/errors.xml), and copy/paste a node within the root node. It must follow the others:
An index has been used without being defined Check the max and min limits of your array
Just change the values, save the file, and that's it. You can, of course, also change an existing node, if you do not like my translations/suggestions ;-)
* How to change the display: Well, there is currently 2 types of display : realtime, and stats. IN the folder 'templates/', you can find some files. For example : default.dat default_log.dat
default.dat is the default realtime display HTML template, while default_log.dat is the default stat HTML template. You can create your own, of course. The information supplied by odebugger replace the {INFO_NAME} types of string. Just make sure you put all the information you want in your templates :-) For the stats template, there is a slight difference : it has 3 parts. The first one starts from the...start, and ends on : <--! LINES HERE -->. This part is fixed. These are the headers!
Then, between <--! LINES HERE -->. and , the logs will be displayed. And of course, the lines here will be repeated as many times as you have lines in your log. Then, after , you have your stats :-)
You can set new templates with : odebugger::HTML and odebugger::HTMLLOG properties. See the part of this documentation about the OPTIONS.
In the 'css/' folder, you can also find files. These are the CSS files used to modify the HTML templates. default.dat being the CSS for the default.dat HTML template. default_log.dat being the CSS for the default_log.dat HTML template. You can also, of course, set them : odebugger::CSS and odebugger::CSSLOG
odebugger::LINES => integer : gives the number of source code lines to be displayed before and after the error line default value : 2
odebugger::HTML => string with the name of the file for the HTML template, in the 'templates/' folder, without its extension. Used to display the realtime log. default value : 'default'
odebugger::CSS => string with the name of the file for the CSS template, in the 'css/' folder, without its extension. Used to transform the HTML template for realtime log. default value : 'default'
odebugger::HTMLLOG => string with the name of the file for the HTML template, in the 'templates/' folder, without its extension. Used to display the stats log. default value : 'default_log'
odebugger::CSSLOG => string with the name of the file for the CSS template, in the 'css/' folder, without its extension. Used to transform the HTML template for stats log. default value : 'default_log'
odebugger::REALTIME => boolean : true or false. Activate or de-activate the realtime mode (errors are displayed realtime) default value : true
odebugger::LOGFILE => boolean : true or false. Activate or de-activate the saving of the log into an xml files (in 'logs/'). These can be displayed via odebugger::showLog () method, and loaded with the odebugger::loadXML () method. default value : true
odebugger::ERROR => Boolean : true or false. Activate or de-activate the errors handling. default value : true
odebugger::EXCEPTION => Boolean : true or false. Activate or de-activate the exceptions handling. default value : true
You can also retrieve these values : echo $oDebugger -> LINES; // displays 2
METHODS (the ones you can call only) :
odebugger::checkCode (string sString) Used to check if there are any errors in a string (usually used by retrieving in a string the content of a file. See index3.php to see that in action).
odebugger::loadXML (string sFile) Used to get an existing log from a file (logs are stored in the 'logs/' folder). This method erase any previous log (realtime or not).
odebugger::showAll () Used to display the whole current log, just as if it was in realtime mode. You can display a loaded log, or the current realtime log.
odebugger::showLog () Used to display the whole current log in stats mode. You can display a loaded log, or the current realtime log.
odebugger::saveToFile (optional string sFile) Used to save the current log to a file. This methods is used automatically when the script ends, if odebugger::LOGFILE is set to true. But it can be called manually, with a filename.
By : malalam
<?php /** * CLASS odebugger * * @author : johan <barbier_johan@hotmail.com> */ class odebugger {
/** * private (string) sAssertion * Check if error comes from an essertion or not, if yes, will conatin the filename of the evaluated script */ private $sAssertion = null; /** * private (string) sLang * localization string */ private $sLang = 'EN';
/** * private (int) iNbLines * Number of lines displayed before and after the line of the error */ private $iNbLines = 2;
/** * public function __construct () * contsructor * sets the error_reporting to 0 * gets the localization dir * import all the xml files * set the error handler * @Param (string) sLang : the localization used */ public function __construct ($sLang = 'EN') { @error_reporting (0);
/** * public function checkCode () * use the assert () function to get the errors in a given string, or a given file * @Param (string) sString : the string with the PHP code to evaluate, or the file to evaluate. Usually, it will come from a file via file_get_contents () for example * @Return : false if given parameter is not a string. */ public function checkCode ($sCode) { if (file_exists ($sCode)) { $sString = file_get_contents ($sCode); $this -> sAssertion = $sCode; } elseif (!is_string ($sCode)) { return false; } else { $sString = $sCode; } $sString = str_replace (array ('<?php', '<?', '?>'), '', $sString); assert_options(ASSERT_ACTIVE, 1); assert_options(ASSERT_WARNING, 0); assert_options(ASSERT_QUIET_EVAL, 1); //assert_options (ASSERT_CALLBACK, array ($this, 'myAssertHandler')); Waiting a bit to improve this part assert ($sString); assert_options(ASSERT_ACTIVE, 0); }
/** * public function myAssertHandler () * activate the assertion. Right now, does nothing...and is not used. * @Param (string) file : the file from which comes the code * @Param (int) line : the error line * @Param (string) code : the error code * @Return : true */ public function myAssertHandler ($file, $line, $code){ return true; }
/** * private function checkErrorMessage () * try to find the correct trsnalation and suggestion from a given error message * @Param (string) sMsg : the PHP error message * @Return (array) aTempArr : array with the translation and the suggestion found */ private function checkErrorMessage ($sMsg) { $iLength = strlen ($sMsg); $xpath = new DOMXPath($this -> oXMLERRORS); $sQueryLabel = '//error/label'; $oLabelLists = $xpath -> query ($sQueryLabel); $aMsg = explode (' ', $sMsg); foreach ($oLabelLists as $oLabel) { $aLabel = explode (' ', $oLabel -> nodeValue); $aDiff = array_diff ($aLabel, $aMsg); if (empty ($aDiff)) { $aTempArr['TRANSLATION'] = $oLabel -> nextSibling -> nextSibling -> nodeValue; $aTempArr['SUGGESTION'] = $oLabel -> nextSibling -> nextSibling -> nextSibling -> nextSibling -> nodeValue; return $aTempArr; } } }
/** * private function checkTypeTrans () * try to find the error type translation * @Param (int) cErrno : the PHP constant error type code * @Return (string) nodeValue : the translated error type */ private function checkTypeTrans ($cErrno) { $xpath = new DOMXPath($this -> oXMLTYPES); $sQueryLevel = '//type/level'; $oLevelList = $xpath -> query ($sQueryLevel); foreach ($oLevelList as $oLevel) { if (constant ($oLevel -> nodeValue) === $cErrno) { return $oLevel -> nextSibling -> nextSibling -> nodeValue; } } }
/** * public function myExceptionHandler () * the exception handler : builds the XML error log * @Param (object) e : the Exception object */ public function myExceptionHandler ($e) { $sErrStr = $e -> getMessage (); $iErrLine = $e -> getLine (); $sType = 'Exception '.$e -> getCode (); if (is_null ($this -> sAssertion)) { $sErrFile = $e -> getFile (); } else { $sErrFile = $this -> sAssertion; $this -> sAssertion = null; } $sVars = $e -> getTraceAsString (); $aTempArr = array ('TRANSLATION' => '', 'SUGGESTION' => '');
$aElem[] = $this -> oXMLDOC -> createElement ('CONTEXT', $sVars); $oSource = $this -> oXMLDOC -> createElement ('SOURCE'); $aSourceElem = array (); foreach ($this -> getLine ($sErrFile, $iErrLine) as $iLine => $sLine) { $sLine = utf8_encode ($sLine); if ($iLine === ($iErrLine)) { $aSourceElem[] = $this -> oXMLDOC -> createElement ('SOURCE_LINE_ERROR', ' /** ERROR AROUND THIS LINE => */ '.$sLine); } else { $aSourceElem[] = $this -> oXMLDOC -> createElement ('SOURCE_LINE', $sLine); } } foreach ($aSourceElem as $oSourceElem) { $oSource -> appendChild ($oSourceElem); } foreach ($aElem as $oElem) { $oNewLog -> appendChild ($oElem); } $oNewLog -> appendChild ($oSource); $this -> oCurrentNode = $oNewLog; if (true === $this -> aOptions['REALTIME']) { $this -> printMe (); } } /** * private function getLine () * method to get the lines around the detected error * @Param (string) sErrFile : the file in which the error has been detected * @Param (int) iErrLine : the line of the error * @Return (array) aSource : array with each line */ private function getLine ($sErrFile, $iErrLine) { $aSource = array (); if (file_exists ($sErrFile)) { $aLines = file ($sErrFile); for ($i = $iErrLine - $this -> iNbLines; $i<= $iErrLine + $this -> iNbLines; $i ++) { if (isset ($aLines[$i])) { $aSource[$i] = $aLines[$i]; } } } return $aSource; }
/** * public function loadXML () * loads an external error log * @Param (string) sFile : the error log file to be loaded */ public function loadXML ($sFile) { if (!file_exists ('logs/'.$sFile)) { return false; } $this -> oXMLDOC -> load ('logs/'.$sFile); }
/** * public function showAll () * show the whole current xml log */ public function showAll () { $xpath = new DOMXPath($this -> oXMLDOC); $sQuery = '//ERROR'; $oNodeLists = $xpath -> query ($sQuery); foreach ($oNodeLists as $oNodeList) { $this -> oCurrentNode = $oNodeList; $this -> printMe (); } }
/** * public function showLog () * show the whole current log in a table, with stats (best used after odebugger::loadXML()) * @Return (string) sHtml : the generated HTML */ public function showLog () { $sBaseHtml = file_get_contents ('templates/'.$this -> sTemplateHTMLLOG.'.dat'); $iStartPos = strpos ($sBaseHtml, '<!-- LINES HERE -->'); $sHtml = substr ($sBaseHtml, 0, $iStartPos); $iEndPos = strpos ($sBaseHtml, '<!-- STATS -->'); $iLength = strlen ($sBaseHtml); $sTempHtml = substr ($sBaseHtml, $iStartPos, - ($iLength - $iEndPos)); $sTempHtmlTotal = ''; $xpath = new DOMXPath($this -> oXMLDOC); $sQuery = '//ERROR'; $oNodeLists = $xpath -> query ($sQuery); foreach ($oNodeLists as $oNodeList) { $this -> oCurrentNode = $oNodeList; $sTempHtmlTotal .= $this -> printMeLog ($sTempHtml); } $sHtml .= $sTempHtmlTotal; $sQuery = '//ERROR/TYPE'; $oNodeLists = $xpath -> query ($sQuery); foreach ($oNodeLists as $oNodeList) { $aTypes[] = $oNodeList -> nodeValue; } $sHtml .= substr ($sBaseHtml, $iEndPos, ($iLength - 1)); $aCountType = array_count_values ($aTypes); $sCountType = ''; foreach ($aCountType as $kType => $vType) { $sCountType .= $kType.' : '.$vType.'<br />'; } $sVersion = @phpversion (); $sHtml = str_replace ($this -> aIndex[100], $sCountType, $sHtml); $sHtml = str_replace ($this -> aIndex[101], $sVersion , $sHtml); return $sHtml; }
/** * public function saveToFile () * save the current log to a given file * @Param (string) sFile : name of the log file */ public function saveToFile ($sFile = null) { if ($sFile === null) { $sFile = $this -> sCurId.'_error_log.xml'; } $this -> oXMLDOC -> save ($this -> sCurDir.'logs/'.$sFile); }
/** * public function __destruct () * destructor * will save the log to a file if the LOG_FILE option is set to true */ public function __destruct () { if (true === $this -> aOptions['LOG_FILE']) { $this -> saveToFile (); } }
/** * public function __set () * allows some properties to be set * @Param (string) sProp : name of the property * @Param (mixed) mVal : the value to be given to the property * @Return (boolean) false if failed, true if succeeded */ public function __set ($sProp, $mVal) { if (false === array_key_exists ($sProp, $this -> aCanBeSet)) { return false; } switch ($sProp) { case 'LINES' : if (!is_int ($mVal)) { return false; } $this -> iNbLines = $mVal; return true; break; case 'HTML' : if (!file_exists ('templates/'.$mVal.'.dat')) { return false; } $this -> sTemplateHTML = $mVal; return true; break; case 'HTMLLOG' : if (!file_exists ('templates/'.$mVal.'.dat')) { return false; } $this -> sTemplateHTMLLOG = $mVal; return true; break; case 'CSS' : if (!file_exists ('css/'.$mVal.'.dat')) { return false; } $this -> sTemplateCSS = $mVal; readfile ('css/'.$mVal.'.dat'); return true; break; case 'CSSLOG' : if (!file_exists ('css/'.$mVal.'.dat')) { return false; } $this -> sTemplateCSSLOG = $mVal; readfile ('css/'.$mVal.'.dat'); return true; break; case 'REALTIME' : if (!is_bool ($mVal)) { return false; } $this -> aOptions['REALTIME'] = $mVal; return true; break; case 'LOGFILE' : if (!is_bool ($mVal)) { return false; } $this -> aOptions['LOG_FILE'] = $mVal; return true; break; case 'ERROR' : if (!is_bool ($mVal)) { return false; } $this -> aOptions['ERROR'] = $mVal; if (true === $mVal) { set_error_handler (array ($this, 'myErrorHandler')); } else { restore_error_handler (); } return true; break; case 'EXCEPTION' : if (!is_bool ($mVal)) { return false; } $this -> aOptions['EXCEPTION'] = $mVal; if (true === $mVal) { set_exception_handler (array ($this, 'myExceptionHandler')); } else { restore_exception_handler (); } return true; break; default: return false; } }
/** * public function __get () * allows some properties to be get * @Param (string) sProp : name of the property * @Return (boolean) false if failed, value of the property if succeeded */ public function __get ($sProp) { if (false === array_key_exists ($sProp, $this -> aCanBeSet)) { return false; } $sRealProp = $this -> aCanBeSet[$sProp]; return $this -> $sRealProp; } } ?>
DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.
Download the IBM WebSphere Portal V6.1 beta code and learn more about the rich features and enhancements in IBM WebSphere Portal V6.1. WebSphere Portal provides a composite application or business mashup framework and the advanced tooling needed to build flexible, SOA-based solutions, and scalability to meet the needs of any size organization. FREE! Go There Now!
Discover how IBM Rational AppScan Standard Edition can help you detext vulnerabilities in your web applications in the Web Application Security eKit. IBM Rational AppScan is a leading suite of automated web application security solutions that scan and test for common Web application vulnerabilities. The new Web Application Security eKit provides you with valuable resources, including white papers, demos, and additional information on the benefits of testing your Web applications. FREE! Go There Now!
Visit IBM developerWorks to download a free trial version of IBM Rational Business Developer V7.1. Rational Business Developer offers rapid and simplified development of business applications and services through Enterprise Generation Language (EGL) tools, generating Java or mainframe solutions while shielding developers from technical complexities. FREE! Go There Now!
Visit IBM developerWorks to download a free trial of the Rational Host Access Transformation Services (HATS) Toolkit. The HATS toolkit provides a set of plug-ins for the IBM Rational Software Delivery Platform to help you easily extend your legacy applications. HATS makes your 3270 and 5250 applications available as HTML through the most popular Web browsers, while converting your host screens to a Web look and feel and it also enables you to develop new Web, portal, and rich-client applications. FREE! Go There Now!
Manage, govern, and share services across your organization by using WebSphere Service Registry and Repository. Follow the hands-on exercises to learn how to navigate the Web interface to publish, find, reuse, and update services. FREE! Go There Now!
Join this Rational Talks to You teleconference on December 4 at 1:00 pm ET to discuss how Rational Method Composer can help meet your compliance objectives. Get your questions answered! FREE! Go There Now!
Because access to government information continues to be an area of concern for many U.S. citizens with disabilities, the U.S. government enacted Section 508 of the Rehabilitation Act in 2001 to ensure that government agencies create accessible Web content, enabling all citizens to access the information they need. A fully accessible Web site makes Web content accessible to all individuals, including those with disabilities, who may be accessing Web content via a variety of user agents. Common user agents include standard Web browsers, text-only browsers, assistive devices and mobile devices such as cell phones or personal digital assistants (PDAs). FREE! Go There Now!
Informix Dynamic Server (IDS) Express Edition offers outstanding online transaction processing (OLTP) database performance, while helping to simplify and automate many of the tasks associated with deploying databases for small business applications. IDS 11 further extends the ease of management and applications integration with the Admin API and Scheduler, high availability with Continuous Log Restore for backup server recovery in case of a primary server failure, and column level encryption to protect personal and company private data. FREE! Go There Now!
Whether you are creating new applications or modifying existing ones, managing integration of new components with traditional z/OS elements is a critical part of building and deploying modern applications. Listen to this webcast to see how IBM can help you optimize your development process using an IDE like Rational Developer for System z that integrates with management tools, such as ClearCase to manage your application development on mainframes. FREE! Go There Now!
The unprecedented scope of a service-oriented architecture (SOA) initiative brings to the forefront a number of management and governance issues that were sidestepped in the past. The key to a successful SOA implementation is managing and governing activities throughout the entire SOA delivery lifecycle by ensuring that services conform to the needs of all of the business’s stakeholders. Learn how service lifecycle management allows the business to ensure that the process by which services are defined, created, tested, deployed, optimized and retired is manageable, repeatable and auditable. FREE! Go There Now!