HomeHelpTrac

Changeset 14725


Ignore:
Timestamp:
12/06/10 23:11:27 (18 months ago)
Author:
Alexander Trofimov
Message:

Ticket #2316

Location:
trunk/plugins/firephp
Files:
1 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/plugins/firephp/FirePHP.class.php

    r8795 r14725  
    77 * Software License Agreement (New BSD License) 
    88 *  
    9  * Copyright (c) 2006-2008, Christoph Dorn 
     9 * Copyright (c) 2006-2010, Christoph Dorn 
    1010 * All rights reserved. 
    1111 *  
     
    3737 * ***** END LICENSE BLOCK ***** 
    3838 *  
    39  * @copyright   Copyright (C) 2007-2008 Christoph Dorn 
    40  * @author      Christoph Dorn <christoph@christophdorn.com> 
    41  * @license     http://www.opensource.org/licenses/bsd-license.php 
    42  * @package     FirePHP 
     39 * @copyright       Copyright (C) 2007-2009 Christoph Dorn 
     40 * @author          Christoph Dorn <christoph@christophdorn.com> 
     41 * @license         http://www.opensource.org/licenses/bsd-license.php 
     42 * @package         FirePHPCore 
    4343 */ 
    44   
     44 
     45/** 
     46 * @see http://code.google.com/p/firephp/issues/detail?id=112 
     47 */ 
     48if (!defined('E_STRICT')) { 
     49    define('E_STRICT', 2048); 
     50} 
     51if (!defined('E_RECOVERABLE_ERROR')) { 
     52    define('E_RECOVERABLE_ERROR', 4096); 
     53} 
     54if (!defined('E_DEPRECATED')) { 
     55    define('E_DEPRECATED', 8192); 
     56} 
     57if (!defined('E_USER_DEPRECATED')) { 
     58    define('E_USER_DEPRECATED', 16384); 
     59}  
    4560  
    4661/** 
     
    5166 * For more information see: http://www.firephp.org/ 
    5267 *  
    53  * @copyright   Copyright (C) 2007-2008 Christoph Dorn 
    54  * @author      Christoph Dorn <christoph@christophdorn.com> 
    55  * @license     http://www.opensource.org/licenses/bsd-license.php 
    56  * @package     FirePHP 
     68 * @copyright       Copyright (C) 2007-2009 Christoph Dorn 
     69 * @author          Christoph Dorn <christoph@christophdorn.com> 
     70 * @license         http://www.opensource.org/licenses/bsd-license.php 
     71 * @package         FirePHPCore 
    5772 */ 
    5873class FirePHP { 
     74 
     75    /** 
     76     * FirePHP version 
     77     * 
     78     * @var string 
     79     */ 
     80    const VERSION = '0.3';    // @pinf replace '0.3' with '%%package.version%%' 
     81 
     82    /** 
     83     * Firebug LOG level 
     84     * 
     85     * Logs a message to firebug console. 
     86     *  
     87     * @var string 
     88     */ 
     89    const LOG = 'LOG'; 
    5990   
    60   /** 
    61    * FirePHP version 
    62    * 
    63    * @var string 
    64    */ 
    65   const VERSION = '0.2.1'; 
     91    /** 
     92     * Firebug INFO level 
     93     * 
     94     * Logs a message to firebug console and displays an info icon before the message. 
     95     *  
     96     * @var string 
     97     */ 
     98    const INFO = 'INFO'; 
     99     
     100    /** 
     101     * Firebug WARN level 
     102     * 
     103     * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. 
     104     *  
     105     * @var string 
     106     */ 
     107    const WARN = 'WARN'; 
     108     
     109    /** 
     110     * Firebug ERROR level 
     111     * 
     112     * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. 
     113     *  
     114     * @var string 
     115     */ 
     116    const ERROR = 'ERROR'; 
     117     
     118    /** 
     119     * Dumps a variable to firebug's server panel 
     120     * 
     121     * @var string 
     122     */ 
     123    const DUMP = 'DUMP'; 
     124     
     125    /** 
     126     * Displays a stack trace in firebug console 
     127     * 
     128     * @var string 
     129     */ 
     130    const TRACE = 'TRACE'; 
     131     
     132    /** 
     133     * Displays an exception in firebug console 
     134     *  
     135     * Increments the firebug error count. 
     136     * 
     137     * @var string 
     138     */ 
     139    const EXCEPTION = 'EXCEPTION'; 
     140     
     141    /** 
     142     * Displays an table in firebug console 
     143     * 
     144     * @var string 
     145     */ 
     146    const TABLE = 'TABLE'; 
     147     
     148    /** 
     149     * Starts a group in firebug console 
     150     *  
     151     * @var string 
     152     */ 
     153    const GROUP_START = 'GROUP_START'; 
     154     
     155    /** 
     156     * Ends a group in firebug console 
     157     *  
     158     * @var string 
     159     */ 
     160    const GROUP_END = 'GROUP_END'; 
     161     
     162    /** 
     163     * Singleton instance of FirePHP 
     164     * 
     165     * @var FirePHP 
     166     */ 
     167    protected static $instance = null; 
     168     
     169    /** 
     170     * Flag whether we are logging from within the exception handler 
     171     *  
     172     * @var boolean 
     173     */ 
     174    protected $inExceptionHandler = false; 
     175     
     176    /** 
     177     * Flag whether to throw PHP errors that have been converted to ErrorExceptions 
     178     *  
     179     * @var boolean 
     180     */ 
     181    protected $throwErrorExceptions = true; 
     182     
     183    /** 
     184     * Flag whether to convert PHP assertion errors to Exceptions 
     185     *  
     186     * @var boolean 
     187     */ 
     188    protected $convertAssertionErrorsToExceptions = true; 
     189     
     190    /** 
     191     * Flag whether to throw PHP assertion errors that have been converted to Exceptions 
     192     *  
     193     * @var boolean 
     194     */ 
     195    protected $throwAssertionExceptions = false; 
     196 
     197    /** 
     198     * Wildfire protocol message index 
     199     * 
     200     * @var int 
     201     */ 
     202    protected $messageIndex = 1; 
     203     
     204    /** 
     205     * Options for the library 
     206     *  
     207     * @var array 
     208     */ 
     209    protected $options = array('maxDepth' => 10, 
     210                               'maxObjectDepth' => 5, 
     211                               'maxArrayDepth' => 5, 
     212                               'useNativeJsonEncode' => true, 
     213                               'includeLineNumbers' => true); 
     214 
     215    /** 
     216     * Filters used to exclude object members when encoding 
     217     *  
     218     * @var array 
     219     */ 
     220    protected $objectFilters = array( 
     221        'firephp' => array('objectStack', 'instance', 'json_objectStack'), 
     222        'firephp_test_class' => array('objectStack', 'instance', 'json_objectStack') 
     223    ); 
     224 
     225    /** 
     226     * A stack of objects used to detect recursion during object encoding 
     227     *  
     228     * @var object 
     229     */ 
     230    protected $objectStack = array(); 
     231 
     232    /** 
     233     * Flag to enable/disable logging 
     234     *  
     235     * @var boolean 
     236     */ 
     237    protected $enabled = true; 
     238 
     239    /** 
     240     * The insight console to log to if applicable 
     241     *  
     242     * @var object 
     243     */ 
     244    protected $logToInsightConsole = null; 
     245 
     246    /** 
     247     * When the object gets serialized only include specific object members. 
     248     *  
     249     * @return array 
     250     */   
     251    public function __sleep() 
     252    { 
     253        return array('options','objectFilters','enabled'); 
     254    } 
     255     
     256    /** 
     257     * Gets singleton instance of FirePHP 
     258     * 
     259     * @param boolean $AutoCreate 
     260     * @return FirePHP 
     261     */ 
     262    public static function getInstance($AutoCreate = false) 
     263    { 
     264        if ($AutoCreate===true && !self::$instance) { 
     265            self::init(); 
     266        } 
     267        return self::$instance; 
     268    } 
     269     
     270    /** 
     271     * Creates FirePHP object and stores it for singleton access 
     272     * 
     273     * @return FirePHP 
     274     */ 
     275    public static function init() 
     276    { 
     277        return self::setInstance(new self()); 
     278    } 
     279 
     280    /** 
     281     * Set the instance of the FirePHP singleton 
     282     *  
     283     * @param FirePHP $instance The FirePHP object instance 
     284     * @return FirePHP 
     285     */ 
     286    public static function setInstance($instance) 
     287    { 
     288        return self::$instance = $instance; 
     289    } 
     290 
     291    /** 
     292     * Set an Insight console to direct all logging calls to 
     293     *  
     294     * @param object $console The console object to log to 
     295     * @return void 
     296     */ 
     297    public function setLogToInsightConsole($console) 
     298    { 
     299        if(is_string($console)) { 
     300            if(get_class($this)!='FirePHP_Insight' && !is_subclass_of($this, 'FirePHP_Insight')) { 
     301                throw new Exception('FirePHP instance not an instance or subclass of FirePHP_Insight!'); 
     302            } 
     303            $this->logToInsightConsole = $this->to('request')->console($console); 
     304        } else { 
     305            $this->logToInsightConsole = $console; 
     306        } 
     307    } 
     308 
     309    /** 
     310     * Enable and disable logging to Firebug 
     311     *  
     312     * @param boolean $Enabled TRUE to enable, FALSE to disable 
     313     * @return void 
     314     */ 
     315    public function setEnabled($Enabled) 
     316    { 
     317       $this->enabled = $Enabled; 
     318    } 
     319     
     320    /** 
     321     * Check if logging is enabled 
     322     *  
     323     * @return boolean TRUE if enabled 
     324     */ 
     325    public function getEnabled() 
     326    { 
     327        return $this->enabled; 
     328    } 
     329     
     330    /** 
     331     * Specify a filter to be used when encoding an object 
     332     *  
     333     * Filters are used to exclude object members. 
     334     *  
     335     * @param string $Class The class name of the object 
     336     * @param array $Filter An array of members to exclude 
     337     * @return void 
     338     */ 
     339    public function setObjectFilter($Class, $Filter) 
     340    { 
     341        $this->objectFilters[strtolower($Class)] = $Filter; 
     342    } 
    66343   
    67   /** 
    68    * Firebug LOG level 
    69    * 
    70    * Logs a message to firebug console. 
    71    *  
    72    * @var string 
    73    */ 
    74   const LOG = 'LOG'; 
     344    /** 
     345     * Set some options for the library 
     346     *  
     347     * Options: 
     348     *  - maxDepth: The maximum depth to traverse (default: 10) 
     349     *  - maxObjectDepth: The maximum depth to traverse objects (default: 5) 
     350     *  - maxArrayDepth: The maximum depth to traverse arrays (default: 5) 
     351     *  - useNativeJsonEncode: If true will use json_encode() (default: true) 
     352     *  - includeLineNumbers: If true will include line numbers and filenames (default: true) 
     353     *  
     354     * @param array $Options The options to be set 
     355     * @return void 
     356     */ 
     357    public function setOptions($Options) 
     358    { 
     359        $this->options = array_merge($this->options,$Options); 
     360    } 
     361 
     362    /** 
     363     * Get options from the library 
     364     * 
     365     * @return array The currently set options 
     366     */ 
     367    public function getOptions() 
     368    { 
     369        return $this->options; 
     370    } 
     371 
     372    /** 
     373     * Set an option for the library 
     374     *  
     375     * @param string $Name 
     376     * @param mixed $Value 
     377     * @throws Exception 
     378     * @return void 
     379     */   
     380    public function setOption($Name, $Value) 
     381    { 
     382        if (!isset($this->options[$Name])) { 
     383            throw $this->newException('Unknown option: ' . $Name); 
     384        } 
     385        $this->options[$Name] = $Value; 
     386    } 
     387 
     388    /** 
     389     * Get an option from the library 
     390     * 
     391     * @param string $Name 
     392     * @throws Exception 
     393     * @return mixed 
     394     */ 
     395    public function getOption($Name) 
     396    { 
     397        if (!isset($this->options[$Name])) { 
     398            throw $this->newException('Unknown option: ' . $Name); 
     399        } 
     400        return $this->options[$Name]; 
     401    } 
     402 
     403    /** 
     404     * Register FirePHP as your error handler 
     405     *  
     406     * Will throw exceptions for each php error. 
     407     *  
     408     * @return mixed Returns a string containing the previously defined error handler (if any) 
     409     */ 
     410    public function registerErrorHandler($throwErrorExceptions = false) 
     411    { 
     412        //NOTE: The following errors will not be caught by this error handler: 
     413        //      E_ERROR, E_PARSE, E_CORE_ERROR, 
     414        //      E_CORE_WARNING, E_COMPILE_ERROR, 
     415        //      E_COMPILE_WARNING, E_STRICT 
     416     
     417        $this->throwErrorExceptions = $throwErrorExceptions; 
     418     
     419        return set_error_handler(array($this,'errorHandler'));      
     420    } 
     421 
     422    /** 
     423     * FirePHP's error handler 
     424     *  
     425     * Throws exception for each php error that will occur. 
     426     * 
     427     * @param int $errno 
     428     * @param string $errstr 
     429     * @param string $errfile 
     430     * @param int $errline 
     431     * @param array $errcontext 
     432     */ 
     433    public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) 
     434    { 
     435        // Don't throw exception if error reporting is switched off 
     436        if (error_reporting() == 0) { 
     437            return; 
     438        } 
     439        // Only throw exceptions for errors we are asking for 
     440        if (error_reporting() & $errno) { 
     441 
     442            $exception = new ErrorException($errstr, 0, $errno, $errfile, $errline); 
     443            if ($this->throwErrorExceptions) { 
     444                throw $exception; 
     445            } else { 
     446                $this->fb($exception); 
     447            } 
     448        } 
     449    } 
    75450   
    76   /** 
    77    * Firebug INFO level 
    78    * 
    79    * Logs a message to firebug console and displays an info icon before the message. 
    80    *  
    81    * @var string 
    82    */ 
    83   const INFO = 'INFO'; 
     451    /** 
     452     * Register FirePHP as your exception handler 
     453     *  
     454     * @return mixed Returns the name of the previously defined exception handler, 
     455     *               or NULL on error. 
     456     *               If no previous handler was defined, NULL is also returned. 
     457     */ 
     458    public function registerExceptionHandler() 
     459    { 
     460        return set_exception_handler(array($this,'exceptionHandler'));      
     461    } 
    84462   
    85   /** 
    86    * Firebug WARN level 
    87    * 
    88    * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. 
    89    *  
    90    * @var string 
    91    */ 
    92   const WARN = 'WARN'; 
     463    /** 
     464     * FirePHP's exception handler 
     465     *  
     466     * Logs all exceptions to your firebug console and then stops the script. 
     467     * 
     468     * @param Exception $Exception 
     469     * @throws Exception 
     470     */ 
     471    function exceptionHandler($Exception) 
     472    { 
     473     
     474        $this->inExceptionHandler = true; 
     475     
     476        header('HTTP/1.1 500 Internal Server Error'); 
     477     
     478        try { 
     479            $this->fb($Exception); 
     480        } catch (Exception $e) { 
     481            echo 'We had an exception: ' . $e; 
     482        } 
     483        $this->inExceptionHandler = false; 
     484    } 
    93485   
    94   /** 
    95    * Firebug ERROR level 
    96    * 
    97    * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. 
    98    *  
    99    * @var string 
    100    */ 
    101   const ERROR = 'ERROR'; 
     486    /** 
     487     * Register FirePHP driver as your assert callback 
     488     *  
     489     * @param boolean $convertAssertionErrorsToExceptions 
     490     * @param boolean $throwAssertionExceptions 
     491     * @return mixed Returns the original setting or FALSE on errors 
     492     */ 
     493    public function registerAssertionHandler($convertAssertionErrorsToExceptions = true, $throwAssertionExceptions = false) 
     494    { 
     495        $this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions; 
     496        $this->throwAssertionExceptions = $throwAssertionExceptions; 
     497         
     498        if ($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) { 
     499            throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!'); 
     500        } 
     501         
     502        return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler')); 
     503    } 
    102504   
    103   /** 
    104    * Dumps a variable to firebug's server panel 
    105    * 
    106    * @var string 
    107    */ 
    108   const DUMP = 'DUMP'; 
     505    /** 
     506     * FirePHP's assertion handler 
     507     * 
     508     * Logs all assertions to your firebug console and then stops the script. 
     509     * 
     510     * @param string $file File source of assertion 
     511     * @param int    $line Line source of assertion 
     512     * @param mixed  $code Assertion code 
     513     */ 
     514    public function assertionHandler($file, $line, $code) 
     515    { 
     516        if ($this->convertAssertionErrorsToExceptions) { 
     517           
     518          $exception = new ErrorException('Assertion Failed - Code[ '.$code.' ]', 0, null, $file, $line); 
     519     
     520          if ($this->throwAssertionExceptions) { 
     521              throw $exception; 
     522          } else { 
     523              $this->fb($exception); 
     524          } 
     525         
     526        } else { 
     527            $this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File'=>$file,'Line'=>$line)); 
     528        } 
     529    } 
    109530   
    110   /** 
    111    * Displays a stack trace in firebug console 
    112    * 
    113    * @var string 
    114    */ 
    115   const TRACE = 'TRACE'; 
     531    /** 
     532     * Start a group for following messages. 
     533     *  
     534     * Options: 
     535     *   Collapsed: [true|false] 
     536     *   Color:     [#RRGGBB|ColorName] 
     537     * 
     538     * @param string $Name 
     539     * @param array $Options OPTIONAL Instructions on how to log the group 
     540     * @return true 
     541     * @throws Exception 
     542     */ 
     543    public function group($Name, $Options = null) 
     544    { 
     545     
     546        if (!$Name) { 
     547            throw $this->newException('You must specify a label for the group!'); 
     548        } 
     549         
     550        if ($Options) { 
     551            if (!is_array($Options)) { 
     552                throw $this->newException('Options must be defined as an array!'); 
     553            } 
     554            if (array_key_exists('Collapsed', $Options)) { 
     555                $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false'; 
     556            } 
     557        } 
     558         
     559        return $this->fb(null, $Name, FirePHP::GROUP_START, $Options); 
     560    } 
    116561   
    117   /** 
    118    * Displays an exception in firebug console 
    119    *  
    120    * Increments the firebug error count. 
    121    * 
    122    * @var string 
    123    */ 
    124   const EXCEPTION = 'EXCEPTION'; 
     562    /** 
     563     * Ends a group you have started before 
     564     * 
     565     * @return true 
     566     * @throws Exception 
     567     */ 
     568    public function groupEnd() 
     569    { 
     570        return $this->fb(null, null, FirePHP::GROUP_END); 
     571    } 
     572 
     573    /** 
     574     * Log object with label to firebug console 
     575     * 
     576     * @see FirePHP::LOG 
     577     * @param mixes $Object 
     578     * @param string $Label 
     579     * @return true 
     580     * @throws Exception 
     581     */ 
     582    public function log($Object, $Label = null, $Options = array()) 
     583    { 
     584        return $this->fb($Object, $Label, FirePHP::LOG, $Options); 
     585    }  
     586 
     587    /** 
     588     * Log object with label to firebug console 
     589     * 
     590     * @see FirePHP::INFO 
     591     * @param mixes $Object 
     592     * @param string $Label 
     593     * @return true 
     594     * @throws Exception 
     595     */ 
     596    public function info($Object, $Label = null, $Options = array()) 
     597    { 
     598        return $this->fb($Object, $Label, FirePHP::INFO, $Options); 
     599    }  
     600 
     601    /** 
     602     * Log object with label to firebug console 
     603     * 
     604     * @see FirePHP::WARN 
     605     * @param mixes $Object 
     606     * @param string $Label 
     607     * @return true 
     608     * @throws Exception 
     609     */ 
     610    public function warn($Object, $Label = null, $Options = array()) 
     611    { 
     612        return $this->fb($Object, $Label, FirePHP::WARN, $Options); 
     613    }  
     614 
     615    /** 
     616     * Log object with label to firebug console 
     617     * 
     618     * @see FirePHP::ERROR 
     619     * @param mixes $Object 
     620     * @param string $Label 
     621     * @return true 
     622     * @throws Exception 
     623     */ 
     624    public function error($Object, $Label = null, $Options = array()) 
     625    { 
     626        return $this->fb($Object, $Label, FirePHP::ERROR, $Options); 
     627    }  
     628 
     629    /** 
     630     * Dumps key and variable to firebug server panel 
     631     * 
     632     * @see FirePHP::DUMP 
     633     * @param string $Key 
     634     * @param mixed $Variable 
     635     * @return true 
     636     * @throws Exception 
     637     */ 
     638    public function dump($Key, $Variable, $Options = array()) 
     639    { 
     640        if (!is_string($Key)) { 
     641            throw $this->newException('Key passed to dump() is not a string'); 
     642        } 
     643        if (strlen($Key)>100) { 
     644            throw $this->newException('Key passed to dump() is longer than 100 characters'); 
     645        } 
     646        if (!preg_match_all('/^[a-zA-Z0-9-_\.:]*$/', $Key, $m)) { 
     647            throw $this->newException('Key passed to dump() contains invalid characters [a-zA-Z0-9-_\.:]'); 
     648        } 
     649        return $this->fb($Variable, $Key, FirePHP::DUMP, $Options); 
     650    } 
    125651   
    126   /** 
    127    * Displays an table in firebug console 
    128    * 
    129    * @var string 
    130    */ 
    131   const TABLE = 'TABLE'; 
     652    /** 
     653     * Log a trace in the firebug console 
     654     * 
     655     * @see FirePHP::TRACE 
     656     * @param string $Label 
     657     * @return true 
     658     * @throws Exception 
     659     */ 
     660    public function trace($Label) 
     661    { 
     662        return $this->fb($Label, FirePHP::TRACE); 
     663    }  
     664 
     665    /** 
     666     * Log a table in the firebug console 
     667     * 
     668     * @see FirePHP::TABLE 
     669     * @param string $Label 
     670     * @param string $Table 
     671     * @return true 
     672     * @throws Exception 
     673     */ 
     674    public function table($Label, $Table, $Options = array()) 
     675    { 
     676        return $this->fb($Table, $Label, FirePHP::TABLE, $Options); 
     677    } 
     678 
     679    /** 
     680     * Insight API wrapper 
     681     *  
     682     * @see Insight_Helper::to() 
     683     */ 
     684    public static function to() 
     685    { 
     686        $instance = self::getInstance(); 
     687        if (!method_exists($instance, "_to")) { 
     688            throw new Exception("FirePHP::to() implementation not loaded"); 
     689        } 
     690        $args = func_get_args(); 
     691        return call_user_func_array(array($instance, '_to'), $args); 
     692    } 
     693 
     694    /** 
     695     * Insight API wrapper 
     696     *  
     697     * @see Insight_Helper::plugin() 
     698     */ 
     699    public static function plugin() 
     700    { 
     701        $instance = self::getInstance(); 
     702        if (!method_exists($instance, "_plugin")) { 
     703            throw new Exception("FirePHP::plugin() implementation not loaded"); 
     704        } 
     705        $args = func_get_args(); 
     706        return call_user_func_array(array($instance, '_plugin'), $args); 
     707    } 
     708 
     709    /** 
     710     * Check if FirePHP is installed on client 
     711     * 
     712     * @return boolean 
     713     */ 
     714    public function detectClientExtension() 
     715    { 
     716        // Check if FirePHP is installed on client via User-Agent header 
     717        if (@preg_match_all('/\sFirePHP\/([\.\d]*)\s?/si',$this->getUserAgent(),$m) && 
     718           version_compare($m[1][0],'0.0.6','>=')) { 
     719            return true; 
     720        } else 
     721        // Check if FirePHP is installed on client via X-FirePHP-Version header 
     722        if (@preg_match_all('/^([\.\d]*)$/si',$this->getRequestHeader("X-FirePHP-Version"),$m) && 
     723           version_compare($m[1][0],'0.0.6','>=')) { 
     724            return true; 
     725        } 
     726        return false; 
     727    } 
     728  
     729    /** 
     730     * Log varible to Firebug 
     731     *  
     732     * @see http://www.firephp.org/Wiki/Reference/Fb 
     733     * @param mixed $Object The variable to be logged 
     734     * @return true Return TRUE if message was added to headers, FALSE otherwise 
     735     * @throws Exception 
     736     */ 
     737    public function fb($Object) 
     738    { 
     739        if($this instanceof FirePHP_Insight && method_exists($this, '_logUpgradeClientMessage')) { 
     740            if(!FirePHP_Insight::$upgradeClientMessageLogged) {    // avoid infinite recursion as _logUpgradeClientMessage() logs a message 
     741                $this->_logUpgradeClientMessage(); 
     742            } 
     743        } 
     744 
     745        static $insightGroupStack = array(); 
     746 
     747        if (!$this->getEnabled()) { 
     748            return false; 
     749        } 
     750 
     751        if ($this->headersSent($filename, $linenum)) { 
     752            // If we are logging from within the exception handler we cannot throw another exception 
     753            if ($this->inExceptionHandler) { 
     754                // Simply echo the error out to the page 
     755                echo '<div style="border: 2px solid red; font-family: Arial; font-size: 12px; background-color: lightgray; padding: 5px;"><span style="color: red; font-weight: bold;">FirePHP ERROR:</span> Headers already sent in <b>'.$filename.'</b> on line <b>'.$linenum.'</b>. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.</div>'; 
     756            } else { 
     757                throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); 
     758            } 
     759        } 
     760       
     761        $Type = null; 
     762        $Label = null; 
     763        $Options = array(); 
     764       
     765        if (func_num_args()==1) { 
     766        } else 
     767        if (func_num_args()==2) { 
     768            switch(func_get_arg(1)) { 
     769                case self::LOG: 
     770                case self::INFO: 
     771                case self::WARN: 
     772                case self::ERROR: 
     773                case self::DUMP: 
     774                case self::TRACE: 
     775                case self::EXCEPTION: 
     776                case self::TABLE: 
     777                case self::GROUP_START: 
     778                case self::GROUP_END: 
     779                    $Type = func_get_arg(1); 
     780                    break; 
     781                default: 
     782                    $Label = func_get_arg(1); 
     783                    break; 
     784            } 
     785        } else 
     786        if (func_num_args()==3) { 
     787            $Type = func_get_arg(2); 
     788            $Label = func_get_arg(1); 
     789        } else 
     790        if (func_num_args()==4) { 
     791            $Type = func_get_arg(2); 
     792            $Label = func_get_arg(1); 
     793            $Options = func_get_arg(3); 
     794        } else { 
     795            throw $this->newException('Wrong number of arguments to fb() function!'); 
     796        } 
     797 
     798        if($this->logToInsightConsole!==null && (get_class($this)=='FirePHP_Insight' || is_subclass_of($this, 'FirePHP_Insight'))) { 
     799            $msg = $this->logToInsightConsole; 
     800            if ($Object instanceof Exception) { 
     801                $Type = self::EXCEPTION; 
     802            } 
     803            if($Label && $Type!=self::TABLE && $Type!=self::GROUP_START) { 
     804                $msg = $msg->label($Label); 
     805            } 
     806            switch($Type) { 
     807                case self::DUMP: 
     808                case self::LOG: 
     809                    return $msg->log($Object); 
     810                case self::INFO: 
     811                    return $msg->info($Object); 
     812                case self::WARN: 
     813                    return $msg->warn($Object); 
     814                case self::ERROR: 
     815                    return $msg->error($Object); 
     816                case self::TRACE: 
     817                    return $msg->trace($Object); 
     818                case self::EXCEPTION: 
     819                    return $this->plugin('engine')->handleException($Object, $msg); 
     820                case self::TABLE: 
     821                    if (isset($Object[0]) && !is_string($Object[0]) && $Label) { 
     822                        $Object = array($Label, $Object); 
     823                    } 
     824                    return $msg->table($Object[0], array_slice($Object[1],1), $Object[1][0]); 
     825                case self::GROUP_START: 
     826                    $insightGroupStack[] = $msg->group(md5($Label))->open(); 
     827                    return $msg->log($Label); 
     828                case self::GROUP_END: 
     829                    if(count($insightGroupStack)==0) { 
     830                        throw new Error('Too many groupEnd() as opposed to group() calls!'); 
     831                    } 
     832                    $group = array_pop($insightGroupStack); 
     833                    return $group->close(); 
     834                default: 
     835                    return $msg->log($Object); 
     836            } 
     837        } 
     838 
     839        if (!$this->detectClientExtension()) { 
     840            return false; 
     841        } 
     842       
     843        $meta = array(); 
     844        $skipFinalObjectEncode = false; 
     845       
     846        if ($Object instanceof Exception) { 
     847     
     848            $meta['file'] = $this->_escapeTraceFile($Object->getFile()); 
     849            $meta['line'] = $Object->getLine(); 
     850           
     851            $trace = $Object->getTrace(); 
     852            if ($Object instanceof ErrorException 
     853               && isset($trace[0]['function']) 
     854               && $trace[0]['function']=='errorHandler' 
     855               && isset($trace[0]['class']) 
     856               && $trace[0]['class']=='FirePHP') { 
     857                
     858                $severity = false; 
     859                switch($Object->getSeverity()) { 
     860                    case E_WARNING: $severity = 'E_WARNING'; break; 
     861                    case E_NOTICE: $severity = 'E_NOTICE'; break; 
     862                    case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; 
     863                    case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; 
     864                    case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; 
     865                    case E_STRICT: $severity = 'E_STRICT'; break; 
     866                    case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; 
     867                    case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; 
     868                    case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; 
     869                } 
     870                    
     871                $Object = array('Class'=>get_class($Object), 
     872                                'Message'=>$severity.': '.$Object->getMessage(), 
     873                                'File'=>$this->_escapeTraceFile($Object->getFile()), 
     874                                'Line'=>$Object->getLine(), 
     875                                'Type'=>'trigger', 
     876                                'Trace'=>$this->_escapeTrace(array_splice($trace,2))); 
     877                $skipFinalObjectEncode = true; 
     878            } else { 
     879                $Object = array('Class'=>get_class($Object), 
     880                                'Message'=>$Object->getMessage(), 
     881                                'File'=>$this->_escapeTraceFile($Object->getFile()), 
     882                                'Line'=>$Object->getLine(), 
     883                                'Type'=>'throw', 
     884                                'Trace'=>$this->_escapeTrace($trace)); 
     885                $skipFinalObjectEncode = true; 
     886            } 
     887            $Type = self::EXCEPTION; 
     888           
     889        } else 
     890        if ($Type==self::TRACE) { 
     891           
     892            $trace = debug_backtrace(); 
     893            if (!$trace) return false; 
     894            for( $i=0 ; $i<sizeof($trace) ; $i++ ) { 
     895     
     896                if (isset($trace[$i]['class']) 
     897                   && isset($trace[$i]['file']) 
     898                   && ($trace[$i]['class']=='FirePHP' 
     899                       || $trace[$i]['class']=='FB') 
     900                   && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' 
     901                       || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { 
     902                    /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ 
     903                } else 
     904                if (isset($trace[$i]['class']) 
     905                   && isset($trace[$i+1]['file']) 
     906                   && $trace[$i]['class']=='FirePHP' 
     907                   && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { 
     908                    /* Skip fb() */ 
     909                } else 
     910                if ($trace[$i]['function']=='fb' 
     911                   || $trace[$i]['function']=='trace' 
     912                   || $trace[$i]['function']=='send') { 
     913 
     914                    $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', 
     915                                    'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', 
     916                                    'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', 
     917                                    'Message'=>$trace[$i]['args'][0], 
     918                                    'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', 
     919                                    'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', 
     920                                    'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', 
     921                                    'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); 
     922         
     923                    $skipFinalObjectEncode = true; 
     924                    $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; 
     925                    $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; 
     926                    break; 
     927                } 
     928            } 
     929     
     930        } else 
     931        if ($Type==self::TABLE) { 
     932           
     933            if (isset($Object[0]) && is_string($Object[0])) { 
     934                $Object[1] = $this->encodeTable($Object[1]); 
     935            } else { 
     936                $Object = $this->encodeTable($Object); 
     937            } 
     938     
     939            $skipFinalObjectEncode = true; 
     940           
     941        } else 
     942        if ($Type==self::GROUP_START) { 
     943           
     944            if (!$Label) { 
     945                throw $this->newException('You must specify a label for the group!'); 
     946            } 
     947           
     948        } else { 
     949            if ($Type===null) { 
     950                $Type = self::LOG; 
     951            } 
     952        } 
     953         
     954        if ($this->options['includeLineNumbers']) { 
     955            if (!isset($meta['file']) || !isset($meta['line'])) { 
     956     
     957                $trace = debug_backtrace(); 
     958                for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) { 
     959           
     960                    if (isset($trace[$i]['class']) 
     961                       && isset($trace[$i]['file']) 
     962                       && ($trace[$i]['class']=='FirePHP' 
     963                           || $trace[$i]['class']=='FB') 
     964                       && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' 
     965                           || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { 
     966                        /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ 
     967                    } else 
     968                    if (isset($trace[$i]['class']) 
     969                       && isset($trace[$i+1]['file']) 
     970                       && $trace[$i]['class']=='FirePHP' 
     971                       && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { 
     972                        /* Skip fb() */ 
     973                    } else 
     974                    if (isset($trace[$i]['file']) 
     975                       && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { 
     976                        /* Skip FB::fb() */ 
     977                    } else { 
     978                        $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; 
     979                        $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; 
     980                        break; 
     981                    } 
     982                }       
     983            } 
     984        } else { 
     985            unset($meta['file']); 
     986            unset($meta['line']); 
     987        } 
     988 
     989        $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); 
     990        $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); 
     991      
     992        $structure_index = 1; 
     993        if ($Type==self::DUMP) { 
     994            $structure_index = 2; 
     995            $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); 
     996        } else { 
     997            $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); 
     998        } 
     999       
     1000        if ($Type==self::DUMP) { 
     1001            $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; 
     1002        } else { 
     1003            $msg_meta = $Options; 
     1004            $msg_meta['Type'] = $Type; 
     1005            if ($Label!==null) { 
     1006                $msg_meta['Label'] = $Label; 
     1007            } 
     1008            if (isset($meta['file']) && !isset($msg_meta['File'])) { 
     1009                $msg_meta['File'] = $meta['file']; 
     1010            } 
     1011            if (isset($meta['line']) && !isset($msg_meta['Line'])) { 
     1012                $msg_meta['Line'] = $meta['line']; 
     1013            } 
     1014            $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; 
     1015        } 
     1016         
     1017        $parts = explode("\n",chunk_split($msg, 5000, "\n")); 
     1018     
     1019        for( $i=0 ; $i<count($parts) ; $i++) { 
     1020             
     1021            $part = $parts[$i]; 
     1022            if ($part) { 
     1023                 
     1024                if (count($parts)>2) { 
     1025                    // Message needs to be split into multiple parts 
     1026                    $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, 
     1027                                     (($i==0)?strlen($msg):'') 
     1028                                     . '|' . $part . '|' 
     1029                                     . (($i<count($parts)-2)?'\\':'')); 
     1030                } else { 
     1031                    $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, 
     1032                                     strlen($part) . '|' . $part . '|'); 
     1033                } 
     1034                 
     1035                $this->messageIndex++; 
     1036                 
     1037                if ($this->messageIndex > 99999) { 
     1038                    throw $this->newException('Maximum number (99,999) of messages reached!');              
     1039                } 
     1040            } 
     1041        } 
     1042     
     1043        $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); 
     1044     
     1045        return true; 
     1046    } 
    1321047   
    133   /** 
    134    * Starts a group in firebug console 
    135    *  
    136    * @var string 
    137    */ 
    138   const GROUP_START = 'GROUP_START'; 
     1048    /** 
     1049     * Standardizes path for windows systems. 
     1050     * 
     1051     * @param string $Path 
     1052     * @return string 
     1053     */ 
     1054    protected function _standardizePath($Path) 
     1055    { 
     1056        return preg_replace('/\\\\+/','/',$Path);     
     1057    } 
    1391058   
    140   /** 
    141    * Ends a group in firebug console 
    142    *  
    143    * @var string 
    144    */ 
    145   const GROUP_END = 'GROUP_END'; 
     1059    /** 
     1060     * Escape trace path for windows systems 
     1061     * 
     1062     * @param array $Trace 
     1063     * @return array 
     1064     */ 
     1065    protected function _escapeTrace($Trace) 
     1066    { 
     1067        if (!$Trace) return $Trace; 
     1068        for( $i=0 ; $i<sizeof($Trace) ; $i++ ) { 
     1069            if (isset($Trace[$i]['file'])) { 
     1070                $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']); 
     1071            } 
     1072            if (isset($Trace[$i]['args'])) { 
     1073                $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); 
     1074            } 
     1075        } 
     1076        return $Trace;     
     1077    } 
    1461078   
    147   /** 
    148    * Singleton instance of FirePHP 
    149    * 
    150    * @var FirePHP 
    151    */ 
    152   protected static $instance = null; 
     1079    /** 
     1080     * Escape file information of trace for windows systems 
     1081     * 
     1082     * @param string $File 
     1083     * @return string 
     1084     */ 
     1085    protected function _escapeTraceFile($File) 
     1086    { 
     1087        /* Check if we have a windows filepath */ 
     1088        if (strpos($File,'\\')) { 
     1089            /* First strip down to single \ */ 
     1090           
     1091            $file = preg_replace('/\\\\+/','\\',$File); 
     1092           
     1093            return $file; 
     1094        } 
     1095        return $File; 
     1096    } 
     1097 
     1098    /** 
     1099     * Check if headers have already been sent 
     1100     * 
     1101     * @param string $Filename 
     1102     * @param integer $Linenum 
     1103     */ 
     1104    protected function headersSent(&$Filename, &$Linenum) 
     1105    { 
     1106        return headers_sent($Filename, $Linenum); 
     1107    } 
     1108 
     1109    /** 
     1110     * Send header 
     1111     * 
     1112     * @param string $Name 
     1113     * @param string $Value 
     1114     */ 
     1115    protected function setHeader($Name, $Value) 
     1116    { 
     1117        return header($Name.': '.$Value); 
     1118    } 
     1119 
     1120    /** 
     1121     * Get user agent 
     1122     * 
     1123     * @return string|false 
     1124     */ 
     1125    protected function getUserAgent() 
     1126    { 
     1127        if (!isset($_SERVER['HTTP_USER_AGENT'])) return false; 
     1128        return $_SERVER['HTTP_USER_AGENT']; 
     1129    } 
     1130 
     1131    /** 
     1132     * Get all request headers 
     1133     *  
     1134     * @return array 
     1135     */ 
     1136    public static function getAllRequestHeaders() { 
     1137        static $_cached_headers = false; 
     1138        if($_cached_headers!==false) { 
     1139            return $_cached_headers; 
     1140        } 
     1141        $headers = array(); 
     1142        if(function_exists('getallheaders')) { 
     1143            foreach( getallheaders() as $name => $value ) { 
     1144                $headers[strtolower($name)] = $value; 
     1145            } 
     1146        } else { 
     1147            foreach($_SERVER as $name => $value) { 
     1148                if(substr($name, 0, 5) == 'HTTP_') { 
     1149                    $headers[strtolower(str_replace(' ', '-', str_replace('_', ' ', substr($name, 5))))] = $value; 
     1150                } 
     1151            } 
     1152        } 
     1153        return $_cached_headers = $headers; 
     1154    } 
     1155 
     1156    /** 
     1157     * Get a request header 
     1158     * 
     1159     * @return string|false 
     1160     */ 
     1161    protected function getRequestHeader($Name) 
     1162    { 
     1163        $headers = self::getAllRequestHeaders(); 
     1164        if (isset($headers[strtolower($Name)])) { 
     1165            return $headers[strtolower($Name)]; 
     1166        } 
     1167        return false; 
     1168    } 
     1169 
     1170    /** 
     1171     * Returns a new exception 
     1172     * 
     1173     * @param string $Message 
     1174     * @return Exception 
     1175     */ 
     1176    protected function newException($Message) 
     1177    { 
     1178        return new Exception($Message); 
     1179    } 
    1531180   
    154   /** 
    155    * Wildfire protocol message index 
    156    * 
    157    * @var int 
    158    */ 
    159   protected $messageIndex = 1; 
    160      
    161   /** 
    162    * Options for the library 
    163    *  
    164    * @var array 
    165    */ 
    166   protected $options = array(); 
    167    
    168   /** 
    169    * Filters used to exclude object members when encoding 
    170    *  
    171    * @var array 
    172    */ 
    173   protected $objectFilters = array(); 
    174    
    175   /** 
    176    * A stack of objects used to detect recursion during object encoding 
    177    *  
    178    * @var object 
    179    */ 
    180   protected $objectStack = array(); 
    181    
    182   /** 
    183    * Flag to enable/disable logging 
    184    *  
    185    * @var boolean 
    186    */ 
    187   protected $enabled = true; 
    188    
    189   /** 
    190    * The object constructor 
    191    */ 
    192   function __construct() { 
    193     $this->options['maxObjectDepth'] = 10; 
    194     $this->options['maxArrayDepth'] = 20; 
    195     $this->options['useNativeJsonEncode'] = true; 
    196     $this->options['includeLineNumbers'] = true; 
    197   } 
    198      
    199   /** 
    200    * When the object gets serialized only include specific object members. 
    201    *  
    202    * @return array 
    203    */   
    204   public function __sleep() { 
    205     return array('options','objectFilters','enabled'); 
    206   } 
    207      
    208   /** 
    209    * Gets singleton instance of FirePHP 
    210    * 
    211    * @param boolean $AutoCreate 
    212    * @return FirePHP 
    213    */ 
    214   public static function getInstance($AutoCreate=false) { 
    215     if($AutoCreate===true && !self::$instance) { 
    216       self::init(); 
    217     } 
    218     return self::$instance; 
    219   } 
    220     
    221   /** 
    222    * Creates FirePHP object and stores it for singleton access 
    223    * 
    224    * @return FirePHP 
    225    */ 
    226   public static function init() { 
    227     return self::$instance = new self(); 
    228   } 
    229    
    230   /** 
    231    * Enable and disable logging to Firebug 
    232    *  
    233    * @param boolean $Enabled TRUE to enable, FALSE to disable 
    234    * @return void 
    235    */ 
    236   public function setEnabled($Enabled) { 
    237     $this->enabled = $Enabled; 
    238   } 
    239    
    240   /** 
    241    * Check if logging is enabled 
    242    *  
    243    * @return boolean TRUE if enabled 
    244    */ 
    245   public function getEnabled() { 
    246     return $this->enabled; 
    247   } 
    248    
    249   /** 
    250    * Specify a filter to be used when encoding an object 
    251    *  
    252    * Filters are used to exclude object members. 
    253    *  
    254    * @param string $Class The class name of the object 
    255    * @param array $Filter An array or members to exclude 
    256    * @return void 
    257    */ 
    258   public function setObjectFilter($Class, $Filter) { 
    259     $this->objectFilters[$Class] = $Filter; 
    260   } 
    261    
    262   /** 
    263    * Set some options for the library 
    264    *  
    265    * Options: 
    266    *  - maxObjectDepth: The maximum depth to traverse objects (default: 10) 
    267    *  - maxArrayDepth: The maximum depth to traverse arrays (default: 20) 
    268    *  - useNativeJsonEncode: If true will use json_encode() (default: true) 
    269    *  - includeLineNumbers: If true will include line numbers and filenames (default: true) 
    270    *  
    271    * @param array $Options The options to be set 
    272    * @return void 
    273    */ 
    274   public function setOptions($Options) { 
    275     $this->options = array_merge($this->options,$Options); 
    276   } 
    277    
    278   /** 
    279    * Register FirePHP as your error handler 
    280    *  
    281    * Will throw exceptions for each php error. 
    282    */ 
    283   public function registerErrorHandler() 
    284   { 
    285     //NOTE: The following errors will not be caught by this error handler: 
    286     //      E_ERROR, E_PARSE, E_CORE_ERROR, 
    287     //      E_CORE_WARNING, E_COMPILE_ERROR, 
    288     //      E_COMPILE_WARNING, E_STRICT 
    289      
    290     set_error_handler(array($this,'errorHandler'));      
    291   } 
    292  
    293   /** 
    294    * FirePHP's error handler 
    295    *  
    296    * Throws exception for each php error that will occur. 
    297    * 
    298    * @param int $errno 
    299    * @param string $errstr 
    300    * @param string $errfile 
    301    * @param int $errline 
    302    * @param array $errcontext 
    303    */ 
    304   public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) 
    305   { 
    306     // Don't throw exception if error reporting is switched off 
    307     if (error_reporting() == 0) { 
    308       return; 
    309     } 
    310     // Only throw exceptions for errors we are asking for 
    311     if (error_reporting() & $errno) { 
    312       throw new ErrorException($errstr, 0, $errno, $errfile, $errline); 
    313     } 
    314   } 
    315    
    316   /** 
    317    * Register FirePHP as your exception handler 
    318    */ 
    319   public function registerExceptionHandler() 
    320   { 
    321     set_exception_handler(array($this,'exceptionHandler'));      
    322   } 
    323    
    324   /** 
    325    * FirePHP's exception handler 
    326    *  
    327    * Logs all exceptions to your firebug console and then stops the script. 
    328    * 
    329    * @param Exception $Exception 
    330    * @throws Exception 
    331    */ 
    332   function exceptionHandler($Exception) { 
    333     $this->fb($Exception); 
    334   } 
    335    
    336   /** 
    337    * Set custom processor url for FirePHP 
    338    * 
    339    * @param string $URL 
    340    */     
    341   public function setProcessorUrl($URL) 
    342   { 
    343     $this->setHeader('X-FirePHP-ProcessorURL', $URL); 
    344   } 
    345  
    346   /** 
    347    * Set custom renderer url for FirePHP 
    348    * 
    349    * @param string $URL 
    350    */ 
    351   public function setRendererUrl($URL) 
    352   { 
    353     $this->setHeader('X-FirePHP-RendererURL', $URL); 
    354   } 
    355    
    356   /** 
    357    * Start a group for following messages 
    358    * 
    359    * @param string $Name 
    360    * @return true 
    361    * @throws Exception 
    362    */ 
    363   public function group($Name) { 
    364     return $this->fb(null, $Name, FirePHP::GROUP_START); 
    365   } 
    366    
    367   /** 
    368    * Ends a group you have started before 
    369    * 
    370    * @return true 
    371    * @throws Exception 
    372    */ 
    373   public function groupEnd() { 
    374     return $this->fb(null, null, FirePHP::GROUP_END); 
    375   } 
    376  
    377   /** 
    378    * Log object with label to firebug console 
    379    * 
    380    * @see FirePHP::LOG 
    381    * @param mixes $Object 
    382    * @param string $Label 
    383    * @return true 
    384    * @throws Exception 
    385    */ 
    386   public function log($Object, $Label=null) { 
    387     return $this->fb($Object, $Label, FirePHP::LOG); 
    388   }  
    389  
    390   /** 
    391    * Log object with label to firebug console 
    392    * 
    393    * @see FirePHP::INFO 
    394    * @param mixes $Object 
    395    * @param string $Label 
    396    * @return true 
    397    * @throws Exception 
    398    */ 
    399   public function info($Object, $Label=null) { 
    400     return $this->fb($Object, $Label, FirePHP::INFO); 
    401   }  
    402  
    403   /** 
    404    * Log object with label to firebug console 
    405    * 
    406    * @see FirePHP::WARN 
    407    * @param mixes $Object 
    408    * @param string $Label 
    409    * @return true 
    410    * @throws Exception 
    411    */ 
    412   public function warn($Object, $Label=null) { 
    413     return $this->fb($Object, $Label, FirePHP::WARN); 
    414   }  
    415  
    416   /** 
    417    * Log object with label to firebug console 
    418    * 
    419    * @see FirePHP::ERROR 
    420    * @param mixes $Object 
    421    * @param string $Label 
    422    * @return true 
    423    * @throws Exception 
    424    */ 
    425   public function error($Object, $Label=null) { 
    426     return $this->fb($Object, $Label, FirePHP::ERROR); 
    427   }  
    428  
    429   /** 
    430    * Dumps key and variable to firebug server panel 
    431    * 
    432    * @see FirePHP::DUMP 
    433    * @param string $Key 
    434    * @param mixed $Variable 
    435    * @return true 
    436    * @throws Exception 
    437    */ 
    438   public function dump($Key, $Variable) { 
    439     return $this->fb($Variable, $Key, FirePHP::DUMP); 
    440   } 
    441    
    442   /** 
    443    * Log a trace in the firebug console 
    444    * 
    445    * @see FirePHP::TRACE 
    446    * @param string $Label 
    447    * @return true 
    448    * @throws Exception 
    449    */ 
    450   public function trace($Label) { 
    451     return $this->fb($Label, FirePHP::TRACE); 
    452   }  
    453  
    454   /** 
    455    * Log a table in the firebug console 
    456    * 
    457    * @see FirePHP::TABLE 
    458    * @param string $Label 
    459    * @param string $Table 
    460    * @return true 
    461    * @throws Exception 
    462    */ 
    463   public function table($Label, $Table) { 
    464     return $this->fb($Table, $Label, FirePHP::TABLE); 
    465   } 
    466    
    467   /** 
    468    * Check if FirePHP is installed on client 
    469    * 
    470    * @return boolean 
    471    */ 
    472   public function detectClientExtension() { 
    473     /* Check if FirePHP is installed on client */ 
    474     if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) || 
    475        !version_compare($m[1][0],'0.0.6','>=')) { 
    476       return false; 
    477     } 
    478     return true;     
    479   } 
    480   
    481   /** 
    482    * Log varible to Firebug 
    483    *  
    484    * @see http://www.firephp.org/Wiki/Reference/Fb 
    485    * @param mixed $Object The variable to be logged 
    486    * @return true Return TRUE if message was added to headers, FALSE otherwise 
    487    * @throws Exception 
    488    */ 
    489   public function fb($Object) { 
    490    
    491     if(!$this->enabled) { 
    492       return false; 
    493     } 
    494    
    495     if (headers_sent($filename, $linenum)) { 
    496         throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); 
    497     } 
    498    
    499     $Type = null; 
    500     $Label = null; 
    501    
    502     if(func_num_args()==1) { 
    503     } else 
    504     if(func_num_args()==2) { 
    505       switch(func_get_arg(1)) { 
    506         case self::LOG: 
    507         case self::INFO: 
    508         case self::WARN: 
    509         case self::ERROR: 
    510         case self::DUMP: 
    511         case self::TRACE: 
    512         case self::EXCEPTION: 
    513         case self::TABLE: 
    514         case self::GROUP_START: 
    515         case self::GROUP_END: 
    516           $Type = func_get_arg(1); 
    517           break; 
    518         default: 
    519           $Label = func_get_arg(1); 
    520           break; 
    521       } 
    522     } else 
    523     if(func_num_args()==3) { 
    524       $Type = func_get_arg(2); 
    525       $Label = func_get_arg(1); 
    526     } else { 
    527       throw $this->newException('Wrong number of arguments to fb() function!'); 
    528     } 
    529    
    530    
    531     if(!$this->detectClientExtension()) { 
    532       return false; 
    533     } 
    534    
    535     $meta = array(); 
    536     $skipFinalObjectEncode = false; 
    537    
    538     if($Object instanceof Exception) { 
    539  
    540       $meta['file'] = $this->_escapeTraceFile($Object->getFile()); 
    541       $meta['line'] = $Object->getLine(); 
     1181    /** 
     1182     * Encode an object into a JSON string 
     1183     *  
     1184     * Uses PHP's jeson_encode() if available 
     1185     *  
     1186     * @param object $Object The object to be encoded 
     1187     * @return string The JSON string 
     1188     */ 
     1189    public function jsonEncode($Object, $skipObjectEncode = false) 
     1190    { 
     1191        if (!$skipObjectEncode) { 
     1192            $Object = $this->encodeObject($Object); 
     1193        } 
     1194         
     1195        if (function_exists('json_encode') 
     1196           && $this->options['useNativeJsonEncode']!=false) { 
     1197     
     1198            return json_encode($Object); 
     1199        } else { 
     1200            return $this->json_encode($Object); 
     1201        } 
     1202    } 
     1203 
     1204    /** 
     1205     * Encodes a table by encoding each row and column with encodeObject() 
     1206     *  
     1207     * @param array $Table The table to be encoded 
     1208     * @return array 
     1209     */   
     1210    protected function encodeTable($Table) 
     1211    { 
     1212     
     1213        if (!$Table) return $Table; 
     1214         
     1215        $new_table = array(); 
     1216        foreach($Table as $row) { 
    5421217       
    543       $trace = $Object->getTrace(); 
    544       if($Object instanceof ErrorException 
    545          && isset($trace[0]['function']) 
    546          && $trace[0]['function']=='errorHandler' 
    547          && isset($trace[0]['class']) 
    548          && $trace[0]['class']=='FirePHP') { 
    549             
    550         $severity = false; 
    551         switch($Object->getSeverity()) { 
    552           case E_WARNING: $severity = 'E_WARNING'; break; 
    553           case E_NOTICE: $severity = 'E_NOTICE'; break; 
    554           case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; 
    555           case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; 
    556           case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; 
    557           case E_STRICT: $severity = 'E_STRICT'; break; 
    558           case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; 
    559           case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; 
    560           case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; 
    561         } 
    562             
    563         $Object = array('Class'=>get_class($Object), 
    564                         'Message'=>$severity.': '.$Object->getMessage(), 
    565                         'File'=>$this->_escapeTraceFile($Object->getFile()), 
    566                         'Line'=>$Object->getLine(), 
    567                         'Type'=>'trigger', 
    568                         'Trace'=>$this->_escapeTrace(array_splice($trace,2))); 
    569         $skipFinalObjectEncode = true; 
    570       } else { 
    571         $Object = array('Class'=>get_class($Object), 
    572                         'Message'=>$Object->getMessage(), 
    573                         'File'=>$this->_escapeTraceFile($Object->getFile()), 
    574                         'Line'=>$Object->getLine(), 
    575                         'Type'=>'throw', 
    576                         'Trace'=>$this->_escapeTrace($trace)); 
    577         $skipFinalObjectEncode = true; 
    578       } 
    579       $Type = self::EXCEPTION; 
    580        
    581     } else 
    582     if($Type==self::TRACE) { 
    583        
    584       $trace = debug_backtrace(); 
    585       if(!$trace) return false; 
    586       for( $i=0 ; $i<sizeof($trace) ; $i++ ) { 
    587  
    588         if(isset($trace[$i]['class']) 
    589            && isset($trace[$i]['file']) 
    590            && ($trace[$i]['class']=='FirePHP' 
    591                || $trace[$i]['class']=='FB') 
    592            && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' 
    593                || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { 
    594           /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ 
    595         } else 
    596         if(isset($trace[$i]['class']) 
    597            && isset($trace[$i+1]['file']) 
    598            && $trace[$i]['class']=='FirePHP' 
    599            && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { 
    600           /* Skip fb() */ 
    601         } else 
    602         if($trace[$i]['function']=='fb' 
    603            || $trace[$i]['function']=='trace' 
    604            || $trace[$i]['function']=='send') { 
    605           $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', 
    606                           'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', 
    607                           'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', 
    608                           'Message'=>$trace[$i]['args'][0], 
    609                           'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', 
    610                           'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', 
    611                           'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', 
    612                           'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); 
    613  
    614           $skipFinalObjectEncode = true; 
    615           $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; 
    616           $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; 
    617           break; 
    618         } 
    619       } 
    620  
    621     } else 
    622     if($Type==self::TABLE) { 
    623        
    624       if(isset($Object[0]) && is_string($Object[0])) { 
    625         $Object[1] = $this->encodeTable($Object[1]); 
    626       } else { 
    627         $Object = $this->encodeTable($Object); 
    628       } 
    629  
    630       $skipFinalObjectEncode = true; 
    631        
    632     } else { 
    633       if($Type===null) { 
    634         $Type = self::LOG; 
    635       } 
    636     } 
    637      
    638     if($this->options['includeLineNumbers']) { 
    639       if(!isset($meta['file']) || !isset($meta['line'])) { 
    640  
    641         $trace = debug_backtrace(); 
    642         for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) { 
    643    
    644           if(isset($trace[$i]['class']) 
    645              && isset($trace[$i]['file']) 
    646              && ($trace[$i]['class']=='FirePHP' 
    647                  || $trace[$i]['class']=='FB') 
    648              && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' 
    649                  || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { 
    650             /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ 
    651           } else 
    652           if(isset($trace[$i]['class']) 
    653              && isset($trace[$i+1]['file']) 
    654              && $trace[$i]['class']=='FirePHP' 
    655              && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { 
    656             /* Skip fb() */ 
    657           } else 
    658           if(isset($trace[$i]['file']) 
    659              && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { 
    660             /* Skip FB::fb() */ 
    661           } else { 
    662             $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; 
    663             $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; 
    664             break; 
    665           } 
    666         }       
    667        
    668       } 
    669     } else { 
    670       unset($meta['file']); 
    671       unset($meta['line']); 
    672     } 
    673  
    674     $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); 
    675     $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); 
    676   
    677     $structure_index = 1; 
    678     if($Type==self::DUMP) { 
    679       $structure_index = 2; 
    680         $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); 
    681     } else { 
    682         $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); 
    683     } 
    684    
    685     if($Type==self::DUMP) { 
    686         $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; 
    687     } else { 
    688       $msg_meta = array('Type'=>$Type); 
    689       if($Label!==null) { 
    690         $msg_meta['Label'] = $Label; 
    691       } 
    692       if(isset($meta['file'])) { 
    693         $msg_meta['File'] = $meta['file']; 
    694       } 
    695       if(isset($meta['line'])) { 
    696         $msg_meta['Line'] = $meta['line']; 
    697       } 
    698         $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; 
    699     } 
    700      
    701     $parts = explode("\n",chunk_split($msg, 5000, "\n")); 
    702  
    703     for( $i=0 ; $i<count($parts) ; $i++) { 
     1218            if (is_array($row)) { 
     1219                $new_row = array(); 
     1220             
     1221                foreach($row as $item) { 
     1222                    $new_row[] = $this->encodeObject($item); 
     1223                } 
     1224             
     1225                $new_table[] = $new_row; 
     1226            } 
     1227        } 
    7041228         
    705         $part = $parts[$i]; 
    706         if ($part) { 
     1229        return $new_table; 
     1230    } 
     1231 
     1232    /** 
     1233     * Encodes an object including members with 
     1234     * protected and private visibility 
     1235     *  
     1236     * @param Object $Object The object to be encoded 
     1237     * @param int $Depth The current traversal depth 
     1238     * @return array All members of the object 
     1239     */ 
     1240    protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $MaxDepth = 1) 
     1241    { 
     1242        if ($MaxDepth > $this->options['maxDepth']) { 
     1243            return '** Max Depth ('.$this->options['maxDepth'].') **'; 
     1244        } 
     1245 
     1246        $return = array(); 
     1247     
     1248        if (is_resource($Object)) { 
     1249     
     1250            return '** '.(string)$Object.' **'; 
     1251     
     1252        } else     
     1253        if (is_object($Object)) { 
     1254     
     1255            if ($ObjectDepth > $this->options['maxObjectDepth']) { 
     1256                return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; 
     1257            } 
    7071258             
    708             if(count($parts)>2) { 
    709               // Message needs to be split into multiple parts 
    710               $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, 
    711                                (($i==0)?strlen($msg):'') 
    712                                . '|' . $part . '|' 
    713                                . (($i<count($parts)-2)?'\\':'')); 
     1259            foreach ($this->objectStack as $refVal) { 
     1260                if ($refVal === $Object) { 
     1261                    return '** Recursion ('.get_class($Object).') **'; 
     1262                } 
     1263            } 
     1264            array_push($this->objectStack, $Object); 
     1265                     
     1266            $return['__className'] = $class = get_class($Object); 
     1267            $class_lower = strtolower($class); 
     1268     
     1269            $reflectionClass = new ReflectionClass($class);   
     1270            $properties = array(); 
     1271            foreach( $reflectionClass->getProperties() as $property) { 
     1272                $properties[$property->getName()] = $property; 
     1273            } 
     1274                 
     1275            $members = (array)$Object; 
     1276     
     1277            foreach( $properties as $plain_name => $property ) { 
     1278     
     1279                $name = $raw_name = $plain_name; 
     1280                if ($property->isStatic()) { 
     1281                    $name = 'static:'.$name; 
     1282                } 
     1283                if ($property->isPublic()) { 
     1284                    $name = 'public:'.$name; 
     1285                } else 
     1286                if ($property->isPrivate()) { 
     1287                    $name = 'private:'.$name; 
     1288                    $raw_name = "\0".$class."\0".$raw_name; 
     1289                } else 
     1290                if ($property->isProtected()) { 
     1291                    $name = 'protected:'.$name; 
     1292                    $raw_name = "\0".'*'."\0".$raw_name; 
     1293                } 
     1294     
     1295                if (!(isset($this->objectFilters[$class_lower]) 
     1296                     && is_array($this->objectFilters[$class_lower]) 
     1297                     && in_array($plain_name,$this->objectFilters[$class_lower]))) { 
     1298     
     1299                    if (array_key_exists($raw_name,$members) 
     1300                       && !$property->isStatic()) { 
     1301                   
     1302                        $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1, $MaxDepth + 1);       
     1303                 
     1304                    } else { 
     1305                        if (method_exists($property,'setAccessible')) { 
     1306                            $property->setAccessible(true); 
     1307                            $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1); 
     1308                        } else 
     1309                        if ($property->isPublic()) { 
     1310                            $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1); 
     1311                        } else { 
     1312                            $return[$name] = '** Need PHP 5.3 to get value **'; 
     1313                        } 
     1314                    } 
     1315                } else { 
     1316                    $return[$name] = '** Excluded by Filter **'; 
     1317                } 
     1318            } 
     1319             
     1320            // Include all members that are not defined in the class 
     1321            // but exist in the object 
     1322            foreach( $members as $raw_name => $value ) { 
     1323     
     1324                $name = $raw_name; 
     1325               
     1326                if ($name{0} == "\0") { 
     1327                    $parts = explode("\0", $name); 
     1328                    $name = $parts[2]; 
     1329                } 
     1330               
     1331                $plain_name = $name; 
     1332     
     1333                if (!isset($properties[$name])) { 
     1334                    $name = 'undeclared:'.$name; 
     1335     
     1336                    if (!(isset($this->objectFilters[$class_lower]) 
     1337                         && is_array($this->objectFilters[$class_lower]) 
     1338                         && in_array($plain_name,$this->objectFilters[$class_lower]))) { 
     1339     
     1340                        $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1, $MaxDepth + 1); 
     1341                    } else { 
     1342                        $return[$name] = '** Excluded by Filter **'; 
     1343                    } 
     1344                } 
     1345            } 
     1346             
     1347            array_pop($this->objectStack); 
     1348             
     1349        } elseif (is_array($Object)) { 
     1350     
     1351            if ($ArrayDepth > $this->options['maxArrayDepth']) { 
     1352                return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; 
     1353            } 
     1354           
     1355            foreach ($Object as $key => $val) { 
     1356               
     1357                // Encoding the $GLOBALS PHP array causes an infinite loop 
     1358                // if the recursion is not reset here as it contains 
     1359                // a reference to itself. This is the only way I have come up 
     1360                // with to stop infinite recursion in this case. 
     1361                if ($key=='GLOBALS' 
     1362                   && is_array($val) 
     1363                   && array_key_exists('GLOBALS',$val)) { 
     1364                    $val['GLOBALS'] = '** Recursion (GLOBALS) **'; 
     1365                } 
     1366               
     1367                $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1, $MaxDepth + 1); 
     1368            } 
     1369        } else { 
     1370            if (self::is_utf8($Object)) { 
     1371                return $Object; 
    7141372            } else { 
    715               $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, 
    716                                strlen($part) . '|' . $part . '|'); 
    717             } 
    718              
    719             $this->messageIndex++; 
    720              
    721             if ($this->messageIndex > 99999) { 
    722                 throw new Exception('Maximum number (99,999) of messages reached!');              
    723             } 
    724         } 
    725     } 
    726  
    727     $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); 
    728  
    729     return true; 
    730   } 
    731    
    732   /** 
    733    * Standardizes path for windows systems. 
    734    * 
    735    * @param string $Path 
    736    * @return string 
    737    */ 
    738   protected function _standardizePath($Path) { 
    739     return preg_replace('/\\\\+/','/',$Path);     
    740   } 
    741    
    742   /** 
    743    * Escape trace path for windows systems 
    744    * 
    745    * @param array $Trace 
    746    * @return array 
    747    */ 
    748   protected function _escapeTrace($Trace) { 
    749     if(!$Trace) return $Trace; 
    750     for( $i=0 ; $i<sizeof($Trace) ; $i++ ) { 
    751       if(isset($Trace[$i]['file'])) { 
    752         $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']); 
    753       } 
    754       if(isset($Trace[$i]['args'])) { 
    755         $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); 
    756       } 
    757     } 
    758     return $Trace;     
    759   } 
    760    
    761   /** 
    762    * Escape file information of trace for windows systems 
    763    * 
    764    * @param string $File 
    765    * @return string 
    766    */ 
    767   protected function _escapeTraceFile($File) { 
    768     /* Check if we have a windows filepath */ 
    769     if(strpos($File,'\\')) { 
    770       /* First strip down to single \ */ 
    771        
    772       $file = preg_replace('/\\\\+/','\\',$File); 
    773        
    774       return $file; 
    775     } 
    776     return $File; 
    777   } 
    778  
    779   /** 
    780    * Send header 
    781    * 
    782    * @param string $Name 
    783    * @param string_type $Value 
    784    */ 
    785   protected function setHeader($Name, $Value) { 
    786     return header($Name.': '.$Value); 
    787   } 
    788  
    789   /** 
    790    * Get user agent 
    791    * 
    792    * @return string|false 
    793    */ 
    794   protected function getUserAgent() { 
    795     if(!isset($_SERVER['HTTP_USER_AGENT'])) return false; 
    796     return $_SERVER['HTTP_USER_AGENT']; 
    797   } 
    798  
    799   /** 
    800    * Returns a new exception 
    801    * 
    802    * @param string $Message 
    803    * @return Exception 
    804    */ 
    805   protected function newException($Message) { 
    806     return new Exception($Message); 
    807   } 
    808    
    809   /** 
    810    * Encode an object into a JSON string 
    811    *  
    812    * Uses PHP's jeson_encode() if available 
    813    *  
    814    * @param object $Object The object to be encoded 
    815    * @return string The JSON string 
    816    */ 
    817   public function jsonEncode($Object, $skipObjectEncode=false) 
    818   { 
    819     if(!$skipObjectEncode) { 
    820       $Object = $this->encodeObject($Object); 
    821     } 
    822      
    823     if(function_exists('json_encode') 
    824        && $this->options['useNativeJsonEncode']!=false) { 
    825  
    826       return json_encode($Object); 
    827     } else { 
    828       return $this->json_encode($Object); 
    829     } 
    830   } 
    831    
    832   /** 
    833    * Encodes a table by encoding each row and column with encodeObject() 
    834    *  
    835    * @param array $Table The table to be encoded 
    836    * @return array 
    837    */   
    838   protected function encodeTable($Table) { 
    839     if(!$Table) return $Table; 
    840     for( $i=0 ; $i<count($Table) ; $i++ ) { 
    841       if(is_array($Table[$i])) { 
    842         for( $j=0 ; $j<count($Table[$i]) ; $j++ ) { 
    843           $Table[$i][$j] = $this->encodeObject($Table[$i][$j]); 
    844         } 
    845       } 
    846     } 
    847     return $Table; 
    848   } 
    849    
    850   /** 
    851    * Encodes an object including members with 
    852    * protected and private visibility 
    853    *  
    854    * @param Object $Object The object to be encoded 
    855    * @param int $Depth The current traversal depth 
    856    * @return array All members of the object 
    857    */ 
    858   protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1) 
    859   { 
    860     $return = array(); 
    861  
    862     if (is_resource($Object)) { 
    863  
    864       return '** '.(string)$Object.' **'; 
    865  
    866     } else     
    867     if (is_object($Object)) { 
    868  
    869         if ($ObjectDepth > $this->options['maxObjectDepth']) { 
    870           return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; 
    871         } 
    872          
    873         foreach ($this->objectStack as $refVal) { 
    874             if ($refVal === $Object) { 
    875                 return '** Recursion ('.get_class($Object).') **'; 
    876             } 
    877         } 
    878         array_push($this->objectStack, $Object); 
    879                  
    880         $return['__className'] = $class = get_class($Object); 
    881  
    882         $reflectionClass = new ReflectionClass($class);   
    883         $properties = array(); 
    884         foreach( $reflectionClass->getProperties() as $property) { 
    885           $properties[$property->getName()] = $property; 
    886         } 
    887              
    888         $members = (array)$Object; 
    889              
    890         foreach( $properties as $raw_name => $property ) { 
    891            
    892           $name = $raw_name; 
    893           if($property->isStatic()) { 
    894             $name = 'static:'.$name; 
    895           } 
    896           if($property->isPublic()) { 
    897             $name = 'public:'.$name; 
    898           } else 
    899           if($property->isPrivate()) { 
    900             $name = 'private:'.$name; 
    901             $raw_name = "\0".$class."\0".$raw_name; 
    902           } else 
    903           if($property->isProtected()) { 
    904             $name = 'protected:'.$name; 
    905             $raw_name = "\0".'*'."\0".$raw_name; 
    906           } 
    907            
    908           if(!(isset($this->objectFilters[$class]) 
    909                && is_array($this->objectFilters[$class]) 
    910                && in_array($raw_name,$this->objectFilters[$class]))) { 
    911  
    912             if(array_key_exists($raw_name,$members) 
    913                && !$property->isStatic()) { 
    914                
    915               $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1);       
    916              
    917             } else { 
    918               if(method_exists($property,'setAccessible')) { 
    919                 $property->setAccessible(true); 
    920                 $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); 
    921               } else 
    922               if($property->isPublic()) { 
    923                 $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); 
    924               } else { 
    925                 $return[$name] = '** Need PHP 5.3 to get value **'; 
    926               } 
    927             } 
    928           } else { 
    929             $return[$name] = '** Excluded by Filter **'; 
    930           } 
    931         } 
    932          
    933         // Include all members that are not defined in the class 
    934         // but exist in the object 
    935         foreach( $members as $raw_name => $value ) { 
    936            
    937           $name = $raw_name; 
    938            
    939           if ($name{0} == "\0") { 
    940             $parts = explode("\0", $name); 
    941             $name = $parts[2]; 
    942           } 
    943            
    944           if(!isset($properties[$name])) { 
    945             $name = 'undeclared:'.$name; 
    946                
    947             if(!(isset($this->objectFilters[$class]) 
    948                  && is_array($this->objectFilters[$class]) 
    949                  && in_array($raw_name,$this->objectFilters[$class]))) { 
    950                
    951               $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1); 
    952             } else { 
    953               $return[$name] = '** Excluded by Filter **'; 
    954             } 
    955           } 
    956         } 
    957          
    958         array_pop($this->objectStack); 
    959          
    960     } elseif (is_array($Object)) { 
    961  
    962         if ($ArrayDepth > $this->options['maxArrayDepth']) { 
    963           return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; 
    964         } 
    965        
    966         foreach ($Object as $key => $val) { 
    967            
    968           // Encoding the $GLOBALS PHP array causes an infinite loop 
    969           // if the recursion is not reset here as it contains 
    970           // a reference to itself. This is the only way I have come up 
    971           // with to stop infinite recursion in this case. 
    972           if($key=='GLOBALS' 
    973              && is_array($val) 
    974              && array_key_exists('GLOBALS',$val)) { 
    975             $val['GLOBALS'] = '** Recursion (GLOBALS) **'; 
    976           } 
    977            
    978           $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1); 
    979         } 
    980     } else { 
    981       if(self::is_utf8($Object)) { 
    982         return $Object; 
    983       } else { 
    984         return utf8_encode($Object); 
    985       } 
    986     } 
    987     return $return; 
    988   } 
    989  
    990   /** 
    991    * Returns true if $string is valid UTF-8 and false otherwise. 
    992    * 
    993    * @param mixed $str String to be tested 
    994    * @return boolean 
    995    */ 
    996   protected static function is_utf8($str) { 
    997     $c=0; $b=0; 
    998     $bits=0; 
    999     $len=strlen($str); 
    1000     for($i=0; $i<$len; $i++){ 
    1001         $c=ord($str[$i]); 
    1002         if($c > 128){ 
    1003             if(($c >= 254)) return false; 
    1004             elseif($c >= 252) $bits=6; 
    1005             elseif($c >= 248) $bits=5; 
    1006             elseif($c >= 240) $bits=4; 
    1007             elseif($c >= 224) $bits=3; 
    1008             elseif($c >= 192) $bits=2; 
    1009             else return false; 
    1010             if(($i+$bits) > $len) return false; 
    1011             while($bits > 1){ 
    1012                 $i++; 
    1013                 $b=ord($str[$i]); 
    1014                 if($b < 128 || $b > 191) return false; 
    1015                 $bits--; 
    1016             } 
    1017         } 
    1018     } 
    1019     return true; 
    1020   }  
    1021  
    1022   /** 
    1023    * Converts to and from JSON format. 
    1024    * 
    1025    * JSON (JavaScript Object Notation) is a lightweight data-interchange 
    1026    * format. It is easy for humans to read and write. It is easy for machines 
    1027    * to parse and generate. It is based on a subset of the JavaScript 
    1028    * Programming Language, Standard ECMA-262 3rd Edition - December 1999. 
    1029    * This feature can also be found in  Python. JSON is a text format that is 
    1030    * completely language independent but uses conventions that are familiar 
    1031    * to programmers of the C-family of languages, including C, C++, C#, Java, 
    1032    * JavaScript, Perl, TCL, and many others. These properties make JSON an 
    1033    * ideal data-interchange language. 
    1034    * 
    1035    * This package provides a simple encoder and decoder for JSON notation. It 
    1036    * is intended for use with client-side Javascript applications that make 
    1037    * use of HTTPRequest to perform server communication functions - data can 
    1038    * be encoded into JSON notation for use in a client-side javascript, or 
    1039    * decoded from incoming Javascript requests. JSON format is native to 
    1040    * Javascript, and can be directly eval()'ed with no further parsing 
    1041    * overhead 
    1042    * 
    1043    * All strings should be in ASCII or UTF-8 format! 
    1044    * 
    1045    * LICENSE: Redistribution and use in source and binary forms, with or 
    1046    * without modification, are permitted provided that the following 
    1047    * conditions are met: Redistributions of source code must retain the 
    1048    * above copyright notice, this list of conditions and the following 
    1049    * disclaimer. Redistributions in binary form must reproduce the above 
    1050    * copyright notice, this list of conditions and the following disclaimer 
    1051    * in the documentation and/or other materials provided with the 
    1052    * distribution. 
    1053    * 
    1054    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
    1055    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
    1056    * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 
    1057    * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
    1058    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
    1059    * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
    1060    * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
    1061    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
    1062    * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
    1063    * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
    1064    * DAMAGE. 
    1065    * 
    1066    * @category 
    1067    * @package     Services_JSON 
    1068    * @author      Michal Migurski <mike-json@teczno.com> 
    1069    * @author      Matt Knapp <mdknapp[at]gmail[dot]com> 
    1070    * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com> 
    1071    * @author      Christoph Dorn <christoph@christophdorn.com> 
    1072    * @copyright   2005 Michal Migurski 
    1073    * @version     CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ 
    1074    * @license     http://www.opensource.org/licenses/bsd-license.php 
    1075    * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198 
    1076    */ 
     1373                return utf8_encode($Object); 
     1374            } 
     1375        } 
     1376        return $return; 
     1377    } 
     1378 
     1379    /** 
     1380     * Returns true if $string is valid UTF-8 and false otherwise. 
     1381     * 
     1382     * @param mixed $str String to be tested 
     1383     * @return boolean 
     1384     */ 
     1385    protected static function is_utf8($str) 
     1386    { 
     1387        if(function_exists('mb_detect_encoding')) { 
     1388            return (mb_detect_encoding($str) == 'UTF-8'); 
     1389        } 
     1390        $c=0; $b=0; 
     1391        $bits=0; 
     1392        $len=strlen($str); 
     1393        for($i=0; $i<$len; $i++){ 
     1394            $c=ord($str[$i]); 
     1395            if ($c > 128){ 
     1396                if (($c >= 254)) return false; 
     1397                elseif ($c >= 252) $bits=6; 
     1398                elseif ($c >= 248) $bits=5; 
     1399                elseif ($c >= 240) $bits=4; 
     1400                elseif ($c >= 224) $bits=3; 
     1401                elseif ($c >= 192) $bits=2; 
     1402                else return false; 
     1403                if (($i+$bits) > $len) return false; 
     1404                while($bits > 1){ 
     1405                    $i++; 
     1406                    $b=ord($str[$i]); 
     1407                    if ($b < 128 || $b > 191) return false; 
     1408                    $bits--; 
     1409                } 
     1410            } 
     1411        } 
     1412        return true; 
     1413    }  
     1414 
     1415    /** 
     1416     * Converts to and from JSON format. 
     1417     * 
     1418     * JSON (JavaScript Object Notation) is a lightweight data-interchange 
     1419     * format. It is easy for humans to read and write. It is easy for machines 
     1420     * to parse and generate. It is based on a subset of the JavaScript 
     1421     * Programming Language, Standard ECMA-262 3rd Edition - December 1999. 
     1422     * This feature can also be found in  Python. JSON is a text format that is 
     1423     * completely language independent but uses conventions that are familiar 
     1424     * to programmers of the C-family of languages, including C, C++, C#, Java, 
     1425     * JavaScript, Perl, TCL, and many others. These properties make JSON an 
     1426     * ideal data-interchange language. 
     1427     * 
     1428     * This package provides a simple encoder and decoder for JSON notation. It 
     1429     * is intended for use with client-side Javascript applications that make 
     1430     * use of HTTPRequest to perform server communication functions - data can 
     1431     * be encoded into JSON notation for use in a client-side javascript, or 
     1432     * decoded from incoming Javascript requests. JSON format is native to 
     1433     * Javascript, and can be directly eval()'ed with no further parsing 
     1434     * overhead 
     1435     * 
     1436     * All strings should be in ASCII or UTF-8 format! 
     1437     * 
     1438     * LICENSE: Redistribution and use in source and binary forms, with or 
     1439     * without modification, are permitted provided that the following 
     1440     * conditions are met: Redistributions of source code must retain the 
     1441     * above copyright notice, this list of conditions and the following 
     1442     * disclaimer. Redistributions in binary form must reproduce the above 
     1443     * copyright notice, this list of conditions and the following disclaimer 
     1444     * in the documentation and/or other materials provided with the 
     1445     * distribution. 
     1446     * 
     1447     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
     1448     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
     1449     * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 
     1450     * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
     1451     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
     1452     * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
     1453     * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
     1454     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
     1455     * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
     1456     * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
     1457     * DAMAGE. 
     1458     * 
     1459     * @category 
     1460     * @package     Services_JSON 
     1461     * @author      Michal Migurski <mike-json@teczno.com> 
     1462     * @author      Matt Knapp <mdknapp[at]gmail[dot]com> 
     1463     * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com> 
     1464     * @author      Christoph Dorn <christoph@christophdorn.com> 
     1465     * @copyright   2005 Michal Migurski 
     1466     * @version     CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ 
     1467     * @license     http://www.opensource.org/licenses/bsd-license.php 
     1468     * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198 
     1469     */ 
    10771470    
    10781471      
    1079   /** 
    1080    * Keep a list of objects as we descend into the array so we can detect recursion. 
    1081    */ 
    1082   private $json_objectStack = array(); 
    1083  
    1084  
    1085  /** 
    1086   * convert a string from one UTF-8 char to one UTF-16 char 
    1087   * 
    1088   * Normally should be handled by mb_convert_encoding, but 
    1089   * provides a slower PHP-only method for installations 
    1090   * that lack the multibye string extension. 
    1091   * 
    1092   * @param    string  $utf8   UTF-8 character 
    1093   * @return   string  UTF-16 character 
    1094   * @access   private 
    1095   */ 
    1096   private function json_utf82utf16($utf8) 
    1097   { 
    1098       // oh please oh please oh please oh please oh please 
    1099       if(function_exists('mb_convert_encoding')) { 
    1100           return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); 
    1101       } 
    1102  
    1103       switch(strlen($utf8)) { 
    1104           case 1: 
    1105               // this case should never be reached, because we are in ASCII range 
    1106               // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1107               return $utf8; 
    1108  
    1109           case 2: 
    1110               // return a UTF-16 character from a 2-byte UTF-8 char 
    1111               // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1112               return chr(0x07 & (ord($utf8{0}) >> 2)) 
    1113                    . chr((0xC0 & (ord($utf8{0}) << 6)) 
     1472    /** 
     1473     * Keep a list of objects as we descend into the array so we can detect recursion. 
     1474     */ 
     1475    private $json_objectStack = array(); 
     1476 
     1477 
     1478   /** 
     1479    * convert a string from one UTF-8 char to one UTF-16 char 
     1480    * 
     1481    * Normally should be handled by mb_convert_encoding, but 
     1482    * provides a slower PHP-only method for installations 
     1483    * that lack the multibye string extension. 
     1484    * 
     1485    * @param    string  $utf8   UTF-8 character 
     1486    * @return   string  UTF-16 character 
     1487    * @access   private 
     1488    */ 
     1489    private function json_utf82utf16($utf8) 
     1490    { 
     1491        // oh please oh please oh please oh please oh please 
     1492        if (function_exists('mb_convert_encoding')) { 
     1493            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); 
     1494        } 
     1495 
     1496        switch(strlen($utf8)) { 
     1497            case 1: 
     1498                // this case should never be reached, because we are in ASCII range 
     1499                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1500                return $utf8; 
     1501 
     1502            case 2: 
     1503                // return a UTF-16 character from a 2-byte UTF-8 char 
     1504                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1505                return chr(0x07 & (ord($utf8{0}) >> 2)) 
     1506                       . chr((0xC0 & (ord($utf8{0}) << 6)) 
    11141507                       | (0x3F & ord($utf8{1}))); 
    11151508 
    1116           case 3: 
    1117               // return a UTF-16 character from a 3-byte UTF-8 char 
    1118               // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1119               return chr((0xF0 & (ord($utf8{0}) << 4)) 
     1509            case 3: 
     1510                // return a UTF-16 character from a 3-byte UTF-8 char 
     1511                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1512                return chr((0xF0 & (ord($utf8{0}) << 4)) 
    11201513                       | (0x0F & (ord($utf8{1}) >> 2))) 
    1121                    . chr((0xC0 & (ord($utf8{1}) << 6)) 
     1514                       . chr((0xC0 & (ord($utf8{1}) << 6)) 
    11221515                       | (0x7F & ord($utf8{2}))); 
    1123       } 
    1124  
    1125       // ignoring UTF-32 for now, sorry 
    1126       return ''; 
    1127   } 
    1128  
    1129  /** 
    1130   * encodes an arbitrary variable into JSON format 
    1131   * 
    1132   * @param    mixed   $var    any number, boolean, string, array, or object to be encoded. 
    1133   *                           see argument 1 to Services_JSON() above for array-parsing behavior. 
    1134   *                           if var is a strng, note that encode() always expects it 
    1135   *                           to be in ASCII or UTF-8 format! 
    1136   * 
    1137   * @return   mixed   JSON string representation of input var or an error if a problem occurs 
    1138   * @access   public 
    1139   */ 
    1140   private function json_encode($var) 
    1141   { 
    1142      
    1143     if(is_object($var)) { 
    1144       if(in_array($var,$this->json_objectStack)) { 
    1145         return '"** Recursion **"'; 
    1146       } 
    1147     } 
     1516        } 
     1517 
     1518        // ignoring UTF-32 for now, sorry 
     1519        return ''; 
     1520    } 
     1521 
     1522   /** 
     1523    * encodes an arbitrary variable into JSON format 
     1524    * 
     1525    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded. 
     1526    *                           see argument 1 to Services_JSON() above for array-parsing behavior. 
     1527    *                           if var is a strng, note that encode() always expects it 
     1528    *                           to be in ASCII or UTF-8 format! 
     1529    * 
     1530    * @return   mixed   JSON string representation of input var or an error if a problem occurs 
     1531    * @access   public 
     1532    */ 
     1533    private function json_encode($var) 
     1534    { 
     1535     
     1536        if (is_object($var)) { 
     1537            if (in_array($var,$this->json_objectStack)) { 
     1538                return '"** Recursion **"'; 
     1539            } 
     1540        } 
    11481541           
    1149       switch (gettype($var)) { 
    1150           case 'boolean': 
    1151               return $var ? 'true' : 'false'; 
    1152  
    1153           case 'NULL': 
    1154               return 'null'; 
    1155  
    1156           case 'integer': 
    1157               return (int) $var; 
    1158  
    1159           case 'double': 
    1160           case 'float': 
    1161               return (float) $var; 
    1162  
    1163           case 'string': 
    1164               // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT 
    1165               $ascii = ''; 
    1166               $strlen_var = strlen($var); 
    1167  
    1168              /* 
    1169               * Iterate over every character in the string, 
    1170               * escaping with a slash or encoding to UTF-8 where necessary 
    1171               */ 
    1172               for ($c = 0; $c < $strlen_var; ++$c) { 
    1173  
    1174                   $ord_var_c = ord($var{$c}); 
    1175  
    1176                   switch (true) { 
    1177                       case $ord_var_c == 0x08: 
    1178                           $ascii .= '\b'; 
    1179                           break; 
    1180                       case $ord_var_c == 0x09: 
    1181                           $ascii .= '\t'; 
    1182                           break; 
    1183                       case $ord_var_c == 0x0A: 
    1184                           $ascii .= '\n'; 
    1185                           break; 
    1186                       case $ord_var_c == 0x0C: 
    1187                           $ascii .= '\f'; 
    1188                           break; 
    1189                       case $ord_var_c == 0x0D: 
    1190                           $ascii .= '\r'; 
    1191                           break; 
    1192  
    1193                       case $ord_var_c == 0x22: 
    1194                       case $ord_var_c == 0x2F: 
    1195                       case $ord_var_c == 0x5C: 
    1196                           // double quote, slash, slosh 
    1197                           $ascii .= '\\'.$var{$c}; 
    1198                           break; 
    1199  
    1200                       case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): 
    1201                           // characters U-00000000 - U-0000007F (same as ASCII) 
    1202                           $ascii .= $var{$c}; 
    1203                           break; 
    1204  
    1205                       case (($ord_var_c & 0xE0) == 0xC0): 
    1206                           // characters U-00000080 - U-000007FF, mask 110XXXXX 
    1207                           // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1208                           $char = pack('C*', $ord_var_c, ord($var{$c + 1})); 
    1209                           $c += 1; 
    1210                           $utf16 = $this->json_utf82utf16($char); 
    1211                           $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
    1212                           break; 
    1213  
    1214                       case (($ord_var_c & 0xF0) == 0xE0): 
    1215                           // characters U-00000800 - U-0000FFFF, mask 1110XXXX 
    1216                           // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1217                           $char = pack('C*', $ord_var_c, 
    1218                                        ord($var{$c + 1}), 
    1219                                        ord($var{$c + 2})); 
    1220                           $c += 2; 
    1221                           $utf16 = $this->json_utf82utf16($char); 
    1222                           $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
    1223                           break; 
    1224  
    1225                       case (($ord_var_c & 0xF8) == 0xF0): 
    1226                           // characters U-00010000 - U-001FFFFF, mask 11110XXX 
    1227                           // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1228                           $char = pack('C*', $ord_var_c, 
    1229                                        ord($var{$c + 1}), 
    1230                                        ord($var{$c + 2}), 
    1231                                        ord($var{$c + 3})); 
    1232                           $c += 3; 
    1233                           $utf16 = $this->json_utf82utf16($char); 
    1234                           $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
    1235                           break; 
    1236  
    1237                       case (($ord_var_c & 0xFC) == 0xF8): 
    1238                           // characters U-00200000 - U-03FFFFFF, mask 111110XX 
    1239                           // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1240                           $char = pack('C*', $ord_var_c, 
    1241                                        ord($var{$c + 1}), 
    1242                                        ord($var{$c + 2}), 
    1243                                        ord($var{$c + 3}), 
    1244                                        ord($var{$c + 4})); 
    1245                           $c += 4; 
    1246                           $utf16 = $this->json_utf82utf16($char); 
    1247                           $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
    1248                           break; 
    1249  
    1250                       case (($ord_var_c & 0xFE) == 0xFC): 
    1251                           // characters U-04000000 - U-7FFFFFFF, mask 1111110X 
    1252                           // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
    1253                           $char = pack('C*', $ord_var_c, 
    1254                                        ord($var{$c + 1}), 
    1255                                        ord($var{$c + 2}), 
    1256                                        ord($var{$c + 3}), 
    1257                                        ord($var{$c + 4}), 
    1258                                        ord($var{$c + 5})); 
    1259                           $c += 5; 
    1260                           $utf16 = $this->json_utf82utf16($char); 
    1261                           $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
    1262                           break; 
    1263                   } 
    1264               } 
    1265  
    1266               return '"'.$ascii.'"'; 
    1267  
    1268           case 'array': 
    1269              /* 
    1270               * As per JSON spec if any array key is not an integer 
    1271               * we must treat the the whole array as an object. We 
    1272               * also try to catch a sparsely populated associative 
    1273               * array with numeric keys here because some JS engines 
    1274               * will create an array with empty indexes up to 
    1275               * max_index which can cause memory issues and because 
    1276               * the keys, which may be relevant, will be remapped 
    1277               * otherwise. 
    1278               * 
    1279               * As per the ECMA and JSON specification an object may 
    1280               * have any string as a property. Unfortunately due to 
    1281               * a hole in the ECMA specification if the key is a 
    1282               * ECMA reserved word or starts with a digit the 
    1283               * parameter is only accessible using ECMAScript's 
    1284               * bracket notation. 
    1285               */ 
    1286  
    1287               // treat as a JSON object 
    1288               if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { 
     1542        switch (gettype($var)) { 
     1543            case 'boolean': 
     1544                return $var ? 'true' : 'false'; 
     1545 
     1546            case 'NULL': 
     1547                return 'null'; 
     1548 
     1549            case 'integer': 
     1550                return (int) $var; 
     1551 
     1552            case 'double': 
     1553            case 'float': 
     1554                return (float) $var; 
     1555 
     1556            case 'string': 
     1557                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT 
     1558                $ascii = ''; 
     1559                $strlen_var = strlen($var); 
     1560 
     1561               /* 
     1562                * Iterate over every character in the string, 
     1563                * escaping with a slash or encoding to UTF-8 where necessary 
     1564                */ 
     1565                for ($c = 0; $c < $strlen_var; ++$c) { 
     1566 
     1567                    $ord_var_c = ord($var{$c}); 
     1568 
     1569                    switch (true) { 
     1570                        case $ord_var_c == 0x08: 
     1571                            $ascii .= '\b'; 
     1572                            break; 
     1573                        case $ord_var_c == 0x09: 
     1574                            $ascii .= '\t'; 
     1575                            break; 
     1576                        case $ord_var_c == 0x0A: 
     1577                            $ascii .= '\n'; 
     1578                            break; 
     1579                        case $ord_var_c == 0x0C: 
     1580                            $ascii .= '\f'; 
     1581                            break; 
     1582                        case $ord_var_c == 0x0D: 
     1583                            $ascii .= '\r'; 
     1584                            break; 
     1585 
     1586                        case $ord_var_c == 0x22: 
     1587                        case $ord_var_c == 0x2F: 
     1588                        case $ord_var_c == 0x5C: 
     1589                            // double quote, slash, slosh 
     1590                            $ascii .= '\\'.$var{$c}; 
     1591                            break; 
     1592 
     1593                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): 
     1594                            // characters U-00000000 - U-0000007F (same as ASCII) 
     1595                            $ascii .= $var{$c}; 
     1596                            break; 
     1597 
     1598                        case (($ord_var_c & 0xE0) == 0xC0): 
     1599                            // characters U-00000080 - U-000007FF, mask 110XXXXX 
     1600                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1601                            $char = pack('C*', $ord_var_c, ord($var{$c + 1})); 
     1602                            $c += 1; 
     1603                            $utf16 = $this->json_utf82utf16($char); 
     1604                            $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
     1605                            break; 
     1606 
     1607                        case (($ord_var_c & 0xF0) == 0xE0): 
     1608                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX 
     1609                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1610                            $char = pack('C*', $ord_var_c, 
     1611                                         ord($var{$c + 1}), 
     1612                                         ord($var{$c + 2})); 
     1613                            $c += 2; 
     1614                            $utf16 = $this->json_utf82utf16($char); 
     1615                            $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
     1616                            break; 
     1617 
     1618                        case (($ord_var_c & 0xF8) == 0xF0): 
     1619                            // characters U-00010000 - U-001FFFFF, mask 11110XXX 
     1620                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1621                            $char = pack('C*', $ord_var_c, 
     1622                                         ord($var{$c + 1}), 
     1623                                         ord($var{$c + 2}), 
     1624                                         ord($var{$c + 3})); 
     1625                            $c += 3; 
     1626                            $utf16 = $this->json_utf82utf16($char); 
     1627                            $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
     1628                            break; 
     1629 
     1630                        case (($ord_var_c & 0xFC) == 0xF8): 
     1631                            // characters U-00200000 - U-03FFFFFF, mask 111110XX 
     1632                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1633                            $char = pack('C*', $ord_var_c, 
     1634                                         ord($var{$c + 1}), 
     1635                                         ord($var{$c + 2}), 
     1636                                         ord($var{$c + 3}), 
     1637                                         ord($var{$c + 4})); 
     1638                            $c += 4; 
     1639                            $utf16 = $this->json_utf82utf16($char); 
     1640                            $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
     1641                            break; 
     1642 
     1643                        case (($ord_var_c & 0xFE) == 0xFC): 
     1644                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X 
     1645                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 
     1646                            $char = pack('C*', $ord_var_c, 
     1647                                         ord($var{$c + 1}), 
     1648                                         ord($var{$c + 2}), 
     1649                                         ord($var{$c + 3}), 
     1650                                         ord($var{$c + 4}), 
     1651                                         ord($var{$c + 5})); 
     1652                            $c += 5; 
     1653                            $utf16 = $this->json_utf82utf16($char); 
     1654                            $ascii .= sprintf('\u%04s', bin2hex($utf16)); 
     1655                            break; 
     1656                    } 
     1657                } 
     1658 
     1659                return '"'.$ascii.'"'; 
     1660 
     1661            case 'array': 
     1662                /* 
     1663                 * As per JSON spec if any array key is not an integer 
     1664                 * we must treat the the whole array as an object. We 
     1665                 * also try to catch a sparsely populated associative 
     1666                 * array with numeric keys here because some JS engines 
     1667                 * will create an array with empty indexes up to 
     1668                 * max_index which can cause memory issues and because 
     1669                 * the keys, which may be relevant, will be remapped 
     1670                 * otherwise. 
     1671                 * 
     1672                 * As per the ECMA and JSON specification an object may 
     1673                 * have any string as a property. Unfortunately due to 
     1674                 * a hole in the ECMA specification if the key is a 
     1675                 * ECMA reserved word or starts with a digit the 
     1676                 * parameter is only accessible using ECMAScript's 
     1677                 * bracket notation. 
     1678                 */ 
     1679 
     1680                // treat as a JSON object 
     1681                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { 
    12891682                   
    1290                   $this->json_objectStack[] = $var; 
    1291  
    1292                   $properties = array_map(array($this, 'json_name_value'), 
    1293                                           array_keys($var), 
    1294                                           array_values($var)); 
    1295  
    1296                   array_pop($this->json_objectStack); 
    1297  
    1298                   foreach($properties as $property) { 
    1299                       if($property instanceof Exception) { 
    1300                           return $property; 
    1301                       } 
    1302                   } 
    1303  
    1304                   return '{' . join(',', $properties) . '}'; 
    1305               } 
    1306  
    1307               $this->json_objectStack[] = $var; 
    1308  
    1309               // treat it like a regular array 
    1310               $elements = array_map(array($this, 'json_encode'), $var); 
    1311  
    1312               array_pop($this->json_objectStack); 
    1313  
    1314               foreach($elements as $element) { 
    1315                   if($element instanceof Exception) { 
    1316                       return $element; 
    1317                   } 
    1318               } 
    1319  
    1320               return '[' . join(',', $elements) . ']'; 
    1321  
    1322           case 'object': 
    1323               $vars = self::encodeObject($var); 
    1324  
    1325               $this->json_objectStack[] = $var; 
    1326  
    1327               $properties = array_map(array($this, 'json_name_value'), 
    1328                                       array_keys($vars), 
    1329                                       array_values($vars)); 
    1330  
    1331               array_pop($this->json_objectStack); 
     1683                    $this->json_objectStack[] = $var; 
     1684 
     1685                    $properties = array_map(array($this, 'json_name_value'), 
     1686                                            array_keys($var), 
     1687                                            array_values($var)); 
     1688 
     1689                    array_pop($this->json_objectStack); 
     1690 
     1691                    foreach($properties as $property) { 
     1692                        if ($property instanceof Exception) { 
     1693                            return $property; 
     1694                        } 
     1695                    } 
     1696 
     1697                    return '{' . join(',', $properties) . '}'; 
     1698                } 
     1699 
     1700                $this->json_objectStack[] = $var; 
     1701 
     1702                // treat it like a regular array 
     1703                $elements = array_map(array($this, 'json_encode'), $var); 
     1704 
     1705                array_pop($this->json_objectStack); 
     1706 
     1707                foreach($elements as $element) { 
     1708                    if ($element instanceof Exception) { 
     1709                        return $element; 
     1710                    } 
     1711                } 
     1712 
     1713                return '[' . join(',', $elements) . ']'; 
     1714 
     1715            case 'object': 
     1716                $vars = self::encodeObject($var); 
     1717 
     1718                $this->json_objectStack[] = $var; 
     1719 
     1720                $properties = array_map(array($this, 'json_name_value'), 
     1721                                        array_keys($vars), 
     1722                                        array_values($vars)); 
     1723 
     1724                array_pop($this->json_objectStack); 
    13321725               
    1333               foreach($properties as $property) { 
    1334                   if($property instanceof Exception) { 
    1335                       return $property; 
    1336                   } 
    1337               } 
     1726                foreach($properties as $property) { 
     1727                    if ($property instanceof Exception) { 
     1728                        return $property; 
     1729                    } 
     1730                } 
    13381731                      
    1339               return '{' . join(',', $properties) . '}'; 
    1340  
    1341           default: 
    1342               return null; 
    1343       } 
    1344   } 
    1345  
    1346  /** 
    1347   * array-walking function for use in generating JSON-formatted name-value pairs 
    1348   * 
    1349   * @param    string  $name   name of key to use 
    1350   * @param    mixed   $value  reference to an array element to be encoded 
    1351   * 
    1352   * @return   string  JSON-formatted name-value pair, like '"name":value' 
    1353   * @access   private 
    1354   */ 
    1355   private function json_name_value($name, $value) 
    1356   { 
    1357       // Encoding the $GLOBALS PHP array causes an infinite loop 
    1358       // if the recursion is not reset here as it contains 
    1359       // a reference to itself. This is the only way I have come up 
    1360       // with to stop infinite recursion in this case. 
    1361       if($name=='GLOBALS' 
    1362          && is_array($value) 
    1363          && array_key_exists('GLOBALS',$value)) { 
    1364         $value['GLOBALS'] = '** Recursion **'; 
    1365       } 
    1366      
    1367       $encoded_value = $this->json_encode($value); 
    1368  
    1369       if($encoded_value instanceof Exception) { 
    1370           return $encoded_value; 
    1371       } 
    1372  
    1373       return $this->json_encode(strval($name)) . ':' . $encoded_value; 
    1374   } 
     1732                return '{' . join(',', $properties) . '}'; 
     1733 
     1734            default: 
     1735                return null; 
     1736        } 
     1737    } 
     1738 
     1739   /** 
     1740    * array-walking function for use in generating JSON-formatted name-value pairs 
     1741    * 
     1742    * @param    string  $name   name of key to use 
     1743    * @param    mixed   $value  reference to an array element to be encoded 
     1744    * 
     1745    * @return   string  JSON-formatted name-value pair, like '"name":value' 
     1746    * @access   private 
     1747    */ 
     1748    private function json_name_value($name, $value) 
     1749    { 
     1750        // Encoding the $GLOBALS PHP array causes an infinite loop 
     1751        // if the recursion is not reset here as it contains 
     1752        // a reference to itself. This is the only way I have come up 
     1753        // with to stop infinite recursion in this case. 
     1754        if ($name=='GLOBALS' 
     1755           && is_array($value) 
     1756           && array_key_exists('GLOBALS',$value)) { 
     1757            $value['GLOBALS'] = '** Recursion **'; 
     1758        } 
     1759     
     1760        $encoded_value = $this->json_encode($value); 
     1761 
     1762        if ($encoded_value instanceof Exception) { 
     1763            return $encoded_value; 
     1764        } 
     1765 
     1766        return $this->json_encode(strval($name)) . ':' . $encoded_value; 
     1767    } 
     1768 
     1769    /** 
     1770     * @deprecated 
     1771     */     
     1772    public function setProcessorUrl($URL) 
     1773    { 
     1774        trigger_error("The FirePHP::setProcessorUrl() method is no longer supported", E_USER_DEPRECATED); 
     1775    } 
     1776 
     1777    /** 
     1778     * @deprecated 
     1779     */ 
     1780    public function setRendererUrl($URL) 
     1781    { 
     1782        trigger_error("The FirePHP::setRendererUrl() method is no longer supported", E_USER_DEPRECATED); 
     1783    }   
    13751784} 
  • trunk/plugins/firephp/LICENSE

    r8795 r14725  
    11Software License Agreement (New BSD License) 
    22 
    3 Copyright (c) 2006-2008, Christoph Dorn 
     3Copyright (c) 2006-2009, Christoph Dorn 
    44All rights reserved. 
    55 
  • trunk/plugins/firephp/fb.php

    r13492 r14725  
    77 * Software License Agreement (New BSD License) 
    88 *  
    9  * Copyright (c) 2006-2008, Christoph Dorn 
     9 * Copyright (c) 2006-2010, Christoph Dorn 
    1010 * All rights reserved. 
    1111 *  
     
    3737 * ***** END LICENSE BLOCK ***** 
    3838 *  
    39  * @copyright   Copyright (C) 2007-2008 Christoph Dorn 
     39 * @copyright   Copyright (C) 2007-2009 Christoph Dorn 
    4040 * @author      Christoph Dorn <christoph@christophdorn.com> 
    4141 * @license     http://www.opensource.org/licenses/bsd-license.php 
    42  * @package     FirePHP 
     42 * @package     FirePHPCore 
    4343 */ 
    4444 
    45 require_once dirname(__FILE__).'/FirePHP.class.php'; 
     45if(!class_exists('FirePHP')) { 
     46    require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'FirePHP.class.php'; 
     47} 
    4648 
    4749/** 
     
    5759function fb() 
    5860{ 
    59     $mixedRet = false; 
    60  
    61     try { 
    62  
    63         $instance = FirePHP::getInstance(true); 
    64    
    65         $args = func_get_args(); 
    66         $mixedRet = call_user_func_array(array($instance,'fb'),$args); 
    67  
    68     } catch (Exception $e) { 
    69         //echo 'Caught exception: ',  $e->getMessage(), "\n"; 
    70     } 
    71  
    72     return $mixedRet; 
     61    $instance = FirePHP::getInstance(true); 
     62   
     63    $args = func_get_args(); 
     64    return call_user_func_array(array($instance,'fb'),$args); 
    7365} 
    7466 
     
    7668class FB 
    7769{ 
    78   /** 
    79    * Enable and disable logging to Firebug 
    80    *  
    81    * @see FirePHP->setEnabled() 
    82    * @param boolean $Enabled TRUE to enable, FALSE to disable 
    83    * @return void 
    84    */ 
    85   public static function setEnabled($Enabled) { 
    86     $instance = FirePHP::getInstance(true); 
    87     $instance->setEnabled($Enabled); 
    88   } 
    89    
    90   /** 
    91    * Check if logging is enabled 
    92    *  
    93    * @see FirePHP->getEnabled() 
    94    * @return boolean TRUE if enabled 
    95    */ 
    96   public static function getEnabled() { 
    97     $instance = FirePHP::getInstance(true); 
    98     return $instance->getEnabled(); 
    99   }   
    100    
    101   /** 
    102    * Specify a filter to be used when encoding an object 
    103    *  
    104    * Filters are used to exclude object members. 
    105    *  
    106    * @see FirePHP->setObjectFilter() 
    107    * @param string $Class The class name of the object 
    108    * @param array $Filter An array or members to exclude 
    109    * @return void 
    110    */ 
    111   public static function setObjectFilter($Class, $Filter) { 
    112     $instance = FirePHP::getInstance(true); 
    113     $instance->setObjectFilter($Class, $Filter); 
    114   } 
    115    
    116   /** 
    117    * Set some options for the library 
    118    *  
    119    * @see FirePHP->setOptions() 
    120    * @param array $Options The options to be set 
    121    * @return void 
    122    */ 
    123   public static function setOptions($Options) { 
    124     $instance = FirePHP::getInstance(true); 
    125     $instance->setOptions($Options); 
    126   } 
    127  
    128   /** 
    129    * Log object to firebug 
    130    *  
    131    * @see http://www.firephp.org/Wiki/Reference/Fb 
    132    * @param mixed $Object 
    133    * @return true 
    134    * @throws Exception 
    135    */ 
    136   public static function send() 
    137   { 
    138     $instance = FirePHP::getInstance(true); 
    139     $args = func_get_args(); 
    140     return call_user_func_array(array($instance,'fb'),$args); 
    141   } 
    142  
    143   /** 
    144    * Start a group for following messages 
    145    * 
    146    * @param string $Name 
    147    * @return true 
    148    * @throws Exception 
    149    */ 
    150   public static function group($Name) { 
    151     return self::send(null, $Name, FirePHP::GROUP_START); 
    152   } 
    153    
    154   /** 
    155    * Ends a group you have started before 
    156    * 
    157    * @return true 
    158    * @throws Exception 
    159    */ 
    160   public static function groupEnd() { 
    161     return self::send(null, null, FirePHP::GROUP_END); 
    162   } 
    163  
    164   /** 
    165    * Log object with label to firebug console 
    166    * 
    167    * @see FirePHP::LOG 
    168    * @param mixes $Object 
    169    * @param string $Label 
    170    * @return true 
    171    * @throws Exception 
    172    */ 
    173   public static function log($Object, $Label=null) { 
    174     return self::send($Object, $Label, FirePHP::LOG); 
    175   }  
    176  
    177   /** 
    178    * Log object with label to firebug console 
    179    * 
    180    * @see FirePHP::INFO 
    181    * @param mixes $Object 
    182    * @param string $Label 
    183    * @return true 
    184    * @throws Exception 
    185    */ 
    186   public static function info($Object, $Label=null) { 
    187     return self::send($Object, $Label, FirePHP::INFO); 
    188   }  
    189  
    190   /** 
    191    * Log object with label to firebug console 
    192    * 
    193    * @see FirePHP::WARN 
    194    * @param mixes $Object 
    195    * @param string $Label 
    196    * @return true 
    197    * @throws Exception 
    198    */ 
    199   public static function warn($Object, $Label=null) { 
    200     return self::send($Object, $Label, FirePHP::WARN); 
    201   }  
    202  
    203   /** 
    204    * Log object with label to firebug console 
    205    * 
    206    * @see FirePHP::ERROR 
    207    * @param mixes $Object 
    208    * @param string $Label 
    209    * @return true 
    210    * @throws Exception 
    211    */ 
    212   public static function error($Object, $Label=null) { 
    213     return self::send($Object, $Label, FirePHP::ERROR); 
    214   }  
    215  
    216   /** 
    217    * Dumps key and variable to firebug server panel 
    218    * 
    219    * @see FirePHP::DUMP 
    220    * @param string $Key 
    221    * @param mixed $Variable 
    222    * @return true 
    223    * @throws Exception 
    224    */ 
    225   public static function dump($Key, $Variable) { 
    226     return self::send($Variable, $Key, FirePHP::DUMP); 
    227   }  
    228  
    229   /** 
    230    * Log a trace in the firebug console 
    231    * 
    232    * @see FirePHP::TRACE 
    233    * @param string $Label 
    234    * @return true 
    235    * @throws Exception 
    236    */ 
    237   public static function trace($Label) { 
    238     return self::send($Label, FirePHP::TRACE); 
    239   }  
    240  
    241   /** 
    242    * Log a table in the firebug console 
    243    * 
    244    * @see FirePHP::TABLE 
    245    * @param string $Label 
    246    * @param string $Table 
    247    * @return true 
    248    * @throws Exception 
    249    */ 
    250   public static function table($Label, $Table) { 
    251     return self::send($Table, $Label, FirePHP::TABLE); 
    252   }  
     70    /** 
     71     * Enable and disable logging to Firebug 
     72     *  
     73     * @see FirePHP->setEnabled() 
     74     * @param boolean $Enabled TRUE to enable, FALSE to disable 
     75     * @return void 
     76     */ 
     77    public static function setEnabled($Enabled) 
     78    { 
     79        $instance = FirePHP::getInstance(true); 
     80        $instance->setEnabled($Enabled); 
     81    } 
     82   
     83    /** 
     84     * Check if logging is enabled 
     85     *  
     86     * @see FirePHP->getEnabled() 
     87     * @return boolean TRUE if enabled 
     88     */ 
     89    public static function getEnabled() 
     90    { 
     91        $instance = FirePHP::getInstance(true); 
     92        return $instance->getEnabled(); 
     93    }   
     94   
     95    /** 
     96     * Specify a filter to be used when encoding an object 
     97     *  
     98     * Filters are used to exclude object members. 
     99     *  
     100     * @see FirePHP->setObjectFilter() 
     101     * @param string $Class The class name of the object 
     102     * @param array $Filter An array or members to exclude 
     103     * @return void 
     104     */ 
     105    public static function setObjectFilter($Class, $Filter) 
     106    { 
     107      $instance = FirePHP::getInstance(true); 
     108      $instance->setObjectFilter($Class, $Filter); 
     109    } 
     110   
     111    /** 
     112     * Set some options for the library 
     113     *  
     114     * @see FirePHP->setOptions() 
     115     * @param array $Options The options to be set 
     116     * @return void 
     117     */ 
     118    public static function setOptions($Options) 
     119    { 
     120        $instance = FirePHP::getInstance(true); 
     121        $instance->setOptions($Options); 
     122    } 
     123 
     124    /** 
     125     * Get options for the library 
     126     *  
     127     * @see FirePHP->getOptions() 
     128     * @return array The options 
     129     */ 
     130    public static function getOptions() 
     131    { 
     132        $instance = FirePHP::getInstance(true); 
     133        return $instance->getOptions(); 
     134    } 
     135 
     136    /** 
     137     * Log object to firebug 
     138     *  
     139     * @see http://www.firephp.org/Wiki/Reference/Fb 
     140     * @param mixed $Object 
     141     * @return true 
     142     * @throws Exception 
     143     */ 
     144    public static function send() 
     145    { 
     146        $instance = FirePHP::getInstance(true); 
     147        $args = func_get_args(); 
     148        return call_user_func_array(array($instance,'fb'),$args); 
     149    } 
     150 
     151    /** 
     152     * Start a group for following messages 
     153     *  
     154     * Options: 
     155     *   Collapsed: [true|false] 
     156     *   Color:     [#RRGGBB|ColorName] 
     157     * 
     158     * @param string $Name 
     159     * @param array $Options OPTIONAL Instructions on how to log the group 
     160     * @return true 
     161     */ 
     162    public static function group($Name, $Options=null) 
     163    { 
     164        $instance = FirePHP::getInstance(true); 
     165        return $instance->group($Name, $Options); 
     166    } 
     167 
     168    /** 
     169     * Ends a group you have started before 
     170     * 
     171     * @return true 
     172     * @throws Exception 
     173     */ 
     174    public static function groupEnd() 
     175    { 
     176        return self::send(null, null, FirePHP::GROUP_END); 
     177    } 
     178 
     179    /** 
     180     * Log object with label to firebug console 
     181     * 
     182     * @see FirePHP::LOG 
     183     * @param mixes $Object 
     184     * @param string $Label 
     185     * @return true 
     186     * @throws Exception 
     187     */ 
     188    public static function log($Object, $Label=null) 
     189    { 
     190        return self::send($Object, $Label, FirePHP::LOG); 
     191    }  
     192 
     193    /** 
     194     * Log object with label to firebug console 
     195     * 
     196     * @see FirePHP::INFO 
     197     * @param mixes $Object 
     198     * @param string $Label 
     199     * @return true 
     200     * @throws Exception 
     201     */ 
     202    public static function info($Object, $Label=null) 
     203    { 
     204        return self::send($Object, $Label, FirePHP::INFO); 
     205    }  
     206 
     207    /** 
     208     * Log object with label to firebug console 
     209     * 
     210     * @see FirePHP::WARN 
     211     * @param mixes $Object 
     212     * @param string $Label 
     213     * @return true 
     214     * @throws Exception 
     215     */ 
     216    public static function warn($Object, $Label=null) 
     217    { 
     218        return self::send($Object, $Label, FirePHP::WARN); 
     219    }  
     220 
     221    /** 
     222     * Log object with label to firebug console 
     223     * 
     224     * @see FirePHP::ERROR 
     225     * @param mixes $Object 
     226     * @param string $Label 
     227     * @return true 
     228     * @throws Exception 
     229     */ 
     230    public static function error($Object, $Label=null) 
     231    { 
     232        return self::send($Object, $Label, FirePHP::ERROR); 
     233    }  
     234 
     235    /** 
     236     * Dumps key and variable to firebug server panel 
     237     * 
     238     * @see FirePHP::DUMP 
     239     * @param string $Key 
     240     * @param mixed $Variable 
     241     * @return true 
     242     * @throws Exception 
     243     */ 
     244    public static function dump($Key, $Variable) 
     245    { 
     246        return self::send($Variable, $Key, FirePHP::DUMP); 
     247    }  
     248 
     249    /** 
     250     * Log a trace in the firebug console 
     251     * 
     252     * @see FirePHP::TRACE 
     253     * @param string $Label 
     254     * @return true 
     255     * @throws Exception 
     256     */ 
     257    public static function trace($Label) 
     258    { 
     259        return self::send($Label, FirePHP::TRACE); 
     260    }  
     261 
     262    /** 
     263     * Log a table in the firebug console 
     264     * 
     265     * @see FirePHP::TABLE 
     266     * @param string $Label 
     267     * @param string $Table 
     268     * @return true 
     269     * @throws Exception 
     270     */ 
     271    public static function table($Label, $Table) 
     272    { 
     273        return self::send($Table, $Label, FirePHP::TABLE); 
     274    }  
    253275 
    254276} 
    255  
    256  
Note: See TracChangeset for help on using the changeset viewer.