Merge pull request #2045 from BillSeurer/timezone
[mono.git] / mcs / class / System.Web / System.Web / HttpException.cs
1 // 
2 // System.Web.HttpException
3 //
4 // Authors:
5 //      Patrik Torstensson (Patrik.Torstensson@labs2.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (c) 2002 Patrik Torstensson
9 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.IO;
33 using System.Runtime.Serialization;
34 using System.Runtime.InteropServices;
35 using System.Security.Permissions;
36 using System.Text;
37 using System.Web.Util;
38 using System.Web.Compilation;
39 using System.Web.Management;
40 using System.Collections.Specialized;
41
42 namespace System.Web
43 {
44         // CAS
45         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47         [Serializable]
48         public class HttpException : ExternalException
49         {
50                 const string DEFAULT_DESCRIPTION_TEXT = "Error processing request.";
51                 const string ERROR_404_DESCRIPTION = "The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.";
52
53                 int webEventCode = WebEventCodes.UndefinedEventCode;
54                 int http_code = 500;
55                 string resource_name;
56                 string description;
57                 ExceptionPageTemplate pageTemplate;
58
59                 ExceptionPageTemplate PageTemplate {
60                         get {
61                                 if (pageTemplate == null)
62                                         pageTemplate = GetPageTemplate ();
63                                 return pageTemplate;
64                         }
65                 }
66                 public
67                 int WebEventCode 
68                 {
69                         get { return webEventCode; }
70                 }
71                 
72                 public HttpException ()
73                 {
74                 }
75
76                 public HttpException (string message)
77                         : base (message)
78                 {
79                 }
80
81                 public HttpException (string message, Exception innerException)
82                         : base (message, innerException)
83                 {
84                 }
85
86                 public HttpException (int httpCode, string message) : base (message)
87                 {
88                         http_code = httpCode;
89                 }
90
91                 internal HttpException (int httpCode, string message, string resourceName) : this (httpCode, message)
92                 {
93                         resource_name = resourceName;
94                 }
95
96                 internal HttpException (int httpCode, string message, string resourceName, string description) : this (httpCode, message, resourceName)
97                 {
98                         this.description = description;
99                 }
100                 
101                 protected HttpException (SerializationInfo info, StreamingContext context)
102                         : base (info, context)
103                 {
104                         http_code = info.GetInt32 ("_httpCode");
105                         webEventCode = info.GetInt32 ("_webEventCode");
106                 }
107
108                 [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
109                 public override void GetObjectData (SerializationInfo info, StreamingContext context)
110                 {
111                         base.GetObjectData (info, context);
112                         info.AddValue ("_httpCode", http_code);
113                         info.AddValue ("_webEventCode", webEventCode);
114                 }
115
116                 public HttpException (int httpCode, string message, int hr) 
117                         : base (message, hr)
118                 {
119                         http_code = httpCode;
120                 }
121
122                 public HttpException (string message, int hr)
123                         : base (message, hr)
124                 {
125                 }
126         
127                 public HttpException (int httpCode, string message, Exception innerException)
128                         : base (message, innerException)
129                 {
130                         http_code = httpCode;
131                 }
132
133                 internal HttpException (int httpCode, string message, Exception innerException, string resourceName)
134                         : this (httpCode, message, innerException)
135                 {
136                         resource_name = resourceName;
137                 }
138
139                 [MonoTODO ("For now just the default template is created. Means of user-provided templates are to be implemented yet.")]
140                 ExceptionPageTemplate GetPageTemplate ()
141                 {
142                         ExceptionPageTemplate template = new DefaultExceptionPageTemplate ();
143                         template.Init ();
144
145                         return template;
146                 }
147                 
148                 public string GetHtmlErrorMessage ()
149                 {
150                         var values = new ExceptionPageTemplateValues ();
151                         ExceptionPageTemplate template = PageTemplate;
152
153                         try {
154                                 values.Add (ExceptionPageTemplate.Template_RuntimeVersionInformationName, RuntimeHelpers.MonoVersion);
155                                 values.Add (ExceptionPageTemplate.Template_AspNetVersionInformationName, Environment.Version.ToString ());
156                                 
157                                 HttpContext ctx = HttpContext.Current;
158                                 ExceptionPageTemplateType pageType = ExceptionPageTemplateType.Standard;
159
160                                 if (ctx != null && ctx.IsCustomErrorEnabled) {
161                                         if (http_code != 404 && http_code != 403) {
162                                                 FillDefaultCustomErrorValues (values);
163                                                 pageType = ExceptionPageTemplateType.CustomErrorDefault;
164                                         } else
165                                                 FillDefaultErrorValues (false, false, null, values);
166                                 } else {
167                                         Exception ex = GetBaseException ();
168                                         if (ex == null)
169                                                 ex = this;
170
171                                         values.Add (ExceptionPageTemplate.Template_FullStackTraceName, FormatFullStackTrace ());
172                                         HtmlizedException htmlException = ex as HtmlizedException;
173                                         if (htmlException == null)
174                                                 FillDefaultErrorValues (true, true, ex, values);
175                                         else {
176                                                 pageType = ExceptionPageTemplateType.Htmlized;
177                                                 FillHtmlizedErrorValues (values, htmlException, ref pageType);
178                                         }
179                                 }
180                                 
181                                 return template.Render (values, pageType);
182                         } catch (Exception ex) {
183                                 Console.Error.WriteLine ("An exception has occurred while generating HttpException page:");
184                                 Console.Error.WriteLine (ex);
185                                 Console.Error.WriteLine ();
186                                 Console.Error.WriteLine ("The actual exception which was being reported was:");
187                                 Console.Error.WriteLine (this);
188
189                                 // we need the try/catch block in case the
190                                 // problem was with MapPath, which will cause
191                                 // IsCustomErrorEnabled to throw an exception
192                                 try {
193                                         FillDefaultCustomErrorValues (values);
194                                         return template.Render (values, ExceptionPageTemplateType.CustomErrorDefault);
195                                 } catch {
196                                         return DoubleFaultExceptionMessage;
197                                 }
198                         }
199                 }
200
201                 internal virtual string Description {
202                         get {
203                                 if (description != null)
204                                         return description;
205
206                                 return DEFAULT_DESCRIPTION_TEXT;
207                         }
208                         
209                         set {
210                                 if (value != null && value.Length > 0)
211                                         description = value;
212                                 else
213                                         description = DEFAULT_DESCRIPTION_TEXT;
214                         }
215                 }
216
217                 internal static HttpException NewWithCode (string message, int webEventCode)
218                 {
219                         var ret = new HttpException (message);
220                         ret.SetWebEventCode (webEventCode);
221
222                         return ret;
223                 }
224
225                 internal static HttpException NewWithCode (string message, Exception innerException, int webEventCode)
226                 {
227                         var ret = new HttpException (message, innerException);
228                         ret.SetWebEventCode (webEventCode);
229
230                         return ret;
231                 }
232
233                 internal static HttpException NewWithCode (int httpCode, string message, int webEventCode)
234                 {
235                         var ret = new HttpException (httpCode, message);
236                         ret.SetWebEventCode (webEventCode);
237
238                         return ret;
239                 }
240                 
241                 internal static HttpException NewWithCode (int httpCode, string message, Exception innerException, string resourceName, int webEventCode)
242                 {
243                         var ret = new HttpException (httpCode, message, innerException, resourceName);
244                         ret.SetWebEventCode (webEventCode);
245
246                         return ret;
247                 }
248
249                 internal static HttpException NewWithCode (int httpCode, string message, string resourceName, int webEventCode)
250                 {
251                         var ret = new HttpException (httpCode, message, resourceName);
252                         ret.SetWebEventCode (webEventCode);
253
254                         return ret;
255                 }
256
257                 internal static HttpException NewWithCode (int httpCode, string message, Exception innerException, int webEventCode)
258                 {
259                         var ret = new HttpException (httpCode, message, innerException);
260                         ret.SetWebEventCode (webEventCode);
261
262                         return ret;
263                 }
264                 
265                 internal void SetWebEventCode (int webEventCode)
266                 {
267                         this.webEventCode = webEventCode;
268                 }
269                 
270                 string FormatFullStackTrace ()
271                 {
272                         Exception ex = this;
273                         var builder = new StringBuilder ("\r\n<!--");
274                         string trace;
275                         string message;
276                         bool haveTrace, first = true;
277                         
278                         while (ex != null) {
279                                 trace = ex.StackTrace;
280                                 message = ex.Message;
281                                 haveTrace = !String.IsNullOrEmpty (trace);
282                                 
283                                 if (!haveTrace && String.IsNullOrEmpty (message)) {
284                                         ex = ex.InnerException;
285                                         continue;
286                                 }
287
288                                 if (first)
289                                         first = false;
290                                 else
291                                         builder.Append ("\r\n");
292                                 
293                                 builder.Append ("\r\n[" + ex.GetType () + "]: " + HtmlEncode (message) + "\r\n");
294                                 if (haveTrace)
295                                         builder.Append (ex.StackTrace);
296                                 
297                                 ex = ex.InnerException;
298                         }
299                         builder.Append ("\r\n-->\r\n");
300
301                         return builder.ToString ();
302                 }
303
304                 void FillHtmlizedErrorValues (ExceptionPageTemplateValues values, HtmlizedException exc, ref ExceptionPageTemplateType pageType)
305                 {
306                         bool isParseException = exc is ParseException;
307                         bool isCompileException = (!isParseException && exc is CompilationException);
308                         values.Add (ExceptionPageTemplate.Template_PageTitleName, HtmlEncode (exc.Title));
309                         values.Add (ExceptionPageTemplate.Template_DescriptionName, HtmlEncode (exc.Description));
310                         values.Add (ExceptionPageTemplate.Template_StackTraceName, HtmlEncode (exc.StackTrace));
311                         values.Add (ExceptionPageTemplate.Template_ExceptionTypeName, exc.GetType ().ToString ());
312                         values.Add (ExceptionPageTemplate.Template_ExceptionMessageName, HtmlEncode (exc.Message));
313                         values.Add (ExceptionPageTemplate.Template_DetailsName, HtmlEncode (exc.ErrorMessage));
314
315                         string origin;
316                         if (isParseException)
317                                 origin = "Parser";
318                         else if (isCompileException)
319                                 origin = "Compiler";
320                         else
321                                 origin = "Other";
322                         values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionOriginName, origin);
323                         if (exc.FileText != null) {
324                                 pageType |= ExceptionPageTemplateType.SourceError;
325                                 StringBuilder shortSource = new StringBuilder ();
326                                 StringBuilder longSource;
327                                 
328                                 if (isCompileException)
329                                         longSource = new StringBuilder ();
330                                 else
331                                         longSource = null;
332                                 FormatSource (shortSource, longSource, exc);
333                                 values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionShortSourceName, shortSource.ToString ());
334                                 values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionLongSourceName, longSource != null ? longSource.ToString () : null);
335                                 
336                                 if (exc.SourceFile != exc.FileName)
337                                         values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionSourceFileName, FormatSourceFile (exc.SourceFile));
338                                 else
339                                         values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionSourceFileName, FormatSourceFile (exc.FileName));
340                                 if (isParseException || isCompileException) {
341                                         int[] errorLines = exc.ErrorLines;
342                                         int numErrors = errorLines != null ? errorLines.Length : 0;
343                                         var lines = new StringBuilder ();
344                                         for (int i = 0; i < numErrors; i++) {
345                                                 if (i > 0)
346                                                         lines.Append (", ");
347                                                 lines.Append (errorLines [i]);
348                                         }
349                                         values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionErrorLinesName, lines.ToString ());
350                                 }
351                         } else
352                                 values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionSourceFileName, FormatSourceFile (exc.FileName));
353
354                         if (isCompileException) {
355                                 CompilationException cex = exc as CompilationException;
356                                 StringCollection output = cex.CompilerOutput;
357
358                                 if (output != null && output.Count > 0) {
359                                         pageType |= ExceptionPageTemplateType.CompilerOutput;
360                                         var sb = new StringBuilder ();
361                                         bool first = true;
362                                         foreach (string s in output) {
363                                                 sb.Append (HtmlEncode (s));
364                                                 if (first) {
365                                                         sb.Append ("<br/>");
366                                                         first = false;
367                                                 }
368                                                 sb.Append ("<br/>");
369                                         }
370                                         
371                                         values.Add (ExceptionPageTemplate.Template_HtmlizedExceptionCompilerOutputName, sb.ToString ());
372                                 }
373                         }
374                 }
375                 
376                 void FillDefaultCustomErrorValues (ExceptionPageTemplateValues values)
377                 {
378                         values.Add (ExceptionPageTemplate.Template_PageTitleName, "Runtime Error");
379                         values.Add (ExceptionPageTemplate.Template_ExceptionTypeName, "Runtime Error");
380                         values.Add (ExceptionPageTemplate.Template_ExceptionMessageName, "A runtime error has occurred");
381                         values.Add (ExceptionPageTemplate.Template_DescriptionName, "An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed (for security reasons).");
382                         values.Add (ExceptionPageTemplate.Template_DetailsName, "To enable the details of this specific error message to be viewable, please create a &lt;customErrors&gt; tag within a &quot;web.config&quot; configuration file located in the root directory of the current web application. This &lt;customErrors&gt; tag should then have its &quot;mode&quot; attribute set to &quot;Off&quot;.");
383                 }
384                 
385                 void FillDefaultErrorValues (bool showTrace, bool showExceptionType, Exception baseEx, ExceptionPageTemplateValues values)
386                 {
387                         if (baseEx == null)
388                                 baseEx = this;
389                         
390                         values.Add (ExceptionPageTemplate.Template_PageTitleName, String.Format ("Error{0}", http_code != 0 ? " " + http_code : String.Empty));
391                         values.Add (ExceptionPageTemplate.Template_ExceptionTypeName, showExceptionType ? baseEx.GetType ().ToString () : "Runtime error");
392                         values.Add (ExceptionPageTemplate.Template_ExceptionMessageName, http_code == 404 ? "The resource cannot be found." : HtmlEncode (baseEx.Message));
393
394                         string tmp = http_code != 0 ? "HTTP " + http_code + "." : String.Empty;
395                         values.Add (ExceptionPageTemplate.Template_DescriptionName, tmp + (http_code == 404 ? ERROR_404_DESCRIPTION : HtmlEncode (Description)));
396
397                         if (!String.IsNullOrEmpty (resource_name))
398                                 values.Add (ExceptionPageTemplate.Template_DetailsName, "Requested URL: " + HtmlEncode (resource_name));
399                         else if (http_code == 404)
400                                 values.Add (ExceptionPageTemplate.Template_DetailsName, "No virtual path information available.");
401                         else if (baseEx is HttpException) {
402                                 tmp = ((HttpException)baseEx).Description;
403                                 values.Add (ExceptionPageTemplate.Template_DetailsName, !String.IsNullOrEmpty (tmp) ? HtmlEncode (tmp) : "Web exception occurred but no additional error description given.");
404                         } else {
405                                 var sb = new StringBuilder ("Non-web exception.");
406
407                                 tmp = baseEx.Source;
408                                 if (!String.IsNullOrEmpty (tmp))
409                                         sb.AppendFormat (" Exception origin (name of application or object): {0}.", HtmlEncode (tmp));
410                                 tmp = baseEx.HelpLink;
411                                 if (!String.IsNullOrEmpty (tmp))
412                                         sb.AppendFormat (" Additional information is available at {0}", HtmlEncode (tmp));
413                                 
414                                 values.Add (ExceptionPageTemplate.Template_DetailsName, sb.ToString ());
415                         }
416                         
417                         if (showTrace) {
418                                 string stackTrace = baseEx.StackTrace;
419                                 if (!String.IsNullOrEmpty (stackTrace))
420                                         values.Add (ExceptionPageTemplate.Template_StackTraceName, HtmlEncode (stackTrace));
421                         }
422                 }
423                 
424                 static string HtmlEncode (string s)
425                 {
426                         if (String.IsNullOrEmpty (s))
427                                 return s;
428
429                         string res = HttpUtility.HtmlEncode (s);
430                         return res.Replace ("\r\n", "<br />");
431                 }
432
433                 string FormatSourceFile (string filename)
434                 {
435                         if (filename == null || filename.Length == 0)
436                                 return String.Empty;
437
438                         if (filename.StartsWith ("@@"))
439                                 return "[internal] <!-- " + HttpUtility.HtmlEncode (filename) + " -->";
440
441                         return HttpUtility.HtmlEncode (filename);
442                 }
443                 
444                 static void FormatSource (StringBuilder builder, StringBuilder longVersion, HtmlizedException e)
445                 {
446                         if (e is CompilationException)
447                                 WriteCompilationSource (builder, longVersion, e);
448                         else
449                                 WritePageSource (builder, e);
450                 }
451
452                 static void WriteCompilationSource (StringBuilder builder, StringBuilder longVersion, HtmlizedException e)
453                 {
454                         int [] a = e.ErrorLines;
455                         string s;
456                         int line = 0;
457                         int index = 0;
458                         int errline = 0;
459
460                         if (a != null && a.Length > 0)
461                                 errline = a [0];
462
463                         int begin = errline - 2;
464                         int end = errline + 2;
465
466                         if (begin < 0)
467                                 begin = 0;
468
469                         string tmp;                     
470                         using (TextReader reader = new StringReader (e.FileText)) {
471                                 while ((s = reader.ReadLine ()) != null) {
472                                         line++;
473                                         if (line < begin || line > end) {
474                                                 if (longVersion != null)
475                                                         longVersion.AppendFormat ("{0}: {1}\r\n", line, HtmlEncode (s));
476                                                 continue;
477                                         }
478                                 
479                                         if (errline == line) {
480                                                 if (longVersion != null)
481                                                         longVersion.Append ("<span class=\"sourceErrorLine\">");
482                                                 builder.Append ("<span class=\"sourceErrorLine\">");
483                                         }
484                                         
485                                         tmp = String.Format ("{0}: {1}\r\n", line, HtmlEncode (s));
486                                         builder.Append (tmp);
487                                         if (longVersion != null)
488                                                 longVersion.Append (tmp);
489                                         
490                                         if (line == errline) {
491                                                 builder.Append ("</span>");
492                                                 if (longVersion != null)
493                                                         longVersion.Append ("</span>");
494                                                 errline = (++index < a.Length) ? a [index] : 0;
495                                         }
496                                 }
497                         }                       
498                 }
499
500                 static void WritePageSource (StringBuilder builder, HtmlizedException e)
501                 {
502                         string s;
503                         int line = 0;
504                         int beginerror = e.ErrorLines [0];
505                         int enderror = e.ErrorLines [1];
506                         int begin = beginerror - 2;
507                         int end = enderror + 2;
508                         if (begin <= 0)
509                                 begin = 1;
510                         
511                         TextReader reader = new StringReader (e.FileText);
512                         while ((s = reader.ReadLine ()) != null) {
513                                 line++;
514                                 if (line < begin)
515                                         continue;
516
517                                 if (line > end)
518                                         break;
519
520                                 if (beginerror == line)
521                                         builder.Append ("<span class=\"sourceErrorLine\">");
522
523                                 builder.AppendFormat ("{0}: {1}\r\n", line, HtmlEncode (s));
524
525                                 if (enderror <= line) {
526                                         builder.Append ("</span>");
527                                         enderror = end + 1; // one shot
528                                 }
529                         }
530                 }
531                 
532                 public int GetHttpCode ()
533                 {
534                         return http_code;
535                 }
536
537                 public static HttpException CreateFromLastError (string message)
538                 {
539                         WebTrace.WriteLine ("CreateFromLastError");
540                         return new HttpException (message, 0);
541                 }
542
543                 // Putting this at the end so that the code above isn't bloated
544                 const string DoubleFaultExceptionMessage = @"<?xml version=""1.0"" encoding=""utf-8""?>
545 <!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">
546 <html xmlns=""http://www.w3.org/1999/xhtml"">
547 <head>
548 <style type=""text/css"">
549 body { background-color: #FFFFFF; font-size: .75em; font-family: Verdana, Helvetica, Sans-Serif; margin: 0; padding: 0; color: #696969; }
550 a:link { color: #000000; text-decoration: underline; }
551 a:visited { color: #000000; }
552 a:hover { color: #000000; text-decoration: none; }
553 a:active { color: #12eb87; }
554 p, ul { margin-bottom: 20px; line-height: 1.6em; }
555 pre { font-size: 1.2em; margin-left: 20px; margin-top: 0px; }
556 h1, h2, h3, h4, h5, h6 { font-size: 1.6em; color: #000; font-family: Arial, Helvetica, sans-serif; }
557 h1 { font-weight: bold; margin-bottom: 0; margin-top: 0; padding-bottom: 0; }
558 h2 { font-size: 1em; padding: 0 0 0px 0; color: #696969; font-weight: normal; margin-top: 0; margin-bottom: 20px; }
559 h3 { font-size: 1.2em; }
560 h4 { font-size: 1.1em; }
561 h5, h6 { font-size: 1em; }
562 #header { position: relative; margin-bottom: 0px; color: #000; padding: 0; background-color: #5c87b2; height: 38px; padding-left: 10px; }
563 #header h1 { font-weight: bold; padding: 5px 0; margin: 0; color: #fff; border: none; line-height: 2em; font-family: Arial, Helvetica, sans-serif; font-size: 32px !important; }
564 #header-image { float: left; padding: 3px; margin-left: 1px; margin-right: 1px; }
565 #header-text { color: #fff; font-size: 1.4em; line-height: 38px; font-weight: bold; }
566 #main { padding: 20px 20px 15px 20px; background-color: #fff; _height: 1px; }
567 #footer { color: #999; padding: 5px 0; text-align: left; line-height: normal; margin: 20px 0px 0px 0px; font-size: .9em; border-top: solid 1px #5C87B2; }
568 #footer-powered-by { float: right; }
569 .details { font-family: monospace; border: solid 1px #e8eef4; white-space: pre; font-size: 1.2em; overflow: auto; padding: 6px; margin-top: 6px }
570 .details-wrapped { white-space: normal }
571 .details-header { margin-top: 1.5em }
572 .details-header a { font-weight: bold; text-decoration: none }
573 p { margin-bottom: 0.3em; margin-top: 0.1em }
574 .sourceErrorLine { color: #770000; font-weight: bold; }
575 </style>
576
577 <title>Double fault in exception reporting code</title>
578 </head>
579 <body>
580 <h1>Double fault in exception reporting code</h1>
581 <p>While generating HTML with exception report, a double fault has occurred. Please consult your server's console and/or log file to see the actual exception.</p>
582 </body>
583 </html>
584 ";
585         }
586 }
587