Merge "Strip excess newlines from formatting test"
[lhc/web/wiklou.git] / includes / Exception.php
index c513ef7..39fe6f4 100644 (file)
@@ -127,7 +127,7 @@ class MWException extends Exception {
 
                if ( $wgShowExceptionDetails ) {
                        return '<p>' . nl2br( htmlspecialchars( $this->getMessage() ) ) .
-                               '</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( $this->getTraceAsString() ) ) .
+                               '</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( MWExceptionHandler::formatRedactedTrace( $this ) ) ) .
                                "</p>\n";
                } else {
                        return "<div class=\"errorbox\">" .
@@ -152,7 +152,7 @@ class MWException extends Exception {
 
                if ( $wgShowExceptionDetails ) {
                        return $this->getMessage() .
-                               "\nBacktrace:\n" . $this->getTraceAsString() . "\n";
+                               "\nBacktrace:\n" . MWExceptionHandler::formatRedactedTrace( $this ) . "\n";
                } else {
                        return "Set \$wgShowExceptionDetails = true; " .
                                "in LocalSettings.php to show detailed debugging information.\n";
@@ -247,16 +247,9 @@ class MWException extends Exception {
         * It will be either HTML or plain text based on isCommandLine().
         */
        function report() {
-               global $wgLogExceptionBacktrace, $wgMimeType;
-               $log = $this->getLogMessage();
+               global $wgMimeType;
 
-               if ( $log ) {
-                       if ( $wgLogExceptionBacktrace ) {
-                               wfDebugLog( 'exception', $log . "\n" . $this->getTraceAsString() . "\n" );
-                       } else {
-                               wfDebugLog( 'exception', $log );
-                       }
-               }
+               $this->logException();
 
                if ( defined( 'MW_API' ) ) {
                        // Unhandled API exception, we can't be sure that format printer is alive
@@ -273,6 +266,22 @@ class MWException extends Exception {
                }
        }
 
+       /**
+        * Log the error message to the exception log (if enabled)
+        */
+       function logException() {
+               global $wgLogExceptionBacktrace;
+
+               $log = $this->getLogMessage();
+               if ( $log ) {
+                       if ( $wgLogExceptionBacktrace ) {
+                               wfDebugLog( 'exception', $log . "\n" . MWExceptionHandler::formatRedactedTrace( $this ) . "\n" );
+                       } else {
+                               wfDebugLog( 'exception', $log );
+                       }
+               }
+       }
+
        /**
         * Check whether we are in command line mode or not to report the exception
         * in the correct format.
@@ -624,7 +633,7 @@ class MWExceptionHandler {
                                $message = "MediaWiki internal error.\n\n";
 
                                if ( $wgShowExceptionDetails ) {
-                                       $message .= 'Original exception: ' . $e->__toString() . "\n\n" .
+                                       $message .= 'Original exception: ' . self::formatRedactedTrace( $e ) . "\n\n" .
                                                'Exception caught inside exception handler: ' . $e2->__toString();
                                } else {
                                        $message .= "Exception caught inside exception handler.\n\n" .
@@ -641,11 +650,10 @@ class MWExceptionHandler {
                                }
                        }
                } else {
-                       $message = "Unexpected non-MediaWiki exception encountered, of type \"" . get_class( $e ) . "\"\n" .
-                               $e->__toString() . "\n";
+                       $message = "Unexpected non-MediaWiki exception encountered, of type \"" . get_class( $e ) . "\"";
 
                        if ( $wgShowExceptionDetails ) {
-                               $message .= "\n" . $e->getTraceAsString() . "\n";
+                               $message .= "\nexception '" . get_class( $e ) . "' in " . $e->getFile() . ":" . $e->getLine() . "\nStack trace:\n" . self::formatRedactedTrace( $e ) . "\n";
                        }
 
                        if ( $cmdLine ) {
@@ -668,7 +676,7 @@ class MWExceptionHandler {
                if ( defined( 'STDERR' ) ) {
                        fwrite( STDERR, $message );
                } else {
-                       echo( $message );
+                       echo $message;
                }
        }
 
@@ -700,4 +708,53 @@ class MWExceptionHandler {
                // Exit value should be nonzero for the benefit of shell jobs
                exit( 1 );
        }
+
+       /**
+        * Get the stack trace from the exception as a string, redacting certain function arguments in the process
+        * @param Exception $e The exception
+        * @return string The stack trace as a string
+        */
+       public static function formatRedactedTrace( Exception $e ) {
+               global $wgRedactedFunctionArguments;
+               $finalExceptionText = '';
+
+               foreach ( $e->getTrace() as $i => $call ) {
+                       $checkFor = array();
+                       if ( isset( $call['class'] ) ) {
+                               $checkFor[] = $call['class'] . '::' . $call['function'];
+                               foreach ( class_parents( $call['class'] ) as $parent ) {
+                                       $checkFor[] = $parent . '::' . $call['function'];
+                               }
+                       } else {
+                               $checkFor[] = $call['function'];
+                       }
+
+                       foreach ( $checkFor as $check ) {
+                               if ( isset( $wgRedactedFunctionArguments[$check] ) ) {
+                                       foreach ( (array)$wgRedactedFunctionArguments[$check] as $argNo ) {
+                                               $call['args'][$argNo] = 'REDACTED';
+                                       }
+                               }
+                       }
+
+                       $finalExceptionText .= "#{$i} {$call['file']}({$call['line']}): ";
+                       if ( isset( $call['class'] ) ) {
+                               $finalExceptionText .= $call['class'] . $call['type'] . $call['function'];
+                       } else {
+                               $finalExceptionText .= $call['function'];
+                       }
+                       $args = array();
+                       foreach ( $call['args'] as $arg ) {
+                               if ( is_object( $arg ) ) {
+                                       $args[] = 'Object(' . get_class( $arg ) . ')';
+                               } elseif( is_array( $arg ) ) {
+                                       $args[] = 'Array';
+                               } else {
+                                       $args[] = var_export( $arg, true );
+                               }
+                       }
+                       $finalExceptionText .=  '(' . implode( ', ', $args ) . ")\n";
+               }
+               return $finalExceptionText . '#' . ( $i + 1 ) . ' {main}';
+       }
 }