eZ Publish  [4.0]
ezdebug.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZDebug class
00004 //
00005 // Created on: <12-Feb-2002 11:00:54 bf>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*! \defgroup eZUtils Utility classes */
00032 
00033 /*!
00034   \class eZDebug ezdebug.php
00035   \ingroup eZUtils
00036   \brief Advanced debug/log system
00037 
00038   The eZ debug library is used to handle debug information. It
00039   can display information on screen and/or write it to log files.
00040 
00041   You can enable on-screen debug information for specific IP addresses.
00042 
00043   Timing points can be placed in the code to time the different sections of code.
00044 
00045   Each debug message can be turned on/off by using the showTypes() function.
00046 
00047   PHP error messages can also be shown using setHandleType().
00048 
00049   \code
00050   require_once( "lib/ezutils/classes/ezdebug.php" );
00051 
00052   // write a temporary debug message
00053   eZDebug::writeDebug( "Test" );
00054 
00055   // write a notice
00056   eZDebug::writeNotice( "Image found" );
00057 
00058   // write a warning
00059   eZDebug::writeWarning( "Image not found, using default" );
00060 
00061   // write an error
00062   eZDebug::writeError( "Object not found, bailing.." );
00063 
00064   // add a timing points
00065   eZDebug::addTimingPoint( "Module Found" );
00066 
00067   //.... code
00068 
00069   eZDebug::addTimingPoint( "Module loading" );
00070 
00071   // print the results on screen.
00072   eZDebug::printReport();
00073 
00074   \endcode
00075 */
00076 
00077 //include_once( "lib/ezutils/classes/ezsys.php" );
00078 
00079 class eZDebug
00080 {
00081     const LEVEL_NOTICE = 1;
00082     const LEVEL_WARNING = 2;
00083     const LEVEL_ERROR = 3;
00084     const LEVEL_TIMING_POINT = 4;
00085     const LEVEL_DEBUG = 5;
00086     const LEVEL_STRICT = 6;
00087 
00088     const SHOW_NOTICE = 1; // 1 << (EZ_LEVEL_NOTICE - 1)
00089     const SHOW_WARNING = 2; // 1 << (EZ_LEVEL_WARNING - 1)
00090     const SHOW_ERROR = 4; // 1 << (EZ_LEVEL_ERROR - 1)
00091     const SHOW_TIMING_POINT = 8; // 1 << (EZ_LEVEL_TIMING_POINT - 1)
00092     const SHOW_DEBUG = 16; // 1 << (EZ_LEVEL_DEBUG - 1)
00093     const SHOW_STRICT = 32; // 1 << (EZ_LEVEL_STRICT - 1)
00094     const SHOW_ALL = 63; // EZ_SHOW_NOTICE | EZ_SHOW_WARNING | EZ_SHOW_ERROR | EZ_SHOW_TIMING_POINT | EZ_SHOW_DEBUG | EZ_SHOW_STRICT
00095 
00096     const HANDLE_NONE = 0;
00097     const HANDLE_FROM_PHP = 1;
00098     const HANDLE_TO_PHP = 2;
00099 
00100     const OUTPUT_MESSAGE_SCREEN = 1;
00101     const OUTPUT_MESSAGE_STORE = 2;
00102 
00103     const MAX_LOGFILE_SIZE = 204800; // 200*1024
00104     const MAX_LOGROTATE_FILES = 3;
00105 
00106     const XDEBUG_SIGNATURE = '--XDEBUG--';
00107 
00108     /*!
00109       Creates a new debug object.
00110     */
00111     function __construct( )
00112     {
00113         $this->TmpTimePoints = array( self::LEVEL_NOTICE => array(),
00114                                       self::LEVEL_WARNING => array(),
00115                                       self::LEVEL_ERROR => array(),
00116                                       self::LEVEL_DEBUG => array(),
00117                                       self::LEVEL_STRICT => array() );
00118 
00119         $this->OutputFormat = array( self::LEVEL_NOTICE => array( "color" => "green",
00120                                                                'style' => 'notice',
00121                                                                'xhtml-identifier' => 'ezdebug-first-notice',
00122                                                                "name" => "Notice" ),
00123                                      self::LEVEL_WARNING => array( "color" => "orange",
00124                                                                 'style' => 'warning',
00125                                                                 'xhtml-identifier' => 'ezdebug-first-warning',
00126                                                                 "name" => "Warning" ),
00127                                      self::LEVEL_ERROR => array( "color" => "red",
00128                                                               'style' => 'error',
00129                                                               'xhtml-identifier' => 'ezdebug-first-error',
00130                                                               "name" => "Error" ),
00131                                      self::LEVEL_DEBUG => array( "color" => "brown",
00132                                                               'style' => 'debug',
00133                                                               'xhtml-identifier' => 'ezdebug-first-debug',
00134                                                               "name" => "Debug" ),
00135                                      self::LEVEL_TIMING_POINT => array( "color" => "blue",
00136                                                                      'style' => 'timing',
00137                                                                      'xhtml-identifier' => 'ezdebug-first-timing-point',
00138                                                                      "name" => "Timing" ),
00139                                      self::LEVEL_STRICT => array( "color" => "purple",
00140                                                               'style' => 'strict',
00141                                                               'xhtml-identifier' => 'ezdebug-first-strict',
00142                                                               'name' => 'Strict' ) );
00143         $this->LogFiles = array( self::LEVEL_NOTICE => array( "var/log/",
00144                                                            "notice.log" ),
00145                                  self::LEVEL_WARNING => array( "var/log/",
00146                                                             "warning.log" ),
00147                                  self::LEVEL_ERROR => array( "var/log/",
00148                                                           "error.log" ),
00149                                  self::LEVEL_DEBUG => array( "var/log/",
00150                                                           "debug.log" ),
00151                                  self::LEVEL_STRICT => array( 'var/log/',
00152                                                            'strict.log' ) );
00153         $this->MessageTypes = array( self::LEVEL_NOTICE,
00154                                      self::LEVEL_WARNING,
00155                                      self::LEVEL_ERROR,
00156                                      self::LEVEL_TIMING_POINT,
00157                                      self::LEVEL_DEBUG,
00158                                      self::LEVEL_STRICT );
00159         $this->MessageNames = array( self::LEVEL_NOTICE => 'Notice',
00160                                      self::LEVEL_WARNING => 'Warning',
00161                                      self::LEVEL_ERROR => 'Error',
00162                                      self::LEVEL_TIMING_POINT => 'TimingPoint',
00163                                      self::LEVEL_DEBUG => 'Debug',
00164                                      self::LEVEL_STRICT => 'Strict' );
00165         $this->LogFileEnabled = array( self::LEVEL_NOTICE => true,
00166                                        self::LEVEL_WARNING => true,
00167                                        self::LEVEL_ERROR => true,
00168                                        self::LEVEL_TIMING_POINT => true,
00169                                        self::LEVEL_DEBUG => true,
00170                                        self::LEVEL_STRICT => true );
00171         $this->AlwaysLog = array( self::LEVEL_NOTICE => false,
00172                                   self::LEVEL_WARNING => false,
00173                                   self::LEVEL_ERROR => true, // Error is on by default, due to its importance
00174                                   self::LEVEL_TIMING_POINT => false,
00175                                   self::LEVEL_DEBUG => false,
00176                                   self::LEVEL_STRICT => false );
00177         $this->GlobalLogFileEnabled = true;
00178         if ( isset( $GLOBALS['eZDebugLogFileEnabled'] ) )
00179         {
00180             $this->GlobalLogFileEnabled = $GLOBALS['eZDebugLogFileEnabled'];
00181         }
00182         $this->ShowTypes = self::SHOW_ALL;
00183         $this->HandleType = self::HANDLE_NONE;
00184         $this->OldHandler = false;
00185         $this->UseCSS = false;
00186         $this->MessageOutput = self::OUTPUT_MESSAGE_STORE;
00187         $this->ScriptStart = microtime( true );
00188         $this->TimeAccumulatorList = array();
00189         $this->TimeAccumulatorGroupList = array();
00190         $this->OverrideList = array();
00191         $this->topReportsList = array();
00192         $this->bottomReportsList = array();
00193     }
00194 
00195     function reset()
00196     {
00197         $this->DebugStrings = array();
00198         $this->TmpTimePoints = array( self::LEVEL_NOTICE => array(),
00199                                       self::LEVEL_WARNING => array(),
00200                                       self::LEVEL_ERROR => array(),
00201                                       self::LEVEL_DEBUG => array(),
00202                                       self::LEVEL_STRICT => array() );
00203         $this->TimeAccumulatorList = array();
00204         $this->TimeAccumulatorGroupList = array();
00205         $this->topReportsList = array();
00206         $this->bottomReportsList = array();
00207     }
00208 
00209     /*!
00210      \return the name of the message type.
00211     */
00212     function messageName( $messageType )
00213     {
00214         return $this->MessageNames[$messageType];
00215     }
00216 
00217     /*!
00218       Will return the current eZDebug object. If no object exists one will
00219       be created.
00220     */
00221     static function instance( )
00222     {
00223         if ( empty( $GLOBALS["eZDebugGlobalInstance"] ) )
00224         {
00225             $GLOBALS["eZDebugGlobalInstance"] = new eZDebug();
00226         }
00227         return $GLOBALS["eZDebugGlobalInstance"];
00228     }
00229 
00230     /*!
00231      \static
00232      Returns true if the message type $type can be shown.
00233     */
00234     static function showMessage( $type )
00235     {
00236         $debug = eZDebug::instance();
00237         return $debug->ShowTypes & $type;
00238     }
00239 
00240     /*!
00241      \return \c true if the debug level \a $level should always log to file.
00242     */
00243     static function alwaysLogMessage( $level )
00244     {
00245         $instance = eZDebug::instance();
00246         // If there is a global setting for this get the value
00247         // and unset it globally
00248         if ( isset( $GLOBALS['eZDebugAlwaysLog'] ) )
00249         {
00250             $instance->AlwaysLog = $GLOBALS['eZDebugAlwaysLog'] + $instance->AlwaysLog;
00251             unset( $GLOBALS['eZDebugAlwaysLog'] );
00252         }
00253 
00254         if ( !isset( $instance->AlwaysLog[$level] ) )
00255         {
00256             return false;
00257         }
00258         return $instance->AlwaysLog[$level];
00259     }
00260 
00261     /*!
00262      Determines how PHP errors are handled. If $type is self::HANDLE_TO_PHP all error messages
00263      is sent to PHP using trigger_error(), if $type is self::HANDLE_FROM_PHP all error messages
00264      from PHP is fetched using a custom error handler and output as a usual eZDebug message.
00265      If $type is self::HANDLE_NONE there is no error exchange between PHP and eZDebug.
00266     */
00267     static function setHandleType( $type )
00268     {
00269         $instance = eZDebug::instance();
00270 
00271         if ( $type != self::HANDLE_TO_PHP and
00272              $type != self::HANDLE_FROM_PHP )
00273             $type = self::HANDLE_NONE;
00274         if ( extension_loaded( 'xdebug' ) and
00275              $type == self::HANDLE_FROM_PHP )
00276             $type = self::HANDLE_NONE;
00277         if ( $type == $instance->HandleType )
00278             return $instance->HandleType;
00279 
00280         if ( $instance->HandleType == self::HANDLE_FROM_PHP )
00281             restore_error_handler();
00282         switch ( $type )
00283         {
00284             case self::HANDLE_FROM_PHP:
00285             {
00286                 set_error_handler( "eZDebugErrorHandler" );
00287             } break;
00288 
00289             case self::HANDLE_TO_PHP:
00290             {
00291                 restore_error_handler();
00292             } break;
00293 
00294             case self::HANDLE_NONE:
00295             {
00296             }
00297         }
00298         $oldHandleType = $instance->HandleType;
00299         $instance->HandleType = $type;
00300         return $oldHandleType;
00301     }
00302 
00303     /*!
00304      \static
00305      Sets types to be shown to $types and returns the old show types.
00306      If $types is not supplied the current value is returned and no change is done.
00307      $types is one or more of self::SHOW_NOTICE, self::SHOW_WARNING, self::SHOW_ERROR, self::SHOW_TIMING_POINT
00308      or'ed together.
00309     */
00310     static function showTypes( $types = false )
00311     {
00312         $instance = eZDebug::instance();
00313 
00314         if ( $types === false )
00315         {
00316             return $instance->ShowTypes;
00317         }
00318         $old_types = $instance->ShowTypes;
00319         $instance->ShowTypes = $types;
00320         return $old_types;
00321     }
00322 
00323     /*!
00324      Handles PHP errors, creates notice, warning and error messages for
00325      the various PHP error types.
00326     */
00327     function errorHandler( $errno, $errstr, $errfile, $errline )
00328     {
00329         if ( error_reporting() == 0 ) // @ error-control operator is used
00330             return;
00331         if ( !eZDebug::isDebugEnabled() )
00332             return;
00333         $str = "$errstr in $errfile on line $errline";
00334         if ( empty( $GLOBALS["eZDebugPHPErrorNames"] ) )
00335         {
00336             $GLOBALS["eZDebugPHPErrorNames"] =
00337                 array( E_ERROR => "E_ERROR",
00338                        E_PARSE => "E_PARSE",
00339                        E_CORE_ERROR => "E_CORE_ERROR",
00340                        E_COMPILE_ERROR => "E_COMPILE_ERROR",
00341                        E_USER_ERROR => "E_USER_ERROR",
00342                        E_WARNING => "E_WARNING",
00343                        E_CORE_WARNING => "E_CORE_WARNING",
00344                        E_COMPILE_WARNING => "E_COMPILE_WARNING",
00345                        E_USER_WARNING => "E_USER_WARNING",
00346                        E_NOTICE => "E_NOTICE",
00347                        E_USER_NOTICE => "E_USER_NOTICE",
00348                        E_STRICT => "E_STRICT" );
00349         }
00350         $errname = "unknown";
00351         if ( isset( $GLOBALS["eZDebugPHPErrorNames"][$errno] ) )
00352         {
00353             $errname = $GLOBALS["eZDebugPHPErrorNames"][$errno];
00354         }
00355         switch ( $errno )
00356         {
00357             case E_ERROR:
00358             case E_PARSE:
00359             case E_CORE_ERROR:
00360             case E_COMPILE_ERROR:
00361             case E_USER_ERROR:
00362             {
00363                 $this->writeError( $str, "PHP" );
00364             } break;
00365 
00366             case E_WARNING:
00367             case E_CORE_WARNING:
00368             case E_COMPILE_WARNING:
00369             case E_USER_WARNING:
00370             case E_NOTICE:
00371             {
00372                 $this->writeWarning( $str, "PHP" );
00373             } break;
00374 
00375             case E_USER_NOTICE:
00376             {
00377                 $this->writeNotice( $str, "PHP" );
00378             } break;
00379 
00380             case E_STRICT:
00381             {
00382                 return $this->writeStrict( $str, "PHP" );
00383             } break;
00384         }
00385     }
00386 
00387     /*!
00388       \static
00389       Writes a strict debug message.
00390 
00391       The global variable \c 'eZDebugStrict' will be set to \c true if the notice is added.
00392       \param $label This label will be associated with the strict message, e.g. to say where the message came from.
00393       \param $backgroundClass A string defining the class to use in the HTML debug output.
00394     */
00395     static function writeStrict( $string, $label = "", $backgroundClass = "" )
00396     {
00397         $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_STRICT );
00398         $enabled = eZDebug::isDebugEnabled();
00399         if ( !$alwaysLog and !$enabled )
00400             return;
00401 
00402         $show = eZDebug::showMessage( self::SHOW_STRICT );
00403         if ( !$alwaysLog and !$show )
00404             return;
00405 
00406         if ( is_object( $string ) || is_array( $string ) )
00407              $string = eZDebug::dumpVariable( $string );
00408 
00409         $GLOBALS['eZDebugStrict'] = true;
00410         if ( !isset( $GLOBALS['eZDebugStrictCount'] ) )
00411             $GLOBALS['eZDebugStrictCount'] = 0;
00412         ++$GLOBALS['eZDebugStrictCount'];
00413 
00414         $debug = eZDebug::instance();
00415         if ( $debug->HandleType == self::HANDLE_TO_PHP )
00416         {
00417             // If we get here only because of $alwaysLog we should not trigger a PHP error
00418             if ( $enabled and $show )
00419             {
00420                 // we can't trigger E_STRICT but we can let the default error handler handle it
00421                 // see http://www.php.net/manual/en/function.set-error-handler.php#69218
00422                 return false;
00423             }
00424         }
00425         else
00426         {
00427             $debug->write( $string, self::LEVEL_STRICT, $label, $backgroundClass, $alwaysLog );
00428             return true;
00429         }
00430     }
00431 
00432     /*!
00433       \static
00434       Writes a debug notice.
00435 
00436       The global variable \c 'eZDebugNotice' will be set to \c true if the notice is added.
00437       \param $label This label will be associated with the notice, e.g. to say where the notice came from.
00438       \param $backgroundClass A string defining the class to use in the HTML debug output.
00439     */
00440     static function writeNotice( $string, $label = "", $backgroundClass = "" )
00441     {
00442         $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_NOTICE );
00443         $enabled = eZDebug::isDebugEnabled();
00444         if ( !$alwaysLog and !$enabled )
00445             return;
00446 
00447         $show = eZDebug::showMessage( self::SHOW_NOTICE );
00448         if ( !$alwaysLog and !$show )
00449             return;
00450 
00451         if ( is_object( $string ) || is_array( $string ) )
00452              $string = eZDebug::dumpVariable( $string );
00453 
00454         $GLOBALS['eZDebugNotice'] = true;
00455         if ( !isset( $GLOBALS['eZDebugNoticeCount'] ) )
00456             $GLOBALS['eZDebugNoticeCount'] = 0;
00457         ++$GLOBALS['eZDebugNoticeCount'];
00458 
00459         $debug = eZDebug::instance();
00460         if ( $debug->HandleType == self::HANDLE_TO_PHP )
00461         {
00462             // If we get here only because of $alwaysLog we should not trigger a PHP error
00463             if ( $enabled and $show )
00464             {
00465                 if ( $label )
00466                     $string = "$label: $string";
00467                 trigger_error( $string, E_USER_NOTICE );
00468             }
00469         }
00470         else
00471         {
00472             $debug->write( $string, self::LEVEL_NOTICE, $label, $backgroundClass, $alwaysLog );
00473         }
00474     }
00475 
00476     /*!
00477       \static
00478       Writes a debug warning.
00479 
00480       The global variable \c 'eZDebugWarning' will be set to \c true if the notice is added.
00481       \param $label This label will be associated with the notice, e.g. to say where the notice came from.
00482     */
00483     static function writeWarning( $string, $label = "", $backgroundClass = "" )
00484     {
00485         $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_WARNING );
00486         $enabled = eZDebug::isDebugEnabled();
00487         if ( !$alwaysLog and !$enabled )
00488             return;
00489 
00490         $show = eZDebug::showMessage( self::SHOW_WARNING );
00491         if ( !$alwaysLog and !$show )
00492             return;
00493 
00494         if ( is_object( $string ) || is_array( $string ) )
00495             $string = eZDebug::dumpVariable( $string );
00496 
00497         $GLOBALS['eZDebugWarning'] = true;
00498         if ( !isset( $GLOBALS['eZDebugWarningCount'] ) )
00499             $GLOBALS['eZDebugWarningCount'] = 0;
00500         ++$GLOBALS['eZDebugWarningCount'];
00501 
00502         $debug = eZDebug::instance();
00503         if ( $debug->HandleType == self::HANDLE_TO_PHP )
00504         {
00505             // If we get here only because of $alwaysLog we should not trigger a PHP error
00506             if ( $enabled and $show )
00507             {
00508                 if ( $label )
00509                     $string = "$label: $string";
00510                 trigger_error( $string, E_USER_WARNING );
00511             }
00512         }
00513         else
00514         {
00515             $debug->write( $string, self::LEVEL_WARNING, $label, $backgroundClass, $alwaysLog );
00516         }
00517     }
00518 
00519     /*!
00520       \static
00521       Writes a debug error.
00522 
00523       The global variable \c 'eZDebugError' will be set to \c true if the notice is added.
00524       \param $label This label will be associated with the notice, e.g. to say where the notice came from.
00525     */
00526     static function writeError( $string, $label = "", $backgroundClass = "" )
00527     {
00528         $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_ERROR );
00529         $enabled = eZDebug::isDebugEnabled();
00530         if ( !$alwaysLog and !$enabled )
00531             return;
00532 
00533         $show = eZDebug::showMessage( self::SHOW_ERROR );
00534         if ( !$alwaysLog and !$show )
00535             return;
00536 
00537         if ( is_object( $string ) || is_array( $string ) )
00538             $string = eZDebug::dumpVariable( $string );
00539 
00540         $GLOBALS['eZDebugError'] = true;
00541         if ( !isset( $GLOBALS['eZDebugErrorCount'] ) )
00542             $GLOBALS['eZDebugErrorCount'] = 0;
00543         ++$GLOBALS['eZDebugErrorCount'];
00544 
00545         $debug = eZDebug::instance();
00546         if ( $debug->HandleType == self::HANDLE_TO_PHP )
00547         {
00548             // If we get here only because of $alwaysLog we should not trigger a PHP error
00549             if ( $enabled and $show )
00550             {
00551                 if ( $label )
00552                     $string = "$label: $string";
00553                 trigger_error( $string, E_USER_ERROR );
00554             }
00555         }
00556         else
00557         {
00558             $debug->write( $string, self::LEVEL_ERROR, $label, $backgroundClass, $alwaysLog );
00559         }
00560     }
00561 
00562     /*!
00563       \static
00564       Writes a debug message.
00565 
00566       The global variable \c 'eZDebugDebug' will be set to \c true if the notice is added.
00567       \param $label This label will be associated with the notice, e.g. to say where the notice came from.
00568     */
00569     static function writeDebug( $string, $label = "", $backgroundClass = "" )
00570     {
00571         $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_DEBUG );
00572         $enabled = eZDebug::isDebugEnabled();
00573         if ( !$alwaysLog and !$enabled )
00574             return;
00575 
00576         $show = eZDebug::showMessage( self::SHOW_DEBUG );
00577         if ( !$alwaysLog and !$show )
00578             return;
00579 
00580         if ( is_object( $string ) || is_array( $string ) )
00581             $string = eZDebug::dumpVariable( $string );
00582 
00583         $GLOBALS['eZDebugDebug'] = true;
00584         if ( !isset( $GLOBALS['eZDebugDebugCount'] ) )
00585             $GLOBALS['eZDebugDebugCount'] = 0;
00586         ++$GLOBALS['eZDebugDebugCount'];
00587 
00588         $debug = eZDebug::instance();
00589         if ( $debug->HandleType == self::HANDLE_TO_PHP )
00590         {
00591             // If we get here only because of $alwaysLog we should not trigger a PHP error
00592             if ( $enabled and $show )
00593             {
00594                 if ( $label )
00595                     $string = "$label: $string";
00596                 trigger_error( $string, E_USER_NOTICE );
00597             }
00598         }
00599         else
00600         {
00601             $debug->write( $string, self::LEVEL_DEBUG, $label, $backgroundClass, $alwaysLog );
00602         }
00603     }
00604 
00605     /*!
00606       \static
00607       \private
00608       Dumps the variables contents using the var_dump function
00609     */
00610     static function dumpVariable( $var )
00611     {
00612         // If we have var_export (PHP >= 4.2.0) we use the instead
00613         // provides better output, doesn't require output buffering
00614         // and doesn't get mangled by Xdebug
00615 
00616         // dl: we should always use 'var_dump' since 'var_export' is
00617         // unable to handle recursion properly.
00618         //if ( function_exists( 'var_export' ) )
00619         //    return var_export( $var, true );
00620 
00621         ob_start();
00622         var_dump( $var );
00623         $variableContents = '';
00624         if ( extension_loaded( 'xdebug' ) )
00625            $variableContents = self::XDEBUG_SIGNATURE;
00626         $variableContents .= ob_get_contents();
00627         ob_end_clean();
00628         return $variableContents;
00629     }
00630 
00631     /*!
00632      Enables/disables the use of external CSS. If false a <style> tag is output
00633      before the debug list. Default is to use internal css.
00634     */
00635     static function setUseExternalCSS( $use )
00636     {
00637         eZDebug::instance()->UseCSS = $use;
00638     }
00639 
00640     /*!
00641      Determines the way messages are output, the \a $output parameter
00642      is self::OUTPUT_MESSAGE_SCREEN and self::OUTPUT_MESSAGE_STORE ored together.
00643     */
00644     function setMessageOutput( $output )
00645     {
00646         $this->MessageOutput = $output;
00647     }
00648 
00649     /*!
00650     */
00651     function setStoreLog( $store )
00652     {
00653         $this->StoreLog = $store;
00654     }
00655 
00656     /*!
00657       Adds a new timing point for the benchmark report.
00658     */
00659     static function addTimingPoint( $description = "" )
00660     {
00661         if ( !eZDebug::isDebugEnabled() )
00662             return;
00663         if ( !eZDebug::showMessage( self::SHOW_TIMING_POINT ) )
00664             return;
00665         $debug = eZDebug::instance();
00666 
00667         $time = microtime( true );
00668         $usedMemory = 0;
00669         if ( function_exists( "memory_get_usage" ) )
00670             $usedMemory = memory_get_usage();
00671         $tp = array( "Time" => $time,
00672                      "Description" => $description,
00673                      "MemoryUsage" => $usedMemory );
00674         $debug->TimePoints[] = $tp;
00675         $desc = "Timing Point: $description";
00676         foreach ( array( self::LEVEL_NOTICE, self::LEVEL_WARNING, self::LEVEL_ERROR, self::LEVEL_DEBUG, self::LEVEL_STRICT ) as $lvl )
00677         {
00678             if ( isset( $debug->TmpTimePoints[$lvl] ) )
00679                 $debug->TmpTimePoints[$lvl] = array();
00680             if ( $debug->TmpTimePoints[$lvl] === false and
00681                  $debug->isLogFileEnabled( $lvl ) )
00682             {
00683                 $files = $debug->logFiles();
00684                 $file = $files[$lvl];
00685                 $debug->writeFile( $file, $desc, $lvl );
00686             }
00687             else
00688                 array_push( $debug->TmpTimePoints[$lvl],  $tp );
00689         }
00690         $debug->write( $description, self::LEVEL_TIMING_POINT );
00691     }
00692 
00693     /*!
00694       \private
00695       Writes a debug log message.
00696     */
00697     function write( $string, $verbosityLevel = self::LEVEL_NOTICE, $label = "", $backgroundClass = "", $alwaysLog = false )
00698     {
00699         $enabled = eZDebug::isDebugEnabled();
00700         if ( !$alwaysLog and !$enabled )
00701             return;
00702         switch ( $verbosityLevel )
00703         {
00704             case self::LEVEL_NOTICE:
00705             case self::LEVEL_WARNING:
00706             case self::LEVEL_ERROR:
00707             case self::LEVEL_DEBUG:
00708             case self::LEVEL_TIMING_POINT:
00709             case self::LEVEL_STRICT:
00710                 break;
00711 
00712             default:
00713                 $verbosityLevel = self::LEVEL_ERROR;
00714             break;
00715         }
00716         if ( $this->MessageOutput & self::OUTPUT_MESSAGE_SCREEN and $enabled )
00717         {
00718             print( "$verbosityLevel: $string ($label)\n" );
00719         }
00720         $files = $this->logFiles();
00721         $fileName = false;
00722         if ( isset( $files[$verbosityLevel] ) )
00723             $fileName = $files[$verbosityLevel];
00724         if ( $this->MessageOutput & self::OUTPUT_MESSAGE_STORE or $alwaysLog )
00725         {
00726             if ( ! eZDebug::isLogOnlyEnabled() and $enabled )
00727             {
00728                 $ip = eZSys::serverVariable( 'REMOTE_ADDR', true );
00729                 if ( !$ip )
00730                     $ip = eZSys::serverVariable( 'HOSTNAME', true );
00731                 $this->DebugStrings[] = array( "Level" => $verbosityLevel,
00732                                                "IP" => $ip,
00733                                                "Time" => time(),
00734                                                "Label" => $label,
00735                                                "String" => $string,
00736                                                "BackgroundClass" => $backgroundClass );
00737             }
00738 
00739             if ( $fileName !== false )
00740             {
00741                 $timePoints = $this->TmpTimePoints[$verbosityLevel];
00742                 if ( is_array( $timePoints ) )
00743                 {
00744                     if ( $this->isLogFileEnabled( $verbosityLevel ) )
00745                     {
00746                         foreach ( $timePoints as $tp )
00747                         {
00748                             $desc = "Timing Point: " . $tp["Description"];
00749                             if ( $this->isLogFileEnabled( $verbosityLevel ) )
00750                             {
00751                                 $this->writeFile( $fileName, $desc, $verbosityLevel, $alwaysLog );
00752                             }
00753                         }
00754                     }
00755                     $this->TmpTimePoints[$verbosityLevel] = false;
00756                 }
00757                 if ( $this->isLogFileEnabled( $verbosityLevel ) )
00758                 {
00759                     $string = "$label:\n$string";
00760                     $this->writeFile( $fileName, $string, $verbosityLevel, $alwaysLog );
00761                 }
00762             }
00763         }
00764     }
00765 
00766     /*!
00767      \static
00768      \return the maxium size for a log file in bytes.
00769     */
00770     static function maxLogSize()
00771     {
00772         if ( isset( $GLOBALS['eZDebugMaxLogSize'] ) )
00773         {
00774             return $GLOBALS['eZDebugMaxLogSize'];
00775         }
00776         return self::MAX_LOGFILE_SIZE;
00777     }
00778 
00779     /*!
00780      \static
00781      Sets the maxium size for a log file to \a $size.
00782     */
00783     static function setMaxLogSize( $size )
00784     {
00785         $GLOBALS['eZDebugMaxLogSize'] = $size;
00786     }
00787 
00788     /*!
00789      \static
00790      \return the maxium number of logrotate files to keep.
00791     */
00792     static function maxLogrotateFiles()
00793     {
00794         if ( isset( $GLOBALS['eZDebugMaxLogrotateFiles'] ) )
00795         {
00796             return $GLOBALS['eZDebugMaxLogrotateFiles'];
00797         }
00798         return self::MAX_LOGROTATE_FILES;
00799     }
00800 
00801     /*!
00802      \static
00803      Sets the maxium number of logrotate files to keep to \a $files.
00804     */
00805     static function setLogrotateFiles( $files )
00806     {
00807         $GLOBALS['eZDebugMaxLogrotateFiles'] = $files;
00808     }
00809 
00810     /*!
00811      \static
00812      Rotates logfiles so the current logfile is backed up,
00813      old rotate logfiles are rotated once more and those that
00814      exceed maxLogrotateFiles() will be removed.
00815      Rotated files will get the extension .1, .2 etc.
00816     */
00817     static function rotateLog( $fileName )
00818     {
00819         $maxLogrotateFiles = eZDebug::maxLogrotateFiles();
00820         for ( $i = $maxLogrotateFiles; $i > 0; --$i )
00821         {
00822             $logRotateName = $fileName . '.' . $i;
00823             if ( @file_exists( $logRotateName ) )
00824             {
00825                 if ( $i == $maxLogrotateFiles )
00826                 {
00827                     @unlink( $logRotateName );
00828 //                     print( "@unlink( $logRotateName )<br/>" );
00829                 }
00830                 else
00831                 {
00832                     $newLogRotateName = $fileName . '.' . ($i + 1);
00833                     //include_once( 'lib/ezfile/classes/ezfile.php' );
00834                     eZFile::rename( $logRotateName, $newLogRotateName );
00835 //                     print( "@rename( $logRotateName, $newLogRotateName )<br/>" );
00836                 }
00837             }
00838         }
00839         if ( @file_exists( $fileName ) )
00840         {
00841             $newLogRotateName = $fileName . '.' . 1;
00842             //include_once( 'lib/ezfile/classes/ezfile.php' );
00843             eZFile::rename( $fileName, $newLogRotateName );
00844 //             print( "@rename( $fileName, $newLogRotateName )<br/>" );
00845             return true;
00846         }
00847         return false;
00848     }
00849 
00850     /*!
00851      \private
00852      Writes the log message $string to the file $fileName.
00853     */
00854     function writeFile( &$logFileData, &$string, $verbosityLevel, $alwaysLog = false )
00855     {
00856         $enabled = eZDebug::isDebugEnabled();
00857         if ( !$alwaysLog and !$enabled )
00858             return;
00859         if ( !$alwaysLog and !$this->isLogFileEnabled( $verbosityLevel ) )
00860             return;
00861         $oldHandleType = eZDebug::setHandleType( self::HANDLE_TO_PHP );
00862         $logDir = $logFileData[0];
00863         $logName = $logFileData[1];
00864         $fileName = $logDir . $logName;
00865         if ( !file_exists( $logDir ) )
00866         {
00867             //include_once( 'lib/ezfile/classes/ezdir.php' );
00868             eZDir::mkdir( $logDir, false, true );
00869         }
00870         $oldumask = @umask( 0 );
00871         $fileExisted = @file_exists( $fileName );
00872         if ( $fileExisted and
00873              filesize( $fileName ) > eZDebug::maxLogSize() )
00874         {
00875             if ( eZDebug::rotateLog( $fileName ) )
00876                 $fileExisted = false;
00877         }
00878         $logFile = @fopen( $fileName, "a" );
00879         if ( $logFile )
00880         {
00881             $time = strftime( "%b %d %Y %H:%M:%S", strtotime( "now" ) );
00882             $ip = eZSys::serverVariable( 'REMOTE_ADDR', true );
00883             if ( !$ip )
00884                 $ip = eZSys::serverVariable( 'HOSTNAME', true );
00885             $notice = "[ " . $time . " ] [" . $ip . "] " . $string . "\n";
00886             @fwrite( $logFile, $notice );
00887             @fclose( $logFile );
00888             if ( !$fileExisted )
00889             {
00890                 $ini = eZINI::instance();
00891                 $permissions = octdec( $ini->variable( 'FileSettings', 'LogFilePermissions' ) );
00892                 @chmod( $fileName, $permissions );
00893             }
00894             @umask( $oldumask );
00895         }
00896         else
00897         {
00898             @umask( $oldumask );
00899             $logEnabled = $this->isLogFileEnabled( $verbosityLevel );
00900             $this->setLogFileEnabled( false, $verbosityLevel );
00901             if ( $verbosityLevel != self::LEVEL_ERROR or
00902                  $logEnabled )
00903             {
00904                 eZDebug::setHandleType( $oldHandleType );
00905                 $this->writeError( "Cannot open log file '$fileName' for writing\n" .
00906                                    "The web server must be allowed to modify the file.\n" .
00907                                    "File logging for '$fileName' is disabled." , 'eZDebug::writeFile' );
00908             }
00909         }
00910         eZDebug::setHandleType( $oldHandleType );
00911     }
00912 
00913     /*!
00914      \static
00915      Enables or disables logging to file for a given message type.
00916      If \a $types is not supplied it will do the operation for all types.
00917     */
00918     static function setLogFileEnabled( $enabled, $types = false )
00919     {
00920         $instance = eZDebug::instance();
00921         if ( $types === false )
00922         {
00923             $types = $instance->messageTypes();
00924         }
00925         if ( !is_array( $types ) )
00926         {
00927             $types = array( $types );
00928         }
00929         foreach ( $types as $type )
00930         {
00931             $instance->LogFileEnabled[$type] = $enabled;
00932         }
00933     }
00934 
00935     /*!
00936      \return true if the message type \a $type has logging to file enabled.
00937      \sa isGlobalLogFileEnabled, setIsLogFileEnabled
00938     */
00939     function isLogFileEnabled( $type )
00940     {
00941         if ( !$this->isGlobalLogFileEnabled() )
00942             return false;
00943         return $this->LogFileEnabled[$type];
00944     }
00945 
00946     /*!
00947      \return true if the message type \a $type has logging to file enabled.
00948      \sa isLogFileEnabled, setIsGlobalLogFileEnabled
00949     */
00950     function isGlobalLogFileEnabled()
00951     {
00952         return $this->GlobalLogFileEnabled;
00953     }
00954 
00955     /*!
00956      Sets whether the logfile \a $type is enabled or disabled to \a $enabled.
00957      \sa isLogFileEnabled
00958     */
00959     function setIsLogFileEnabled( $type, $enabled )
00960     {
00961         $this->LogFileEnabled[$type] = $enabled;
00962     }
00963 
00964     /*!
00965      Sets whether logfiles are enabled or disabled globally. Sets the value to \a $enabled.
00966      \sa isLogFileEnabled, isGlobalLogFileEnabled
00967     */
00968     function setIsGlobalLogFileEnabled( $enabled )
00969     {
00970         $this->GlobalLogFileEnabled = $enabled;
00971     }
00972 
00973     /*!
00974      Sets whether debug output should be logged only
00975     */
00976     function setLogOnly( $enabled )
00977     {
00978         $GLOBALS['eZDebugLogOnly'] = $enabled;
00979     }
00980 
00981     /*!
00982      \return an array with the available message types.
00983     */
00984     function messageTypes()
00985     {
00986         return $this->MessageTypes;
00987     }
00988 
00989     /*!
00990      Returns an associative array of all the log files used by this class
00991      where each key is the debug level (self::LEVEL_NOTICE, self::LEVEL_WARNING or self::LEVEL_ERROR or self::LEVEL_DEBUG).
00992     */
00993     function logFiles()
00994     {
00995         return $this->LogFiles;
00996     }
00997 
00998     /*!
00999      \static
01000      \return true if debug should be enabled.
01001      \note Will return false until the real settings has been updated with updateSettings()
01002     */
01003     static function isDebugEnabled()
01004     {
01005         if ( isset( $GLOBALS['eZDebugEnabled'] ) )
01006         {
01007             return $GLOBALS['eZDebugEnabled'];
01008         }
01009 
01010         return false;
01011     }
01012 
01013     /*!
01014      \static
01015      \return true if there should only be logging of debug strings to file.
01016      \note Will return false until the real settings has been updated with updateSettings()
01017     */
01018     static function isLogOnlyEnabled()
01019     {
01020         if ( isset( $GLOBALS['eZDebugLogOnly'] ) )
01021         {
01022             return $GLOBALS['eZDebugLogOnly'];
01023         }
01024 
01025         return false;
01026     }
01027 
01028     /*!
01029      \static
01030      Determine if an ipaddress is in a network. E.G. 120.120.120.120 in 120.120.0.0/24.
01031      \return true or false.
01032     */
01033     static function isIPInNet( $ipaddress, $network, $mask = 24 )
01034     {
01035         $lnet = ip2long( $network );
01036         $lip = ip2long( $ipaddress );
01037         $binnet = str_pad( decbin( $lnet ), 32, "0", "STR_PAD_LEFT" );
01038         $firstpart = substr($binnet,0,$mask);
01039         $binip = str_pad( decbin( $lip ), 32, "0", "STR_PAD_LEFT" );
01040         $firstip = substr( $binip, 0, $mask );
01041         return( strcmp( $firstpart, $firstip ) == 0 );
01042     }
01043 
01044     /*!
01045      \static
01046      Updates the settings for debug handling with the settings array \a $settings.
01047      The array must contain the following keys.
01048      - debug-enabled - boolean which controls debug handling
01049      - debug-by-ip   - boolean which controls IP controlled debugging
01050      - debug-ip-list - array of IPs which gets debug
01051      - debug-by-user - boolean which controls userID controlled debugging
01052      - debug-user-list - array of UserIDs which gets debug
01053     */
01054     static function updateSettings( $settings )
01055     {
01056         // Make sure errors are handled by PHP when we read, including our own debug output.
01057         $oldHandleType = eZDebug::setHandleType( self::HANDLE_TO_PHP );
01058 
01059         if ( isset( $settings['debug-log-files-enabled'] ) )
01060         {
01061             $GLOBALS['eZDebugLogFileEnabled'] = $settings['debug-log-files-enabled'];
01062             if ( isset( $GLOBALS["eZDebugGlobalInstance"] ) )
01063                 $GLOBALS["eZDebugGlobalInstance"]->GlobalLogFileEnabled = $settings['debug-log-files-enabled'];
01064         }
01065 
01066         if ( isset( $settings['debug-styles'] ) )
01067         {
01068             $GLOBALS['eZDebugStyles'] = $settings['debug-styles'];
01069         }
01070 
01071         if ( isset( $settings['always-log'] ) and
01072              is_array( $settings['always-log'] ) )
01073         {
01074             $GLOBALS['eZDebugAlwaysLog'] = $settings['always-log'];
01075         }
01076 
01077         if ( isset( $settings['log-only'] ) )
01078         {
01079             $GLOBALS['eZDebugLogOnly'] = ( $settings['log-only'] == 'enabled' );
01080         }
01081 
01082         $GLOBALS['eZDebugAllowedByIP'] = $settings['debug-by-ip'] ? self::isAllowedByCurrentIP( $settings['debug-ip-list'] ) : true;
01083 
01084         // updateSettings is meant to be called before the user session is started
01085         // so we do not take debug-by-user into account yet, but store the debug-user-list in $GLOBALS
01086         // so it can be used in the final check, done by checkDebugByUser()
01087         if ( isset( $settings['debug-by-user'] ) && $settings['debug-by-user'] )
01088         {
01089             $GLOBALS['eZDebugUserIDList'] = $settings['debug-user-list'] ? $settings['debug-user-list'] : array();
01090         }
01091 
01092         $GLOBALS['eZDebugAllowed'] = $GLOBALS['eZDebugAllowedByIP'];
01093         $GLOBALS['eZDebugEnabled'] = $settings['debug-enabled'] && $GLOBALS['eZDebugAllowedByIP'];
01094 
01095         eZDebug::setHandleType( $oldHandleType );
01096     }
01097 
01098     /*!
01099       \static
01100       Final checking for debug by user id.
01101       Checks if we should enable debug.
01102 
01103       Returns false if debug-by-user is not active, was already checked before
01104       or if there is no current user. Returns true otherwise.
01105     */
01106     static function checkDebugByUser()
01107     {
01108         if ( !isset( $GLOBALS['eZDebugUserIDList'] ) ||
01109              !is_array( $GLOBALS['eZDebugUserIDList'] ) )
01110         {
01111             return false;
01112         }
01113         else
01114         {
01115             $currentUserID = eZUser::currentUserID();
01116 
01117             if ( !$currentUserID )
01118             {
01119                 return false;
01120             }
01121             else
01122             {
01123                 $GLOBALS['eZDebugAllowedByUser'] = in_array( $currentUserID, $GLOBALS['eZDebugUserIDList'] );
01124 
01125                 if ( $GLOBALS['eZDebugAllowed'] )
01126                 {
01127                     $GLOBALS['eZDebugAllowed'] = $GLOBALS['eZDebugAllowedByUser'];
01128                 }
01129 
01130                 if ( $GLOBALS['eZDebugEnabled'] )
01131                 {
01132                     $GLOBALS['eZDebugEnabled'] = $GLOBALS['eZDebugAllowedByUser'];
01133                 }
01134 
01135                 unset( $GLOBALS['eZDebugUserIDList'] );
01136 
01137                 return true;
01138             }
01139         }
01140     }
01141 
01142     /*!
01143       \static
01144       Prints the debug report
01145     */
01146     static function printReport( $newWindow = false, $as_html = true, $returnReport = false,
01147                            $allowedDebugLevels = false, $useAccumulators = true, $useTiming = true, $useIncludedFiles = false )
01148     {
01149         if ( !eZDebug::isDebugEnabled() )
01150             return null;
01151 
01152         $debug = eZDebug::instance();
01153         $report = $debug->printReportInternal( $as_html, $returnReport & $newWindow, $allowedDebugLevels, $useAccumulators, $useTiming, $useIncludedFiles );
01154 
01155         if ( $newWindow == true )
01156         {
01157             $debugFilePath = eZDir::path( array( eZSys::varDirectory(), 'cache', 'debug.html' ) );
01158             $debugFileURL = $debugFilePath;
01159             eZURI::transformURI( $debugFileURL, true );
01160             print( "
01161 <SCRIPT LANGUAGE='JavaScript'>
01162 <!-- hide this script from old browsers
01163 
01164 function showDebug()
01165 {
01166     var debugWindow;
01167 
01168     if  (navigator.appName == \"Microsoft Internet Explorer\")
01169     {
01170         //Microsoft Internet Explorer
01171         debugWindow = window.open( '$debugFileURL', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40');
01172         debugWindow.document.close();
01173         debugWindow.location.reload();
01174     }
01175     else if (navigator.appName == \"Opera\")
01176     {
01177         //Opera
01178         debugWindow = window.open( '', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40');
01179         debugWindow.location.href=\"$debugFileURL\";
01180         debugWindow.navigate(\"$debugFileURL\");
01181     }
01182     else
01183     {
01184         //Mozilla, Firefox, etc.
01185         debugWindow = window.open( '', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40');
01186         debugWindow.document.location.href=\"$debugFileURL\";
01187     };
01188 }
01189 
01190 showDebug();
01191 
01192 // done hiding from old browsers -->
01193 </SCRIPT>
01194 " );
01195             $header = "<html><head><title>eZ debug</title></head><body>";
01196             $footer = "</body></html>";
01197             $fp = fopen( $debugFilePath, "w+" );
01198 
01199             fwrite( $fp, $header );
01200             fwrite( $fp, $report );
01201             fwrite( $fp, $footer );
01202             fclose( $fp );
01203         }
01204         else
01205         {
01206             if ( $returnReport )
01207                 return $report;
01208         }
01209         return null;
01210     }
01211 
01212     /*!
01213       \private
01214      Returns the microtime as a float value. $mtime must be in microtime() format.
01215     */
01216     static function timeToFloat( $mtime )
01217     {
01218         $tTime = explode( " ", $mtime );
01219         ereg( "0\.([0-9]+)", "" . $tTime[0], $t1 );
01220         $time = $tTime[1] . "." . $t1[1];
01221         return $time;
01222     }
01223 
01224     /*!
01225      Sets the time of the start of the script ot \a $time.
01226      If \a $time is not supplied it gets the current \c microtime( true ).
01227      This is used to calculate total execution time and percentages.
01228     */
01229     static function setScriptStart( $time = false )
01230     {
01231         if ( $time == false )
01232             $time = microtime( true );
01233         $debug = eZDebug::instance();
01234         $debug->ScriptStart = $time;
01235     }
01236 
01237     /*!
01238       Creates an accumulator group with key \a $key and group name \a $name.
01239       If \a $name is not supplied name is taken from \a $key.
01240     */
01241     static function createAccumulatorGroup( $key, $name = false )
01242     {
01243         if ( !eZDebug::isDebugEnabled() )
01244             return;
01245         if ( $name == '' or
01246              $name === false )
01247             $name = $key;
01248         $debug = eZDebug::instance();
01249         if ( !array_key_exists( $key, $debug->TimeAccumulatorList ) )
01250             $debug->TimeAccumulatorList[$key] = array( 'name' => $name,  'time' => 0, 'count' => 0, 'is_group' => true, 'in_group' => false );
01251         if ( !array_key_exists( $key, $debug->TimeAccumulatorGroupList ) )
01252             $debug->TimeAccumulatorGroupList[$key] = array();
01253     }
01254 
01255     /*!
01256      Creates a new accumulator entry if one does not already exist and initializes with default data.
01257      If \a $name is not supplied name is taken from \a $key.
01258      If \a $inGroup is supplied it will place the accumulator under the specified group.
01259     */
01260     static function createAccumulator( $key, $inGroup = false, $name = false )
01261     {
01262         if ( !eZDebug::isDebugEnabled() )
01263             return;
01264         if ( $name == '' or
01265              $name === false )
01266             $name = $key;
01267         $debug = eZDebug::instance();
01268         $isGroup = false;
01269         if ( array_key_exists( $key, $debug->TimeAccumulatorList ) and
01270              array_key_exists( $key, $debug->TimeAccumulatorGroupList ) )
01271             $isGroup = true;
01272         $debug->TimeAccumulatorList[$key] = array( 'name' => $name,  'time' => 0, 'count' => 0, 'is_group' => $isGroup, 'in_group' => $inGroup );
01273         if ( $inGroup !== false )
01274         {
01275             $groupKeys = array();
01276             if ( array_key_exists( $inGroup, $debug->TimeAccumulatorGroupList ) )
01277                 $groupKeys = $debug->TimeAccumulatorGroupList[$inGroup];
01278             $debug->TimeAccumulatorGroupList[$inGroup] = array_unique( array_merge( $groupKeys, array( $key ) ) );
01279             if ( array_key_exists( $inGroup, $debug->TimeAccumulatorList ) )
01280                 $debug->TimeAccumulatorList[$inGroup]['is_group'] = true;
01281         }
01282     }
01283 
01284     /*!
01285      Starts an time count for the accumulator \a $key.
01286      You can also specify a name which will be displayed.
01287     */
01288     static function accumulatorStart( $key, $inGroup = false, $name = false, $recursive = false )
01289     {
01290         if ( !eZDebug::isDebugEnabled() )
01291             return;
01292         $debug = eZDebug::instance();
01293         $key = $key === false ? 'Default Debug-Accumulator' : $key;
01294         if ( ! array_key_exists( $key, $debug->TimeAccumulatorList ) )
01295         {
01296             $debug->createAccumulator( $key, $inGroup, $name );
01297         }
01298 
01299         if ( $recursive )
01300         {
01301             if ( isset( $debug->TimeAccumulatorList[$key]['recursive_counter'] ) )
01302             {
01303                 $debug->TimeAccumulatorList[$key]['recursive_counter']++;
01304                 return;
01305             }
01306             $debug->TimeAccumulatorList[$key]['recursive_counter'] = 0;
01307         }
01308 
01309         $debug->TimeAccumulatorList[$key]['temp_time'] = microtime( true );
01310     }
01311 
01312     /*!
01313      Stops a previous time count and adds the total time to the accumulator \a $key.
01314     */
01315     static function accumulatorStop( $key, $recursive = false )
01316     {
01317         if ( !eZDebug::isDebugEnabled() )
01318             return;
01319         $debug = eZDebug::instance();
01320         $stopTime = microtime( true );
01321         $key = $key === false ? 'Default Debug-Accumulator' : $key;
01322         if ( ! array_key_exists( $key, $debug->TimeAccumulatorList ) )
01323         {
01324             eZDebug::writeWarning( "Accumulator '$key' does not exist, run eZDebug::accumulatorStart first", 'eZDebug::accumulatorStop' );
01325             return;
01326         }
01327         $accumulator = $debug->TimeAccumulatorList[$key];
01328         if ( $recursive )
01329         {
01330             if ( isset( $accumulator['recursive_counter'] ) )
01331             {
01332                 if ( $accumulator['recursive_counter'] > 0 )
01333                 {
01334                     $accumulator['recursive_counter']--;
01335                     return;
01336                 }
01337             }
01338         }
01339         $diffTime = $stopTime - $accumulator['temp_time'];
01340         $accumulator['time'] = $accumulator['time'] + $diffTime;
01341         ++$accumulator['count'];
01342         $debug->TimeAccumulatorList[$key] = $accumulator;
01343     }
01344 
01345 
01346     /*!
01347       \private
01348       Prints a full debug report with notice, warnings, errors and a timing report.
01349     */
01350     function printReportInternal( $as_html = true, $returnReport = true, $allowedDebugLevels = false,
01351                                   $useAccumulators = true, $useTiming = true, $useIncludedFiles = false )
01352     {
01353         $styles = array( 'strict' => false,
01354                          'strict-end' => false,
01355                          'warning' => false,
01356                          'warning-end' => false,
01357                          'error' => false,
01358                          'error-end' => false,
01359                          'debug' => false,
01360                          'debug-end' => false,
01361                          'notice' => false,
01362                          'notice-end' => false,
01363                          'timing' => false,
01364                          'timing-end' => false,
01365                          'mark' => false,
01366                          'mark-end' => false,
01367                          'emphasize' => false,
01368                          'emphasize-end' => false,
01369                          'bold' => false,
01370                          'bold-end' => false );
01371         if ( isset( $GLOBALS['eZDebugStyles'] ) )
01372             $styles = $GLOBALS['eZDebugStyles'];
01373         if ( !$allowedDebugLevels )
01374             $allowedDebugLevels = array( self::LEVEL_NOTICE, self::LEVEL_WARNING, self::LEVEL_ERROR,
01375                                          self::LEVEL_DEBUG, self::LEVEL_TIMING_POINT, self::LEVEL_STRICT );
01376         $endTime = microtime( true );
01377 
01378         if ( $returnReport )
01379         {
01380             ob_start();
01381         }
01382 
01383         if ( $as_html )
01384         {
01385             echo "<div id=\"debug\"><table style='border: 1px dashed black; background-color: #fefefe;' summary='Layout table for eZ Publish debug output'>";
01386             echo "<tr><th><h1>eZ debug</h1></th></tr>";
01387 
01388             echo "<tr><td>";
01389 
01390             if ( !$this->UseCSS )
01391             {
01392                 echo "<STYLE TYPE='text/css'>
01393                 <!--
01394 td.debugheader
01395 {
01396     background-color : #eeeeee;
01397     border-top : 1px solid #444488;
01398     border-bottom : 1px solid #444488;
01399     font-size : 65%;
01400     font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
01401 }
01402 
01403 pre.debugtransaction
01404 {
01405     background-color : #f8f6d8;
01406 }
01407 
01408 td.timingpoint1
01409 {
01410     background-color : #ffffff;
01411     border-top : 1px solid #444488;
01412     font-size : 65%;
01413     font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
01414 }
01415 
01416 td.timingpoint2
01417 {
01418     background-color : #eeeeee;
01419     border-top : 1px solid #444488;
01420     font-size : 65%;
01421     font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
01422 }
01423 
01424 -->
01425 </STYLE>";
01426             }
01427             echo "<table style='border: 1px lightgray;' cellspacing='0' summary='Table for actual debug output, shows notices, warnings and errors.'>";
01428         }
01429 
01430         $this->printTopReportsList();
01431 
01432         $hasLevel = array( self::LEVEL_NOTICE => false,
01433                            self::LEVEL_WARNING => false,
01434                            self::LEVEL_ERROR => false,
01435                            self::LEVEL_TIMING_POINT => false,
01436                            self::LEVEL_DEBUG => false,
01437                            self::LEVEL_STRICT => false );
01438 
01439         foreach ( $this->DebugStrings as $debug )
01440         {
01441             if ( !in_array( $debug['Level'], $allowedDebugLevels ) )
01442                 continue;
01443             $time = strftime ("%b %d %Y %H:%M:%S", strtotime( "now" ) );
01444 
01445             $outputData = $this->OutputFormat[$debug["Level"]];
01446             if ( is_array( $outputData ) )
01447             {
01448                 $identifierText = '';
01449                 if ( !$hasLevel[$debug['Level']] )
01450                 {
01451                     $hasLevel[$debug['Level']] = true;
01452                     $identifierText = ' id="' . $outputData['xhtml-identifier'] . '"';
01453                 }
01454                 $color = $outputData["color"];
01455                 $name = $outputData["name"];
01456                 $label = $debug["Label"];
01457                 $bgclass = $debug["BackgroundClass"];
01458                 $pre = ($bgclass != '' ? " class='$bgclass'" : '');
01459                 if ( $as_html )
01460                 {
01461                     $label = htmlspecialchars( $label );
01462 
01463                     $contents = '';
01464                     if ( extension_loaded( 'xdebug' ) && ( strncmp( self::XDEBUG_SIGNATURE, $debug['String'], strlen( self::XDEBUG_SIGNATURE ) ) === 0 ) )
01465                         $contents = substr( $debug['String'], strlen( self::XDEBUG_SIGNATURE ) );
01466                     else
01467                         $contents = htmlspecialchars( $debug['String'] );
01468 
01469                     echo "<tr><td class='debugheader' valign='top'$identifierText><b><span style='color: $color'>$name:</span> $label</b></td>
01470                                     <td class='debugheader' valign='top'>$time</td></tr>
01471                                     <tr><td colspan='2'><pre$pre>" .  $contents . "</pre></td></tr>";
01472                 }
01473                 else
01474                 {
01475                     echo $styles[$outputData['style']] . "$name:" . $styles[$outputData['style'].'-end'] . " ";
01476                     echo $styles['bold'] . "($label)" . $styles['bold-end'] . "\n" . $debug["String"] . "\n\n";
01477                 }
01478             }
01479             flush();
01480         }
01481         if ( $as_html )
01482         {
01483             echo "</table>";
01484 
01485             echo "<h2>Timing points:</h2>";
01486             echo "<table id='timingpoints' style='border: 1px dashed black;' cellspacing='0' summary='Tabel of timingpoint stats.'><tr><th>Checkpoint</th><th>Elapsed</th><th>Rel. Elapsed</th><th>Memory</th><th>Rel. Memory</th></tr>";
01487         }
01488         $startTime = false;
01489         $elapsed = 0.00;
01490         $relElapsed = 0.00;
01491         if ( $useTiming )
01492         {
01493             for ( $i = 0; $i < count( $this->TimePoints ); ++$i )
01494             {
01495                 $point = $this->TimePoints[$i];
01496                 $nextPoint = false;
01497                 if ( isset( $this->TimePoints[$i + 1] ) )
01498                     $nextPoint = $this->TimePoints[$i + 1];
01499                 $time = $point["Time"];
01500                 $nextTime = false;
01501                 if ( $startTime === false )
01502                     $startTime = $time;
01503                 $elapsed = $time - $startTime;
01504 
01505                 $relMemory = 0;
01506                 $memory = $point["MemoryUsage"];
01507                 // Calculate relative time and memory usage
01508                 if ( $nextPoint !== false )
01509                 {
01510                     $nextTime = $nextPoint["Time"];
01511                     $relElapsed = $nextTime - $time;
01512                     $relElapsed = number_format( $relElapsed, $this->TimingAccuracy ) . " sec";
01513 
01514                     $nextMemory = $nextPoint["MemoryUsage"];
01515                     $relMemory = $nextMemory - $memory;
01516                     $relMemory = number_format( $relMemory / 1024, $this->TimingAccuracy ) . " KB";
01517                 }
01518                 else
01519                 {
01520                     $relElapsed = $as_html ? '&nbsp;' : '';
01521                     $relMemory = $as_html ? '&nbsp;' : '';
01522                 }
01523 
01524                 // Convert memory usage to human readable
01525                 $memory = number_format( $memory / 1024, $this->TimingAccuracy ) . " KB";
01526                 $elapsed = number_format( $elapsed, $this->TimingAccuracy ) . " sec";
01527 
01528                 if ( $i % 2 == 0 )
01529                     $class = "timingpoint1";
01530                 else
01531                     $class = "timingpoint2";
01532 
01533                 if ( $as_html )
01534                 {
01535                     echo "<tr><td class='$class'>" . $point["Description"] . "</td>
01536                           <td class='$class' align='right'>$elapsed</td><td class='$class' align='right'>$relElapsed</td>
01537                           <td class='$class' align='right'>$memory</td><td class='$class' align='right'>$relMemory</td></tr>";
01538                 }
01539                 else
01540                 {
01541                     echo $point["Description"] . ' ' . $elapsed . $relElapsed . "\n";
01542                 }
01543             }
01544 
01545             if ( count( $this->TimePoints ) > 0 )
01546             {
01547                 $totalElapsed = $endTime - $startTime;
01548 
01549                 if ( $as_html )
01550                 {
01551                     echo "<tr><td><b>Total runtime:</b></td><td><b>" .
01552     number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec</b></td><td></td></tr>";
01553                 }
01554                 else
01555                 {
01556                     echo "Total runtime: " .
01557     number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec\n";
01558                 }
01559             }
01560             else
01561             {
01562                 if ( $as_html )
01563                     echo "<tr><td> No timing points defined</td><td>";
01564                 else
01565                     echo "No timing points defined\n";
01566             }
01567 
01568             if ( function_exists( 'memory_get_peak_usage' ) )
01569             {
01570                 $peakMemory = memory_get_peak_usage();
01571                 if ( $as_html )
01572                 {
01573                     echo "<tr><td><b>Peak memory usage:</b></td><td><b>" .
01574                         number_format( $peakMemory / 1024, $this->TimingAccuracy ) . " KB</b></td></tr>";
01575                 }
01576                 else
01577                 {
01578                     echo "Peak memory usage: " .
01579                         number_format( $peakMemory / 1024, $this->TimingAccuracy ) . " KB\n";
01580                 }
01581             }
01582         }
01583         if ( $as_html )
01584         {
01585             echo "</table>";
01586         }
01587 
01588         if ( $useIncludedFiles )
01589         {
01590             if ( $as_html )
01591                 echo "<h2>Included files:</h2><table style='border: 1px dashed black;' cellspacing='0' summary='Tabel list of included templates used in the processing of this page.'><tr><th>File</th></tr>";
01592             else
01593                 echo $styles['emphasize'] . "Includes" . $styles['emphasize-end'] . "\n";
01594             $phpFiles = get_included_files();
01595             $j = 0;
01596             $currentPathReg = preg_quote( realpath( "." ) );
01597             foreach ( $phpFiles as $phpFile )
01598             {
01599                 if ( preg_match( "#^$currentPathReg/(.+)$#", $phpFile, $matches ) )
01600                     $phpFile = $matches[1];
01601                 if ( $as_html )
01602                 {
01603                     if ( $j % 2 == 0 )
01604                         $class = "timingpoint1";
01605                     else
01606                         $class = "timingpoint2";
01607                     ++$j;
01608                     echo "<tr><td class=\"$class\">$phpFile</td></tr>";
01609                 }
01610                 else
01611                 {
01612                     echo "$phpFile\n";
01613                 }
01614             }
01615             if ( $as_html )
01616                 echo "</table>";
01617         }
01618 
01619         if ( $as_html )
01620         {
01621             echo "<h2>Time accumulators:</h2>";
01622             echo "<table id='timeaccumulators' style='border: 1px dashed black;' cellspacing='0' summary='Table with detailed list of time accumulators'><tr><th>&nbsp;Accumulator</th><th>&nbsp;Elapsed</th><th>&nbsp;Percent</th><th>&nbsp;Count</th><th>&nbsp;Average</th></tr>";
01623             $i = 0;
01624         }
01625 
01626         $scriptEndTime = microtime( true );
01627         $totalElapsed = $scriptEndTime - $this->ScriptStart;
01628         $timeList = $this->TimeAccumulatorList;
01629         $groups = $this->TimeAccumulatorGroupList;
01630         $groupList = array();
01631         foreach ( $groups as $groupKey => $keyList )
01632         {
01633             if ( count( $keyList ) == 0 and
01634                  !array_key_exists( $groupKey, $timeList ) )
01635                 continue;
01636             $groupList[$groupKey] = array( 'name' => $groupKey );
01637             if ( array_key_exists( $groupKey, $timeList ) )
01638             {
01639                 if ( $timeList[$groupKey]['time'] != 0 )
01640                     $groupList[$groupKey]['time_data'] = $timeList[$groupKey];
01641                 $groupList[$groupKey]['name'] = $timeList[$groupKey]['name'];
01642                 unset( $timeList[$groupKey] );
01643             }
01644             $groupChildren = array();
01645             foreach ( $keyList as $timeKey )
01646             {
01647                 if ( array_key_exists( $timeKey, $timeList ) )
01648                 {
01649                     $groupChildren[] = $timeList[$timeKey];
01650                     unset( $timeList[$timeKey] );
01651                 }
01652             }
01653             $groupList[$groupKey]['children'] = $groupChildren;
01654         }
01655         if ( count( $timeList ) > 0 )
01656         {
01657             $groupList['general'] = array( 'name' => 'General',
01658                                            'children' => $timeList );
01659         }
01660 
01661         if ( $useAccumulators )
01662         {
01663             $j = 0;
01664             foreach ( $groupList as $group )
01665             {
01666                 if ( $j % 2 == 0 )
01667                     $class = "timingpoint1";
01668                 else
01669                     $class = "timingpoint2";
01670                 ++$j;
01671                 $groupName = $group['name'];
01672                 $groupChildren = $group['children'];
01673                 if ( count( $groupChildren ) == 0 and
01674                      !array_key_exists( 'time_data', $group ) )
01675                     continue;
01676                 if ( $as_html )
01677                     echo "<tr><td class='$class'><b>$groupName</b></td>";
01678                 else
01679                     echo "Group " . $styles['mark'] . "$groupName:" . $styles['mark-end'] . " ";
01680                 if ( array_key_exists( 'time_data', $group ) )
01681                 {
01682                     $groupData = $group['time_data'];
01683                     $groupElapsed = number_format( ( $groupData['time'] ), $this->TimingAccuracy );
01684                     $groupPercent = number_format( ( $groupData['time'] * 100.0 ) / $totalElapsed, 1 );
01685                     $groupCount = $groupData['count'];
01686                     $groupAverage = number_format( ( $groupData['time'] / $groupData['count'] ), $this->TimingAccuracy );
01687                     if ( $as_html )
01688                     {
01689                         echo ( "<td class=\"$class\">$groupElapsed sec</td>".
01690                                          "<td class=\"$class\" align=\"right\"> $groupPercent%</td>".
01691                                          "<td class=\"$class\" align=\"right\"> $groupCount</td>".
01692                                          "<td class=\"$class\" align=\"right\"> $groupAverage sec</td>" );
01693                     }
01694                     else
01695                     {
01696                         echo $styles['emphasize'] . "$groupElapsed" . $styles['emphasize-end'] . " sec ($groupPercent%), $groupAverage avg sec ($groupCount)";
01697                     }
01698                 }
01699                 else if ( $as_html )
01700                 {
01701                     echo ( "<td class=\"$class\"></td>".
01702                                      "<td class=\"$class\"></td>".
01703                                      "<td class=\"$class\"></td>".
01704                                      "<td class=\"$class\"></td>" );
01705                 }
01706                 if ( $as_html )
01707                     echo "</tr>";
01708                 else
01709                     echo "\n";
01710 
01711                 $i = 0;
01712                 foreach ( $groupChildren as $child )
01713                 {
01714                     $childName = $child['name'];
01715                     $childElapsed = number_format( ( $child['time'] ), $this->TimingAccuracy );
01716                     $childPercent = number_format( ( $child['time'] * 100.0 ) / $totalElapsed, $this->PercentAccuracy );
01717                     $childCount = $child['count'];
01718                     $childAverage = 0.0;
01719                     if ( $childCount > 0 )
01720                     {
01721                         $childAverage = $child['time'] / $childCount;
01722                     }
01723                     $childAverage = number_format( $childAverage, $this->PercentAccuracy );
01724 
01725                     if ( $as_html )
01726                     {
01727                         if ( $i % 2 == 0 )
01728                             $class = "timingpoint1";
01729                         else
01730                             $class = "timingpoint2";
01731                         ++$i;
01732 
01733                         echo ( "<tr>" .
01734                                          "<td class=\"$class\">$childName</td>" .
01735                                          "<td class=\"$class\">$childElapsed sec</td>" .
01736                                          "<td class=\"$class\" align=\"right\">$childPercent%</td>" .
01737                                          "<td class=\"$class\" align=\"right\">$childCount</td>" .
01738                                          "<td class=\"$class\" align=\"right\">$childAverage sec</td>" .
01739                                          "</tr>" );
01740                     }
01741                     else
01742                     {
01743                         echo "$childName: " . $styles['emphasize'] . $childElapsed . $styles['emphasize-end'] . " sec ($childPercent%), $childAverage avg sec ($childCount)\n";
01744                     }
01745                 }
01746             }
01747         }
01748         if ( $as_html )
01749         {
01750             echo "<tr><td><b>Total script time:</b></td><td><b>" . number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec</b></td><td></td></tr>";
01751         }
01752         else
01753         {
01754             echo "\nTotal script time: " . $styles['emphasize'] . number_format( ( $totalElapsed ), $this->TimingAccuracy ) . $styles['emphasize-end'] . " sec\n";
01755         }
01756 
01757         if ( $as_html )
01758         {
01759             echo "</table>";
01760         }
01761 
01762         $this->printBottomReportsList();
01763 
01764         if ( $as_html )
01765         {
01766             echo "</td></tr></table></div>";
01767         }
01768 
01769         if ( $returnReport )
01770         {
01771             $returnText = ob_get_contents();
01772             ob_end_clean();
01773             return $returnText;
01774         }
01775         else
01776         {
01777             return NULL;
01778         }
01779     }
01780 
01781     /*!
01782      Appends report to 'top' reports list.
01783     */
01784     static function appendTopReport( $reportName, $reportContent )
01785     {
01786         $debug = eZDebug::instance();
01787         $debug->topReportsList[$reportName] = $reportContent;
01788     }
01789 
01790     /*!
01791      Prints all 'top' reports
01792     */
01793     static function printTopReportsList()
01794     {
01795         $debug = eZDebug::instance();
01796         $reportNames = array_keys( $debug->topReportsList );
01797         foreach ( $reportNames as $reportName )
01798         {
01799             echo $debug->topReportsList[$reportName];
01800         }
01801     }
01802 
01803     /*!
01804      Appends report to 'bottom' reports list.
01805     */
01806     static function appendBottomReport( $reportName, $reportContent )
01807     {
01808         $debug = eZDebug::instance();
01809         $debug->bottomReportsList[$reportName] = $reportContent;
01810     }
01811 
01812     /*!
01813      Prints all 'bottom' reports
01814     */
01815     static function printBottomReportsList()
01816     {
01817         $debug = eZDebug::instance();
01818         $reportNames = array_keys( $debug->bottomReportsList );
01819         foreach ( $reportNames as $reportName )
01820         {
01821             echo $debug->bottomReportsList[$reportName];
01822         }
01823     }
01824 
01825     /*!
01826      If debugging is allowed, given the limitations of the DebugByIP and DebugByUser settings.
01827     */
01828     function isDebugAllowed()
01829     {
01830 
01831     }
01832 
01833     /*!
01834      If debugging is allowed for the current IP address.
01835     */
01836     private static function isAllowedByCurrentIP( $allowedIpList )
01837     {
01838         $ipAddress = eZSys::serverVariable( 'REMOTE_ADDR', true );
01839         if ( $ipAddress )
01840         {
01841             foreach( $allowedIpList as $itemToMatch )
01842             {
01843                 if ( preg_match("/^(([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+))(\/([0-9]+)$|$)/", $itemToMatch, $matches ) )
01844                 {
01845                     if ( $matches[6] )
01846                     {
01847                         if ( self::isIPInNet( $ipAddress, $matches[1], $matches[7] ) )
01848                         {
01849                             return true;
01850                         }
01851                     }
01852                     else
01853                     {
01854                         if ( $matches[1] == $ipAddress )
01855                         {
01856                             return true;
01857                         }
01858                     }
01859                 }
01860             }
01861 
01862             return false;
01863         }
01864         else
01865         {
01866             return eZSys::isShellExecution() && in_array( 'commandline', $allowedIpList );
01867         }
01868     }
01869 
01870     /// \privatesection
01871     /// String array containing the debug information
01872     public $DebugStrings = array();
01873 
01874     /// Array which contains the time points
01875     public $TimePoints = array();
01876 
01877     /// Array which contains the temporary time points
01878     public $TmpTimePoints;
01879 
01880     /// Array wich contains time accumulators
01881     public $TimeAccumulatorList = array();
01882 
01883     /// Determines which debug messages should be shown
01884     public $ShowTypes;
01885 
01886     /// Determines what to do with php errors, ignore, fetch or output
01887     public $HandleType;
01888 
01889     /// An array of the outputformats for the different debug levels
01890     public $OutputFormat;
01891 
01892     /// An array of logfiles used by the debug class with each key being the debug level
01893     public $LogFiles;
01894 
01895     /// How many places behing . should be displayed when showing times
01896     public $TimingAccuracy = 4;
01897 
01898     /// How many places behing . should be displayed when showing percentages
01899     public $PercentAccuracy = 4;
01900 
01901     /// Whether to use external CSS or output own CSS. True if external is to be used.
01902     public $UseCSS;
01903 
01904     /// Determines how messages are output (screen/log)
01905     public $MessageOutput;
01906 
01907     /// A list of message types
01908     public $MessageTypes;
01909 
01910     /// A map with message types and whether they should do file logging.
01911     public $LogFileEnabled;
01912 
01913     /// Controls whether logfiles are used at all.
01914     public $GlobalLogFileEnabled;
01915 
01916     /// The time when the script was started
01917     public $ScriptStart;
01918 
01919     /// A list of override directories
01920     public $OverrideList;
01921 
01922     /// A list of debug reports that appears at the bottom of debug output
01923     public $bottomReportsList;
01924 
01925     /// A list of debug reports that appears at the top of debug output
01926     public $topReportsList;
01927 }
01928 
01929 /*!
01930   Helper function for eZDebug, called whenever a PHP error occurs.
01931   The error is then handled by the eZDebug class.
01932 */
01933 
01934 function eZDebugErrorHandler( $errno, $errstr, $errfile, $errline )
01935 {
01936     if ( $GLOBALS['eZDebugRecursionFlag'] )
01937     {
01938         print( "Fatal debug error: A recursion in debug error handler was detected, aborting debug message.<br/>" );
01939         $GLOBALS['eZDebugRecursionFlag'] = false;
01940         return;
01941     }
01942 
01943     $GLOBALS['eZDebugRecursionFlag'] = true;
01944     $debug = eZDebug::instance();
01945     $result = $debug->errorHandler( $errno, $errstr, $errfile, $errline );
01946     $GLOBALS['eZDebugRecursionFlag'] = false;
01947     return $result;
01948 }
01949 $GLOBALS['eZDebugRecursionFlag'] = false;
01950 
01951 ?>