diff --git a/src/php_error.php b/src/php_error.php index fa55cd5..ec2d220 100644 --- a/src/php_error.php +++ b/src/php_error.php @@ -530,6 +530,10 @@ class ErrorHandler 'application/xhtml+xml' ); + protected static $ALLOWED_OUTPUT_BUFFERS = array( + 'ob_gzhandler', 'zlib output compression' + ); + private static function isIIS() { return ( isset($_SERVER['SERVER_SOFTWARE']) && @@ -1272,8 +1276,6 @@ public function __construct( $options=null ) { ); $this->isBufferSetup = false; - $this->bufferOutputStr = ''; - $this->bufferOutput = false; $this->startBuffer(); } @@ -1434,22 +1436,7 @@ private function startBuffer() { @ini_set( 'output_buffering', 'on' ); } - $output = ''; - $bufferOutput = true; - - $this->bufferOutputStr = &$output; - $this->bufferOutput = &$bufferOutput; - - ob_start( function($string) use (&$output, &$bufferOutput) { - if ( $bufferOutput ) { - $output .= $string; - return ''; - } else { - $temp = $output . $string; - $output = ''; - return $temp; - } - }); + ob_start(); $self = $this; register_shutdown_function( function() use ( $self ) { @@ -1459,33 +1446,43 @@ private function startBuffer() { } /** - * Turns off buffering, and discards anything buffered - * so far. + * Discards anything buffered so far. + * + * Will preserve output compression handlers. * * This will return what has been buffered incase you * do want it. However otherwise, it will be lost. */ - private function discardBuffer() { - $str = $this->bufferOutputStr; - - $this->bufferOutputStr = ''; - $this->bufferOutput = false; - - return $str; + private function discardBuffer($return = false) { + if (!$this->isBufferSetup) return false; + + $content = ob_get_contents(); + $handlers = ob_list_handlers(); + + /* Flushing buffers may result in errors, so lets get their contents + * in reverse order... */ + $content = false; + for ( $i = count($handlers)-1; $i >= 0; $i-- ) { + $handler = $handlers[$i]; + + if ( in_array($handler, self::$ALLOWED_OUTPUT_BUFFERS) ) { + // these buffers are safe to stay... + break; + } else { + if ($return) { + $content = ob_get_clean() . $content; + } else { + ob_end_clean(); + } + } + } + + // restart buffering + ob_start(); + + return $content; } - /** - * Flushes the internal buffer, - * outputting what is left. - * - * @param append Optional, extra content to append onto the output buffer. - */ - private function flushBuffer() { - $temp = $this->bufferOutputStr; - $this->bufferOutputStr = ''; - - return $temp; - } /** * This will finish buffering, and output the page. @@ -1498,38 +1495,15 @@ private function flushBuffer() { */ public function endBuffer() { if ( $this->isBufferSetup ) { - $content = ob_get_contents(); - $handlers = ob_list_handlers(); - - $wasGZHandler = false; - - $this->bufferOutput = true; - for ( $i = count($handlers)-1; $i >= 0; $i-- ) { - $handler = $handlers[$i]; - - if ( $handler === 'ob_gzhandler' ) { - $wasGZHandler = true; - ob_end_clean(); - } else if ( $handler === 'default output handler' ) { - ob_end_clean(); - } else { - ob_end_flush(); - } - } - - $content = $this->discardBuffer(); - - if ( $wasGZHandler ) { - ob_start('ob_gzhandler'); - } else { - ob_start(); - } if ( !$this->isAjax && $this->catchAjaxErrors && (!$this->htmlOnly || !ErrorHandler::isNonPHPRequest()) ) { + $content = ob_get_contents(); + ob_clean(); + $js = $this->getContent( 'displayJSInjection' ); $js = JSMin::minify( $js ); @@ -1543,9 +1517,12 @@ public function endBuffer() { } else { echo $js; } + + echo $content; } - echo $content; + ob_end_flush(); + } } @@ -2335,7 +2312,6 @@ public function reportException( $ex ) { * more than that. */ public function reportError( $code, $message, $errLine, $errFile, $ex=null ) { - $this->discardBuffer(); if ( $ex === null && @@ -2370,6 +2346,9 @@ public function reportError( $code, $message, $errLine, $errFile, $ex=null ) { !ErrorHandler::isNonPHPRequest() ) ) { + + $this->discardBuffer(); + $root = $this->applicationRoot; list( $ex, $stackTrace, $code, $errFile, $errLine ) =