3v4l.org

run code in 150+ php & hhvm versions
Bugs & Features
<?php class FirePHP { /** * Gets singleton instance of FirePHP * * @param boolean $AutoCreate * @return FirePHP */ public static function getInstance($AutoCreate=false) { if($AutoCreate===true && !self::$instance) { self::init(); } return self::$instance; } /** * Creates FirePHP object and stores it for singleton access * * @return FirePHP */ public static function init() { return self::$instance = new self(); } /** * Enable and disable logging to Firebug * * @param boolean $Enabled TRUE to enable, FALSE to disable * @return void */ public function setEnabled($Enabled) { $this->enabled = $Enabled; } /** * Check if logging is enabled * * @return boolean TRUE if enabled */ public function getEnabled() { return $this->enabled; } /** * Specify a filter to be used when encoding an object * * Filters are used to exclude object members. * * @param string $Class The class name of the object * @param array $Filter An array or members to exclude * @return void */ public function setObjectFilter($Class, $Filter) { $this->objectFilters[$Class] = $Filter; } /** * Register FirePHP as your error handler * * Will throw exceptions for each php error. */ public function registerErrorHandler() { //NOTE: The following errors will not be caught by this error handler: // E_ERROR, E_PARSE, E_CORE_ERROR, // E_CORE_WARNING, E_COMPILE_ERROR, // E_COMPILE_WARNING, E_STRICT set_error_handler(array($this,'errorHandler')); } /** * FirePHP's error handler * * Throws exception for each php error that will occur. * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @param array $errcontext */ public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) { // Don't throw exception if error reporting is switched off if (error_reporting() == 0) { return; } // Only throw exceptions for errors we are asking for if (error_reporting() & $errno) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } } /** * Register FirePHP as your exception handler */ public function registerExceptionHandler() { set_exception_handler(array($this,'exceptionHandler')); } /** * FirePHP's exception handler * * Logs all exceptions to your firebug console and then stops the script. * * @param Exception $Exception * @throws Exception */ function exceptionHandler($Exception) { $this->fb($Exception); } /** * Set custom processor url for FirePHP * * @param string $URL */ public function setProcessorUrl($URL) { $this->setHeader('X-FirePHP-ProcessorURL', $URL); } /** * Set custom renderer url for FirePHP * * @param string $URL */ public function setRendererUrl($URL) { $this->setHeader('X-FirePHP-RendererURL', $URL); } /** * Start a group for following messages * * @param string $Name * @return true * @throws Exception */ public function group($Name) { return $this->fb(null, $Name, FirePHP::GROUP_START); } /** * Ends a group you have started before * * @return true * @throws Exception */ public function groupEnd() { return $this->fb(null, null, FirePHP::GROUP_END); } /** * Log object with label to firebug console * * @see FirePHP::LOG * @param mixes $Object * @param string $Label * @return true * @throws Exception */ public function log($Object, $Label=null) { return $this->fb($Object, $Label, FirePHP::LOG); } /** * Log object with label to firebug console * * @see FirePHP::INFO * @param mixes $Object * @param string $Label * @return true * @throws Exception */ public function info($Object, $Label=null) { return $this->fb($Object, $Label, FirePHP::INFO); } /** * Log object with label to firebug console * * @see FirePHP::WARN * @param mixes $Object * @param string $Label * @return true * @throws Exception */ public function warn($Object, $Label=null) { return $this->fb($Object, $Label, FirePHP::WARN); } /** * Log object with label to firebug console * * @see FirePHP::ERROR * @param mixes $Object * @param string $Label * @return true * @throws Exception */ public function error($Object, $Label=null) { return $this->fb($Object, $Label, FirePHP::ERROR); } /** * Dumps key and variable to firebug server panel * * @see FirePHP::DUMP * @param string $Key * @param mixed $Variable * @return true * @throws Exception */ public function dump($Key, $Variable) { return $this->fb($Variable, $Key, FirePHP::DUMP); } /** * Log a trace in the firebug console * * @see FirePHP::TRACE * @param string $Label * @return true * @throws Exception */ public function trace($Label) { return $this->fb($Label, FirePHP::TRACE); } public function table($Label, $Table) { return $this->fb($Table, $Label, FirePHP::TABLE); } public function detectClientExtension() { /* Check if FirePHP is installed on client */ if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) || !version_compare($m[1][0],'0.0.6','>=')) { return false; } return true; } public function fb($Object) { if(!$this->enabled) { return false; } if (headers_sent($filename, $linenum)) { 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.'); } $Type = null; $Label = null; if(func_num_args()==1) { } else if(func_num_args()==2) { switch(func_get_arg(1)) { case self::LOG: case self::INFO: case self::WARN: case self::ERROR: case self::DUMP: case self::TRACE: case self::EXCEPTION: case self::TABLE: case self::GROUP_START: case self::GROUP_END: $Type = func_get_arg(1); break; default: $Label = func_get_arg(1); break; } } else if(func_num_args()==3) { $Type = func_get_arg(2); $Label = func_get_arg(1); } else { throw $this->newException('Wrong number of arguments to fb() function!'); } if(!$this->detectClientExtension()) { return false; } $meta = array(); $skipFinalObjectEncode = false; if($Object instanceof Exception) { $meta['file'] = $this->_escapeTraceFile($Object->getFile()); $meta['line'] = $Object->getLine(); $trace = $Object->getTrace(); if($Object instanceof ErrorException && isset($trace[0]['function']) && $trace[0]['function']=='errorHandler' && isset($trace[0]['class']) && $trace[0]['class']=='FirePHP') { $severity = false; switch($Object->getSeverity()) { case E_WARNING: $severity = 'E_WARNING'; break; case E_NOTICE: $severity = 'E_NOTICE'; break; case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; case E_STRICT: $severity = 'E_STRICT'; break; case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; } $Object = array('Class'=>get_class($Object), 'Message'=>$severity.': '.$Object->getMessage(), 'File'=>$this->_escapeTraceFile($Object->getFile()), 'Line'=>$Object->getLine(), 'Type'=>'trigger', 'Trace'=>$this->_escapeTrace(array_splice($trace,2))); $skipFinalObjectEncode = true; } else { $Object = array('Class'=>get_class($Object), 'Message'=>$Object->getMessage(), 'File'=>$this->_escapeTraceFile($Object->getFile()), 'Line'=>$Object->getLine(), 'Type'=>'throw', 'Trace'=>$this->_escapeTrace($trace)); $skipFinalObjectEncode = true; } $Type = self::EXCEPTION; } else if($Type==self::TRACE) { $trace = debug_backtrace(); if(!$trace) return false; for( $i=0 ; $i<sizeof($trace) ; $i++ ) { if(isset($trace[$i]['class']) && isset($trace[$i]['file']) && ($trace[$i]['class']=='FirePHP' || $trace[$i]['class']=='FB') && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ } else if(isset($trace[$i]['class']) && isset($trace[$i+1]['file']) && $trace[$i]['class']=='FirePHP' && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { /* Skip fb() */ } else if($trace[$i]['function']=='fb' || $trace[$i]['function']=='trace' || $trace[$i]['function']=='send') { $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', 'Message'=>$trace[$i]['args'][0], 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); $skipFinalObjectEncode = true; $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; break; } } } else if($Type==self::TABLE) { if(isset($Object[0]) && is_string($Object[0])) { $Object[1] = $this->encodeTable($Object[1]); } else { $Object = $this->encodeTable($Object); } $skipFinalObjectEncode = true; } else { if($Type===null) { $Type = self::LOG; } } if($this->options['includeLineNumbers']) { if(!isset($meta['file']) || !isset($meta['line'])) { $trace = debug_backtrace(); for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) { if(isset($trace[$i]['class']) && isset($trace[$i]['file']) && ($trace[$i]['class']=='FirePHP' || $trace[$i]['class']=='FB') && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ } else if(isset($trace[$i]['class']) && isset($trace[$i+1]['file']) && $trace[$i]['class']=='FirePHP' && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { /* Skip fb() */ } else if(isset($trace[$i]['file']) && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { /* Skip FB::fb() */ } else { $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; break; } } } } else { unset($meta['file']); unset($meta['line']); } $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); $structure_index = 1; if($Type==self::DUMP) { $structure_index = 2; $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); } else { $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); } if($Type==self::DUMP) { $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; } else { $msg_meta = array('Type'=>$Type); if($Label!==null) { $msg_meta['Label'] = $Label; } if(isset($meta['file'])) { $msg_meta['File'] = $meta['file']; } if(isset($meta['line'])) { $msg_meta['Line'] = $meta['line']; } $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; } $parts = explode("\n",chunk_split($msg, 5000, "\n")); for( $i=0 ; $i<count($parts) ; $i++) { $part = $parts[$i]; if ($part) { if(count($parts)>2) { // Message needs to be split into multiple parts $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, (($i==0)?strlen($msg):'') . '|' . $part . '|' . (($i<count($parts)-2)?'\\':'')); } else { $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, strlen($part) . '|' . $part . '|'); } $this->messageIndex++; if ($this->messageIndex > 99999) { throw new Exception('Maximum number (99,999) of messages reached!'); } } } $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); return true; } protected function _standardizePath($Path) { } protected function _escapeTrace($Trace) { if(!$Trace) return $Trace; for( $i=0 ; $i<sizeof($Trace) ; $i++ ) { if(isset($Trace[$i]['file'])) { $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']); } if(isset($Trace[$i]['args'])) { $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); } } return $Trace; } protected function _escapeTraceFile($File) { /* Check if we have a windows filepath */ if(strpos($File,'\\')) { /* First strip down to single \ */ $file = preg_replace('/\\\\+/','\\',$File); return $file; } return $File; } protected function setHeader($Name, $Value) { return header($Name.': '.$Value); } protected function getUserAgent() { if(!isset($_SERVER['HTTP_USER_AGENT'])) return false; return $_SERVER['HTTP_USER_AGENT']; } } function ciao() { $out = '<pre>'; $args = func_get_args(); if(!empty($args)) { // var_export() causes fatal errors on recursion... ob_start(); ini_set('xdebug.var_display_max_depth', 4); var_dump($args); $out .= ob_get_contents()."\n\n"; ob_end_clean(); } $out .= get_backtrace(1); die($out); } class A { function B() { while (ob_get_level() > 1) ob_end_flush(); // store possible trailing content $content = ob_get_clean(); // start an output buffer which cannot be flushed (3rd parameter is false) // callback function get all output and corrects Content-Length header ob_start(function($buffer) { ciao($buffer); }, 0, false); } } $a = new A; $a->B();
Output for 5.3.0 - 5.3.29, 7.0.1 - 7.1.0
Fatal error: ob_start(): Cannot use output buffering in output buffering display handlers in /in/cUVsG on line 541
Process exited with code 255.
Output for 7.0.0
Catchable fatal error: ob_start(): Cannot use output buffering in output buffering display handlers in /in/cUVsG on line 541
Process exited with code 255.
Output for hhvm-3.10.0 - 3.12.0
Output for 5.4.7 - 5.6.25
Fatal error: Cannot destroy active lambda function in /in/cUVsG on line 541
Process exited with code 255.
Output for 5.4.0 - 5.4.6
Fatal error: Cannot destroy active lambda function in /in/cUVsG on line 541