30
30
class ExceptionHandler
31
31
{
32
32
private $ debug ;
33
+ private $ charset ;
33
34
private $ handler ;
34
35
private $ caughtBuffer ;
35
36
private $ caughtLength ;
36
37
private $ fileLinkFormat ;
37
38
38
- public function __construct ($ debug = true , $ fileLinkFormat = null )
39
+ public function __construct ($ debug = true , $ charset = null , $ fileLinkFormat = null )
39
40
{
41
+ if (false !== strpos ($ charset , '% ' ) xor false === strpos ($ fileLinkFormat , '% ' )) {
42
+ // Swap $charset and $fileLinkFormat for BC reasons
43
+ $ pivot = $ fileLinkFormat ;
44
+ $ fileLinkFormat = $ charset ;
45
+ $ charset = $ pivot ;
46
+ }
40
47
$ this ->debug = $ debug ;
48
+ $ this ->charset = $ charset ?: ini_get ('default_charset ' ) ?: 'UTF-8 ' ;
41
49
$ this ->fileLinkFormat = $ fileLinkFormat ?: ini_get ('xdebug.file_link_format ' ) ?: get_cfg_var ('xdebug.file_link_format ' );
42
50
}
43
51
44
52
/**
45
53
* Registers the exception handler.
46
54
*
47
- * @param bool $debug
55
+ * @param bool $debug Enable/disable debug mode, where the stack trace is displayed
56
+ * @param string|null $charset The charset used by exception messages
57
+ * @param string|null $fileLinkFormat The IDE link template
48
58
*
49
59
* @return ExceptionHandler The registered exception handler
50
60
*/
51
- public static function register ($ debug = true , $ fileLinkFormat = null )
61
+ public static function register ($ debug = true , $ charset = null , $ fileLinkFormat = null )
52
62
{
53
- $ handler = new static ($ debug , $ fileLinkFormat );
63
+ $ handler = new static ($ debug , $ charset , $ fileLinkFormat );
54
64
55
65
$ prev = set_exception_handler (array ($ handler , 'handle ' ));
56
66
if (is_array ($ prev ) && $ prev [0 ] instanceof ErrorHandler) {
@@ -177,6 +187,7 @@ public function sendPhpResponse($exception)
177
187
foreach ($ exception ->getHeaders () as $ name => $ value ) {
178
188
header ($ name .': ' .$ value , false );
179
189
}
190
+ header ('Content-Type: text/html; charset= ' .$ this ->charset );
180
191
}
181
192
182
193
echo $ this ->decorate ($ this ->getContent ($ exception ), $ this ->getStylesheet ($ exception ));
@@ -195,7 +206,7 @@ public function createResponse($exception)
195
206
$ exception = FlattenException::create ($ exception );
196
207
}
197
208
198
- return new Response ($ this ->decorate ($ this ->getContent ($ exception ), $ this ->getStylesheet ($ exception )), $ exception ->getStatusCode (), $ exception ->getHeaders ());
209
+ return Response:: create ($ this ->decorate ($ this ->getContent ($ exception ), $ this ->getStylesheet ($ exception )), $ exception ->getStatusCode (), $ exception ->getHeaders ())-> setCharset ( $ this -> charset );
199
210
}
200
211
201
212
/**
@@ -223,7 +234,7 @@ public function getContent(FlattenException $exception)
223
234
foreach ($ exception ->toArray () as $ position => $ e ) {
224
235
$ ind = $ count - $ position + 1 ;
225
236
$ class = $ this ->formatClass ($ e ['class ' ]);
226
- $ message = nl2br (self :: utf8Htmlize ($ e ['message ' ]));
237
+ $ message = nl2br ($ this -> escapeHtml ($ e ['message ' ]));
227
238
$ content .= sprintf (<<<EOF
228
239
<h2 class="block_exception clear_fix">
229
240
<span class="exception_counter">%d/%d</span>
@@ -337,7 +348,7 @@ private function decorate($content, $css)
337
348
<!DOCTYPE html>
338
349
<html>
339
350
<head>
340
- <meta charset="UTF-8 " />
351
+ <meta charset=" { $ this -> charset } " />
341
352
<meta name="robots" content="noindex,nofollow" />
342
353
<style>
343
354
/* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
@@ -365,7 +376,7 @@ private function formatClass($class)
365
376
366
377
private function formatPath ($ path , $ line )
367
378
{
368
- $ path = self :: utf8Htmlize ($ path );
379
+ $ path = $ this -> escapeHtml ($ path );
369
380
$ file = preg_match ('#[^/ \\\\]*$# ' , $ path , $ file ) ? $ file [0 ] : $ path ;
370
381
371
382
if ($ linkFormat = $ this ->fileLinkFormat ) {
@@ -393,15 +404,15 @@ private function formatArgs(array $args)
393
404
} elseif ('array ' === $ item [0 ]) {
394
405
$ formattedValue = sprintf ("<em>array</em>(%s) " , is_array ($ item [1 ]) ? $ this ->formatArgs ($ item [1 ]) : $ item [1 ]);
395
406
} elseif ('string ' === $ item [0 ]) {
396
- $ formattedValue = sprintf ("'%s' " , self :: utf8Htmlize ($ item [1 ]));
407
+ $ formattedValue = sprintf ("'%s' " , $ this -> escapeHtml ($ item [1 ]));
397
408
} elseif ('null ' === $ item [0 ]) {
398
409
$ formattedValue = '<em>null</em> ' ;
399
410
} elseif ('boolean ' === $ item [0 ]) {
400
411
$ formattedValue = '<em> ' .strtolower (var_export ($ item [1 ], true )).'</em> ' ;
401
412
} elseif ('resource ' === $ item [0 ]) {
402
413
$ formattedValue = '<em>resource</em> ' ;
403
414
} else {
404
- $ formattedValue = str_replace ("\n" , '' , var_export (self :: utf8Htmlize ((string ) $ item [1 ]), true ));
415
+ $ formattedValue = str_replace ("\n" , '' , var_export ($ this -> escapeHtml ((string ) $ item [1 ]), true ));
405
416
}
406
417
407
418
$ result [] = is_int ($ key ) ? $ formattedValue : sprintf ("'%s' => %s " , $ key , $ formattedValue );
@@ -429,6 +440,14 @@ protected static function utf8Htmlize($str)
429
440
return htmlspecialchars ($ str , ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0 ), 'UTF-8 ' );
430
441
}
431
442
443
+ /**
444
+ * HTML-encodes a string
445
+ */
446
+ private function escapeHtml ($ str )
447
+ {
448
+ return htmlspecialchars ($ str , ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0 ), $ this ->charset );
449
+ }
450
+
432
451
/**
433
452
* @internal
434
453
*/
0 commit comments