[asp.net] Cosmetics to make code a bit more efficient
[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                 
58                 const string errorStyleFonts = "\"Verdana\",\"DejaVu Sans\",sans-serif";
59
60 #if NET_4_0
61                 public
62 #else
63                 internal
64 #endif
65                 int WebEventCode 
66                 {
67                         get { return webEventCode; }
68                 }
69                 
70                 public HttpException ()
71                 {
72                 }
73
74                 public HttpException (string message)
75                         : base (message)
76                 {
77                 }
78
79                 public HttpException (string message, Exception innerException)
80                         : base (message, innerException)
81                 {
82                 }
83
84                 public HttpException (int httpCode, string message) : base (message)
85                 {
86                         http_code = httpCode;
87                 }
88
89                 internal HttpException (int httpCode, string message, string resourceName) : this (httpCode, message)
90                 {
91                         resource_name = resourceName;
92                 }
93
94                 internal HttpException (int httpCode, string message, string resourceName, string description) : this (httpCode, message, resourceName)
95                 {
96                         this.description = description;
97                 }
98                 
99                 protected HttpException (SerializationInfo info, StreamingContext context)
100                         : base (info, context)
101                 {
102                         http_code = info.GetInt32 ("_httpCode");
103                         webEventCode = info.GetInt32 ("_webEventCode");
104                 }
105
106                 [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
107                 public override void GetObjectData (SerializationInfo info, StreamingContext context)
108                 {
109                         base.GetObjectData (info, context);
110                         info.AddValue ("_httpCode", http_code);
111                         info.AddValue ("_webEventCode", webEventCode);
112                 }
113
114                 public HttpException (int httpCode, string message, int hr) 
115                         : base (message, hr)
116                 {
117                         http_code = httpCode;
118                 }
119
120                 public HttpException (string message, int hr)
121                         : base (message, hr)
122                 {
123                 }
124         
125                 public HttpException (int httpCode, string message, Exception innerException)
126                         : base (message, innerException)
127                 {
128                         http_code = httpCode;
129                 }
130
131                 internal HttpException (int httpCode, string message, Exception innerException, string resourceName)
132                         : this (httpCode, message, innerException)
133                 {
134                         resource_name = resourceName;
135                 }
136                 
137                 public string GetHtmlErrorMessage ()
138                 {
139                         try {
140                                 HttpContext ctx = HttpContext.Current;
141                                 if (ctx != null && ctx.IsCustomErrorEnabled) {
142                                         if (http_code != 404 && http_code != 403)
143                                                 return GetCustomErrorDefaultMessage ();
144                                         else
145                                                 return GetDefaultErrorMessage (false, null);
146                                 }
147                                 
148                                 Exception ex = GetBaseException ();
149                                 if (ex == null)
150                                         ex = this;
151                                 
152                                 HtmlizedException htmlException = ex  as HtmlizedException;
153                                 if (htmlException == null)
154                                         return GetDefaultErrorMessage (true, ex);
155                                 
156                                 return GetHtmlizedErrorMessage (htmlException);
157                         } catch (Exception ex) {
158                                 Console.WriteLine (ex);
159                                 
160                                 // we need the try/catch block in case the
161                                 // problem was with MapPath, which will cause
162                                 // IsCustomErrorEnabled to throw an exception
163                                 return GetCustomErrorDefaultMessage ();
164                         }
165                 }
166
167                 internal virtual string Description {
168                         get {
169                                 if (description != null)
170                                         return description;
171
172                                 return DEFAULT_DESCRIPTION_TEXT;
173                         }
174                         
175                         set {
176                                 if (value != null && value.Length > 0)
177                                         description = value;
178                                 else
179                                         description = DEFAULT_DESCRIPTION_TEXT;
180                         }
181                 }
182
183                 internal static HttpException NewWithCode (string message, int webEventCode)
184                 {
185                         var ret = new HttpException (message);
186                         ret.SetWebEventCode (webEventCode);
187
188                         return ret;
189                 }
190
191                 internal static HttpException NewWithCode (string message, Exception innerException, int webEventCode)
192                 {
193                         var ret = new HttpException (message, innerException);
194                         ret.SetWebEventCode (webEventCode);
195
196                         return ret;
197                 }
198
199                 internal static HttpException NewWithCode (int httpCode, string message, int webEventCode)
200                 {
201                         var ret = new HttpException (httpCode, message);
202                         ret.SetWebEventCode (webEventCode);
203
204                         return ret;
205                 }
206                 
207                 internal static HttpException NewWithCode (int httpCode, string message, Exception innerException, string resourceName, int webEventCode)
208                 {
209                         var ret = new HttpException (httpCode, message, innerException, resourceName);
210                         ret.SetWebEventCode (webEventCode);
211
212                         return ret;
213                 }
214
215                 internal static HttpException NewWithCode (int httpCode, string message, string resourceName, int webEventCode)
216                 {
217                         var ret = new HttpException (httpCode, message, resourceName);
218                         ret.SetWebEventCode (webEventCode);
219
220                         return ret;
221                 }
222
223                 internal static HttpException NewWithCode (int httpCode, string message, Exception innerException, int webEventCode)
224                 {
225                         var ret = new HttpException (httpCode, message, innerException);
226                         ret.SetWebEventCode (webEventCode);
227
228                         return ret;
229                 }
230                 
231                 internal void SetWebEventCode (int webEventCode)
232                 {
233                         this.webEventCode = webEventCode;
234                 }
235                 
236                 void WriteFileTop (StringBuilder builder, string title)
237                 {
238 #if TARGET_J2EE
239                         builder.AppendFormat ("<html><head><title>{0}</title><style type=\"text/css\">", title);
240                         builder.AppendFormat (
241                                 @"body {{font-family:{0};font-weight:normal;font-size: 9pt;color:black;background-color: white}}
242 p {{font-family:{0};font-weight:normal;color:black;margin-top: -5px}}
243 b {{font-family:{0};font-weight:bold;color:black;margin-top: -5px}}
244 h1 {{ font-family:{0};font-weight:normal;font-size:18pt;color:red }}
245 h2 {{ font-family:{0};font-weight:normal;font-size:14pt;color:maroon }}
246 pre {{font-family:""Lucida Console"",""DejaVu Sans Mono"",monospace;font-size: 10pt}}
247 div.bodyText {{font-family: {0}}}
248 table.sampleCode {{width: 100%; background-color: #ffffcc; }}
249 .errorText {{color: red; font-weight: bold}}
250 .marker {{font-weight: bold; color: black;text-decoration: none;}}
251 .version {{color: gray;}}
252 .error {{margin-bottom: 10px;}}
253 .expandable {{ text-decoration:underline; font-weight:bold; color:navy; cursor:pointer; }}", errorStyleFonts);
254 #else
255                         builder.Append ("<?xml version=\"1.0\" ?>\n");
256                         builder.Append ("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
257                         builder.AppendFormat ("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"><head><title>{0}</title><style type=\"text/css\">", title);
258                         builder.AppendFormat (
259                                 @"body {{font-family:{0};font-weight:normal;font-size: .7em;color:black;background-color: white}}
260 p {{font-family:{0};font-weight:normal;color:black;margin-top: -5px}}
261 b {{font-family:{0};font-weight:bold;color:black;margin-top: -5px}}
262 h1 {{ font-family:{0};font-weight:normal;font-size:18pt;color:red }}
263 h2 {{ font-family:{0};font-weight:normal;font-size:14pt;color:maroon }}
264 pre,code {{font-family:""Lucida Console"",""DejaVu Sans Mono"",monospace;font-size: 0.9em,white-space: pre-line}}
265 div.bodyText {{font-family: {0}}}
266 table.sampleCode {{width: 100%; background-color: #ffffcc; }}
267 .errorText {{color: red; font-weight: bold}}
268 .marker {{font-weight: bold; color: black;text-decoration: none;}}
269 .version {{color: gray;}}
270 .error {{margin-bottom: 10px;}}
271 .expandable {{ text-decoration:underline; font-weight:bold; color:navy; cursor:pointer; }}", errorStyleFonts);
272 #endif
273
274                         builder.AppendFormat (
275                                 "</style></head><body><h1>Server Error in '{0}' Application</h1><hr style=\"color: silver\"/>",
276                                 HtmlEncode (HttpRuntime.AppDomainAppVirtualPath));
277                 }
278                 
279                 void WriteFileBottom (StringBuilder builder, bool showTrace)
280                 {
281                         if (showTrace) {
282                                 builder.Append ("<hr style=\"color: silver\"/>");
283                                 builder.AppendFormat ("<strong>Version information: </strong> Mono Runtime Version: <tt>{0}</tt>; ASP.NET Version: <tt>{1}</tt></body></html>\r\n",
284                                                       RuntimeHelpers.MonoVersion, Environment.Version);
285                         
286                                 string trace, message;
287                                 bool haveTrace;
288                                 Exception ex = this;
289
290                                 builder.Append ("\r\n<!--");
291                                 while (ex != null) {
292                                         trace = ex.StackTrace;
293                                         message = ex.Message;
294                                         haveTrace = (trace != null && trace.Length > 0);
295                                 
296                                         if (!haveTrace && (message == null || message.Length == 0)) {
297                                                 ex = ex.InnerException;
298                                                 continue;
299                                         }
300
301                                         builder.Append ("\r\n[" + ex.GetType () + "]: " + HtmlEncode (message) + "\r\n");
302                                         if (haveTrace)
303                                                 builder.Append (ex.StackTrace);
304                                 
305                                         ex = ex.InnerException;
306                                 }
307                         
308                                 builder.Append ("\r\n-->");
309                         } else
310                                 builder.Append ("</body></html>\r\n");
311                 }
312
313                 string GetCustomErrorDefaultMessage ()
314                 {
315                         StringBuilder builder = new StringBuilder ();
316                         WriteFileTop (builder, "Runtime Error");
317 #if TARGET_J2EE //on portal we cannot know if we run locally
318                         if (!HttpContext.Current.IsServletRequest)
319                                 builder.Append (
320 @"<p><strong>Description:</strong> 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).</p>
321 <p><strong>Details:</strong> 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;.</p>
322 <table class=""sampleCode""><tr><td><pre>
323
324 &lt;!-- Web.Config Configuration File --&gt;
325
326 &lt;configuration&gt;
327     &lt;system.web&gt;
328
329         &lt;customErrors mode=&quot;Off&quot;/&gt;
330     &lt;/system.web&gt;
331 &lt;/configuration&gt;</pre>
332     </td></tr></table><br/>
333 ");
334                         else
335 #endif
336                         builder.Append (@"<p><strong>Description:</strong> 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 remotely (for security reasons)." + (
337                                 " It could, however, be viewed by browsers running on the local server machine.") 
338                                 + @"</p>
339 <p><strong>Details:</strong> To enable the details of this specific error message to be viewable on remote machines, 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;.</p>
340 <table class=""sampleCode""><tr><td><pre>
341
342 &lt;!-- Web.Config Configuration File --&gt;
343
344 &lt;configuration&gt;
345     &lt;system.web&gt;
346
347         &lt;customErrors mode=&quot;Off&quot;/&gt;
348     &lt;/system.web&gt;
349 &lt;/configuration&gt;</pre>
350     </td></tr></table><br/>
351 <p><strong>Notes:</strong> The current error page you are seeing can be replaced by a custom error page by modifying the &quot;defaultRedirect&quot; attribute of the application's &lt;customErrors&gt; configuration tag to point to a custom error page URL.</p>
352 <table class=""sampleCode""><tr><td><pre>
353 &lt;!-- Web.Config Configuration File --&gt;
354
355 &lt;configuration&gt;
356     &lt;system.web&gt;
357         &lt;customErrors mode=&quot;RemoteOnly&quot; defaultRedirect=&quot;mycustompage.htm&quot;/&gt;
358
359     &lt;/system.web&gt;
360 &lt;/configuration&gt;</pre></td></tr></table>");
361                         WriteFileBottom (builder, false);
362                         return builder.ToString ();
363                 }
364                 
365                 string GetDefaultErrorMessage (bool showTrace, Exception baseEx)
366                 {
367                         Exception ex;
368                         ex = baseEx;
369                         if (ex == null)
370                                 ex = this;
371
372                         StringBuilder builder = new StringBuilder ();
373                         WriteFileTop (builder, String.Format ("Error{0}", http_code != 0 ? " " + http_code : String.Empty));
374                         builder.Append ("<h2><em>");
375                         if (http_code == 404)
376                                 builder.Append ("The resource cannot be found.");
377                         else
378                                 builder.Append (HtmlEncode (ex.Message));
379                         builder.Append ("</em></h2>\r\n<p><strong>Description: </strong>");
380                         
381                         if (http_code != 0)
382                                 builder.AppendFormat ("HTTP {0}. ", http_code);
383                         builder.Append (http_code == 404 ? ERROR_404_DESCRIPTION : HtmlEncode (Description));
384                         builder.Append ("</p>\r\n");
385
386                         if (resource_name != null && resource_name.Length > 0)
387                                 builder.AppendFormat ("<p><strong>Requested URL: </strong>{0}</p>\r\n", resource_name);
388                         
389                         if (showTrace && baseEx != null && http_code != 404 && http_code != 403) {
390                                 builder.Append ("<p><strong>Stack Trace: </strong></p>");
391                                 builder.Append ("<table summary=\"Stack Trace\" class=\"sampleCode\">\r\n<tr><td>");
392                                 WriteTextAsCode (builder, baseEx.ToString ());
393                                 builder.Append ("</td></tr>\r\n</table>\r\n");
394                         }
395                         WriteFileBottom (builder, showTrace);
396                         
397                         return builder.ToString ();
398                 }
399
400                 static string HtmlEncode (string s)
401                 {
402                         if (s == null)
403                                 return s;
404
405                         string res = HttpUtility.HtmlEncode (s);
406                         return res.Replace ("\r\n", "<br />");
407                 }
408
409                 string FormatSourceFile (string filename)
410                 {
411                         if (filename == null || filename.Length == 0)
412                                 return String.Empty;
413
414                         if (filename.StartsWith ("@@"))
415                                 return "[internal] <!-- " + filename + " -->";
416
417                         return filename;
418                 }
419                 
420                 string GetHtmlizedErrorMessage (HtmlizedException exc)
421                 {
422                         StringBuilder builder = new StringBuilder ();
423 #if TARGET_J2EE
424                         bool isParseException = false;
425                         bool isCompileException = false;
426 #else
427                         bool isParseException = exc is ParseException;
428                         bool isCompileException = (!isParseException && exc is CompilationException);
429 #endif
430                         
431                         WriteFileTop (builder, exc.Title);
432                         builder.AppendFormat ("<h2><em>{0}</em></h2>\r\n", exc.Title);
433                         builder.AppendFormat ("<p><strong>Description: </strong>{0}\r\n</p>\r\n", HtmlEncode (exc.Description));
434                         string errorMessage = HtmlEncode (exc.ErrorMessage);
435                         
436                         builder.Append ("<p><strong>");
437                         if (isParseException)
438                                 builder.Append ("Parser ");
439                         else if (isCompileException)
440                                 builder.Append ("Compiler ");
441                         
442                         builder.Append ("Error Message: </strong>");
443                         builder.AppendFormat ("<code>{0}</code></p>", errorMessage);
444
445                         StringBuilder longCodeVersion = null;
446                         
447                         if (exc.FileText != null) {
448                                 if (isParseException || isCompileException) {
449                                         builder.Append ("<p><strong>Source Error: </strong></p>\r\n");
450                                         builder.Append ("<table summary=\"Source error\" class=\"sampleCode\">\r\n<tr><td>");
451
452                                         if (isCompileException)
453                                                 longCodeVersion = new StringBuilder ();
454                                         WriteSource (builder, longCodeVersion, exc);
455                                         builder.Append ("</pre></code></td></tr>\r\n</table>\r\n");
456                                 } else {
457                                         builder.Append ("<table summary=\"Source file\" class=\"sampleCode\">\r\n<tr><td>");
458                                         WriteSource (builder, null, exc);
459                                         builder.Append ("</pre></code></td></tr>\r\n</table>\r\n");
460                                 }
461
462                                 builder.Append ("<br/><p><strong>Source File: </strong>");
463                                 if (exc.SourceFile != exc.FileName)
464                                         builder.Append (FormatSourceFile (exc.SourceFile));
465                                 else
466                                         builder.Append (FormatSourceFile (exc.FileName));
467
468                                 if (isParseException || isCompileException) {
469                                         int[] errorLines = exc.ErrorLines;
470                                         int numErrors = errorLines != null ? errorLines.Length : 0;
471                                         if (numErrors > 0) {
472                                                 builder.AppendFormat ("&nbsp;&nbsp;<strong>Line{0}: </strong>", numErrors > 1 ? "s" : String.Empty);
473                                                 for (int i = 0; i < numErrors; i++) {
474                                                         if (i > 0)
475                                                                 builder.Append (", ");
476                                                         builder.Append (exc.ErrorLines [i]);
477                                                 }
478                                         }
479                                 }
480                                 builder.Append ("</p>");
481                         } else if (exc.FileName != null)
482                                 builder.AppendFormat ("{0}</p>", HtmlEncode (exc.FileName));
483
484                         bool needToggleJS = false;
485                         
486 #if !TARGET_J2EE
487                         if (isCompileException) {
488                                 CompilationException cex = exc as CompilationException;
489                                 StringCollection output = cex.CompilerOutput;
490
491                                 if (output != null && output.Count > 0) {
492                                         needToggleJS = true;
493                                         StringBuilder sb = new StringBuilder ();
494                                         foreach (string s in output)
495                                                 sb.Append (s + "\r\n");
496                                         WriteExpandableBlock (builder, "compilerOutput", "Show Detailed Compiler Output", sb.ToString ());
497                                 }
498                         }
499 #endif
500                         
501                         if (longCodeVersion != null && longCodeVersion.Length > 0) {
502                                 WriteExpandableBlock (builder, "fullCode", "Show Complete Compilation Source", longCodeVersion.ToString ());
503                                 needToggleJS = true;
504                         }
505
506                         if (needToggleJS)
507                                 builder.Append ("<script type=\"text/javascript\">\r\n" +
508                                                 "function ToggleVisible (id)\r\n" +
509                                                 "{\r\n" +
510                                                 "\tvar e = document.getElementById (id);\r\n" +
511                                                 "\tif (e.style.display == 'none')\r\n" +
512                                                 "\t{\r\n" +
513                                                 "\t\te.style.display = '';\r\n" +
514                                                 "\t} else {\r\n" +
515                                                 "\t\te.style.display = 'none';\r\n" +
516                                                 "\t}\r\n" +
517                                                 "}\r\n" +
518                                                 "</script>\r\n");
519                         
520                         WriteFileBottom (builder, true);
521                         
522                         return builder.ToString ();
523                 }
524
525                 static void WriteExpandableBlock (StringBuilder builder, string id, string title, string contents)
526                 {
527                         builder.AppendFormat ("<br><div class=\"expandable\" onclick=\"ToggleVisible ('{1}')\">{0}:</div><br/>" +
528                                               "<div id=\"{1}\" style=\"display: none\"><table summary=\"Details\" class=\"sampleCode\"><tr><td>" +
529                                               "<code><pre>\r\n", title, id);
530                         builder.Append (contents);
531                         builder.Append ("</pre></code></td></tr></table></div>");
532                 }
533                 
534                 static void WriteTextAsCode (StringBuilder builder, string text)
535                 {
536                         builder.AppendFormat ("<pre>{0}</pre>", HtmlEncode (text));
537                 }
538
539 #if TARGET_J2EE
540                 static void WriteSource (StringBuilder builder, StringBuilder longVersion, HtmlizedException e)
541                 {
542                         builder.Append ("<code><pre>");
543                         WritePageSource (builder, e);
544                         builder.Append ("</code></pre>\r\n");
545                 }
546
547 #else
548                 static void WriteSource (StringBuilder builder, StringBuilder longVersion, HtmlizedException e)
549                 {
550                         builder.Append ("<code><pre>");
551                         if (e is CompilationException)
552                                 WriteCompilationSource (builder, longVersion, e);
553                         else
554                                 WritePageSource (builder, e);
555
556                         builder.Append ("<code></pre>\r\n");
557                 }
558 #endif
559                 
560                 static void WriteCompilationSource (StringBuilder builder, StringBuilder longVersion, HtmlizedException e)
561                 {
562                         int [] a = e.ErrorLines;
563                         string s;
564                         int line = 0;
565                         int index = 0;
566                         int errline = 0;
567
568                         if (a != null && a.Length > 0)
569                                 errline = a [0];
570
571                         int begin = errline - 2;
572                         int end = errline + 2;
573
574                         if (begin < 0)
575                                 begin = 0;
576
577                         string tmp;                     
578                         using (TextReader reader = new StringReader (e.FileText)) {
579                                 while ((s = reader.ReadLine ()) != null) {
580                                         line++;
581                                         if (line < begin || line > end) {
582                                                 if (longVersion != null)
583                                                         longVersion.AppendFormat ("Line {0}: {1}\r\n", line, HtmlEncode (s));
584                                                 continue;
585                                         }
586                                 
587                                         if (errline == line) {
588                                                 if (longVersion != null)
589                                                         longVersion.Append ("<span style=\"color: red\">");
590                                                 builder.Append ("<span style=\"color: red\">");
591                                         }
592                                         
593                                         tmp = String.Format ("Line {0}: {1}\r\n", line, HtmlEncode (s));
594                                         builder.Append (tmp);
595                                         if (longVersion != null)
596                                                 longVersion.Append (tmp);
597                                         
598                                         if (line == errline) {
599                                                 builder.Append ("</span>");
600                                                 if (longVersion != null)
601                                                         longVersion.Append ("</span>");
602                                                 errline = (++index < a.Length) ? a [index] : 0;
603                                         }
604                                 }
605                         }                       
606                 }
607
608                 static void WritePageSource (StringBuilder builder, HtmlizedException e)
609                 {
610                         string s;
611                         int line = 0;
612                         int beginerror = e.ErrorLines [0];
613                         int enderror = e.ErrorLines [1];
614                         int begin = beginerror - 2;
615                         int end = enderror + 2;
616                         if (begin <= 0)
617                                 begin = 1;
618                         
619                         TextReader reader = new StringReader (e.FileText);
620                         while ((s = reader.ReadLine ()) != null) {
621                                 line++;
622                                 if (line < begin)
623                                         continue;
624
625                                 if (line > end)
626                                         break;
627
628                                 if (beginerror == line)
629                                         builder.Append ("<span style=\"color: red\">");
630
631                                 builder.AppendFormat ("Line {0}: {1}\r\n", line, HtmlEncode (s));
632
633                                 if (enderror <= line) {
634                                         builder.Append ("</span>");
635                                         enderror = end + 1; // one shot
636                                 }
637                         }
638                 }
639                 
640                 public int GetHttpCode ()
641                 {
642                         return http_code;
643                 }
644
645                 public static HttpException CreateFromLastError (string message)
646                 {
647                         WebTrace.WriteLine ("CreateFromLastError");
648                         return new HttpException (message, 0);
649                 }
650         }
651 }
652