merge -r 58060:58217
[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 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 #if !TARGET_J2EE
39 using System.Web.Compilation;
40 #endif
41
42 namespace System.Web
43 {
44         // CAS
45         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47 #if NET_2_0
48         [Serializable]
49 #endif
50         public class HttpException : ExternalException
51         {
52                 int http_code = 500;
53
54                 public HttpException ()
55                 {
56                 }
57
58                 public HttpException (string message)
59                         : base (message)
60                 {
61                 }
62
63                 public HttpException (string message, Exception innerException)
64                         : base (message, innerException)
65                 {
66                 }
67
68                 public HttpException (int httpCode, string message) : base (message)
69                 {
70                         http_code = httpCode;
71                 }
72
73 #if NET_2_0
74                 protected HttpException (SerializationInfo info, StreamingContext context)
75                         : base (info, context)
76                 {
77                         http_code = info.GetInt32 ("_httpCode");
78                 }
79
80                 [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
81                 public override void GetObjectData (SerializationInfo info, StreamingContext context)
82                 {
83                         base.GetObjectData (info, context);
84                         info.AddValue ("_httpCode", http_code);
85                 }
86 #endif
87
88                 public HttpException (int httpCode, string message, int hr) 
89                         : base (message, hr)
90                 {
91                         http_code = httpCode;
92                 }
93
94                 public HttpException (string message, int hr)
95                         : base (message, hr)
96                 {
97                 }
98         
99                 public HttpException (int httpCode, string message, Exception innerException)
100                         : base (message, innerException)
101                 {
102                         http_code = httpCode;
103                 }
104
105                 public string GetHtmlErrorMessage ()
106                 {
107                         if (!(this.InnerException is HtmlizedException))
108                                 return GetDefaultErrorMessage ();
109
110                         return GetHtmlizedErrorMessage ();
111                 }
112
113                 internal virtual string Description {
114                         get { return "Error processing request."; }
115                 }
116                 
117                 string GetDefaultErrorMessage ()
118                 {
119                         StringBuilder builder = new StringBuilder ("<html>\r\n<title>");
120                         builder.Append ("Error");
121                         if (http_code != 0)
122                                 builder.Append (" " + http_code);
123
124                         builder.AppendFormat ("</title><body bgcolor=\"white\">" + 
125                                               "<h1><font color=\"red\">Server error in '{0}' " + 
126                                               "application</font></h1><hr>\r\n",
127                                               HtmlEncode (HttpRuntime.AppDomainAppVirtualPath));
128
129                         builder.AppendFormat ("<h2><font color=\"maroon\"><i>{0}</i></font></h2>\r\n",
130                                               HtmlEncode (Message));
131
132                         builder.AppendFormat ("<b>Description: </b>{0}\r\n<p>\r\n", Description);
133                         builder.Append ("<b>Error Message: </b>");
134                         if (http_code != 0)
135                                 builder.AppendFormat ("HTTP {0}. ", http_code);
136
137                         builder.AppendFormat ("{0}\r\n<p>\r\n", HtmlEncode (this.Message));
138
139                         if (InnerException != null) {
140                                 builder.AppendFormat ("<b>Stack Trace: </b>");
141                                 builder.Append ("<table summary=\"Stack Trace\" width=\"100%\" " +
142                                                 "bgcolor=\"#ffffc\">\r\n<tr><td>");
143                                 WriteTextAsCode (builder, InnerException.ToString ());
144 #if TARGET_J2EE //Required, because toString of Java doesn't print stackTrace
145                                 WriteTextAsCode (builder, InnerException.StackTrace);
146 #endif
147                                 builder.Append ("</td></tr>\r\n</table>\r\n<p>\r\n");
148                         }
149
150                         builder.Append ("<hr>\r\n</body>\r\n</html>\r\n");
151                         builder.AppendFormat ("<!--\r\n{0}\r\n-->\r\n", HttpUtility.HtmlEncode (this.ToString ()));
152 #if TARGET_J2EE //Required, because toString of Java doesn't print stackTrace
153                         builder.AppendFormat ("<!--\r\n{0}\r\n-->\r\n", HttpUtility.HtmlEncode (this.StackTrace));
154 #endif
155
156                         return builder.ToString ();
157                 }
158
159                 static string HtmlEncode (string s)
160                 {
161                         if (s == null)
162                                 return s;
163
164                         string res = HttpUtility.HtmlEncode (s);
165                         return res.Replace ("\r\n", "<br />");
166                 }
167 #if TARGET_J2EE
168                 string GetHtmlizedErrorMessage ()
169                 {
170                         StringBuilder builder = new StringBuilder ("<html>\r\n<title>");
171                         HtmlizedException exc = (HtmlizedException) this.InnerException;
172                         builder.Append (exc.Title);
173                         builder.AppendFormat ("</title><body bgcolor=\"white\">" +
174                                               "<h1><font color=\"red\">Server Error in '{0}' " +
175                                               "Application</font></h1><hr>\r\n",
176                                               HttpRuntime.AppDomainAppVirtualPath);
177                 
178                         builder.AppendFormat ("<h2><font color=\"maroon\"><i>{0}</i></font></h2>\r\n", exc.Title);
179                         builder.AppendFormat ("<b>Description: </b>{0}\r\n<p>\r\n", HtmlEncode (exc.Description));
180                         builder.AppendFormat ("<b>Error message: </b>{0}\r\n<p>\r\n", HtmlEncode (exc.ErrorMessage));
181
182                         if (exc.FileName != null)
183                                 builder.AppendFormat ("<b>File name: </b> {0}", HtmlEncode (exc.FileName));
184
185                         if (exc.FileText != null) {
186                                 if (exc.SourceFile != exc.FileName)
187                                         builder.AppendFormat ("<p><b>Source File: </b>{0}", exc.SourceFile);
188
189                                 builder.Append ("\r\n<p>\r\n");
190
191                                 builder.Append ("<table summary=\"Source file\" width=\"100%\" " +
192                                                         "bgcolor=\"#ffffc\">\r\n<tr><td>");
193                                         WriteSource (builder, exc);
194                                         builder.Append ("</td></tr>\r\n</table>\r\n<p>\r\n");
195                         }
196
197                         builder.Append ("<hr>\r\n</body>\r\n</html>\r\n");
198                         builder.AppendFormat ("<!--\r\n{0}\r\n-->\r\n", HtmlEncode (exc.ToString ()));
199                         builder.AppendFormat ("<!--\r\n{0}\r\n-->\r\n", HtmlEncode (exc.StackTrace));
200                         return builder.ToString ();
201                 }
202 #else
203                 string GetHtmlizedErrorMessage ()
204                 {
205                         StringBuilder builder = new StringBuilder ("<html>\r\n<title>");
206                         HtmlizedException exc = (HtmlizedException) this.InnerException;
207                         builder.Append (exc.Title);
208                         builder.AppendFormat ("</title><body bgcolor=\"white\">" + 
209                                               "<h1><font color=\"red\">Server Error in '{0}' " + 
210                                               "Application</font></h1><hr>\r\n",
211                                               HttpRuntime.AppDomainAppVirtualPath);
212
213                         builder.AppendFormat ("<h2><font color=\"maroon\"><i>{0}</i></font></h2>\r\n", exc.Title);
214                         builder.AppendFormat ("<b>Description: </b>{0}\r\n<p>\r\n", HtmlEncode (exc.Description));
215                         builder.AppendFormat ("<b>Error message: </b>{0}\r\n<p>\r\n", HtmlEncode (exc.ErrorMessage));
216
217                         if (exc.FileName != null)
218                                 builder.AppendFormat ("<b>File name: </b> {0}", HtmlEncode (exc.FileName));
219
220                         if (exc.FileText != null) {
221                                 if (exc.SourceFile != exc.FileName)
222                                         builder.AppendFormat ("<p><b>Source File: </b>{0}", exc.SourceFile);
223
224                                 if (exc is ParseException) {
225                                         builder.Append ("&nbsp;&nbsp;&nbsp;&nbsp;<b>Line: <b>");
226                                         builder.Append (exc.ErrorLines [0]);
227                                 }
228
229                                 builder.Append ("\r\n<p>\r\n");
230
231                                 if (exc is ParseException) {
232                                         builder.Append ("<b>Source Error: </b>\r\n");
233                                         builder.Append ("<table summary=\"Source error\" width=\"100%\"" +
234                                                         " bgcolor=\"#ffffc\">\r\n<tr><td>");
235                                         WriteSource (builder, exc);
236                                         builder.Append ("</td></tr>\r\n</table>\r\n<p>\r\n");
237                                 } else {
238                                         builder.Append ("<table summary=\"Source file\" width=\"100%\" " +
239                                                         "bgcolor=\"#ffffc\">\r\n<tr><td>");
240                                         WriteSource (builder, exc);
241                                         builder.Append ("</td></tr>\r\n</table>\r\n<p>\r\n");
242                                 }
243                         }
244                         
245                         builder.Append ("<hr>\r\n</body>\r\n</html>\r\n");
246                         builder.AppendFormat ("<!--\r\n{0}\r\n-->\r\n", HtmlEncode (exc.ToString ()));
247                         return builder.ToString ();
248                 }
249 #endif
250                 static void WriteTextAsCode (StringBuilder builder, string text)
251                 {
252                         builder.Append ("<code><pre>\r\n");
253                         builder.AppendFormat ("{0}", HtmlEncode (text));
254                         builder.Append ("</pre></code>\r\n");
255                 }
256
257 #if TARGET_J2EE
258                 static void WriteSource (StringBuilder builder, HtmlizedException e)
259                 {
260                         builder.Append ("<code><pre>");
261                         WritePageSource (builder, e);
262                         builder.Append ("</pre></code>\r\n");
263                 }
264
265 #else
266                 static void WriteSource (StringBuilder builder, HtmlizedException e)
267                 {
268                         builder.Append ("<code><pre>");
269                         if (e is CompilationException)
270                                 WriteCompilationSource (builder, e);
271                         else
272                                 WritePageSource (builder, e);
273
274                         builder.Append ("</pre></code>\r\n");
275                 }
276 #endif
277                 
278                 static void WriteCompilationSource (StringBuilder builder, HtmlizedException e)
279                 {
280                         int [] a = e.ErrorLines;
281                         string s;
282                         int line = 0;
283                         int index = 0;
284                         int errline = 0;
285
286                         if (a != null && a.Length > 0)
287                                 errline = a [0];
288                         
289                         TextReader reader = new StringReader (e.FileText);
290                         while ((s = reader.ReadLine ()) != null) {
291                                 line++;
292
293                                 if (errline == line)
294                                         builder.Append ("<span style=\"color: red\">");
295
296                                 builder.AppendFormat ("Line {0}: {1}\r\n", line, HtmlEncode (s));
297
298                                 if (line == errline) {
299                                         builder.Append ("</span>");
300                                         errline = (++index < a.Length) ? a [index] : 0;
301                                 }
302                         }
303                 }
304
305                 static void WritePageSource (StringBuilder builder, HtmlizedException e)
306                 {
307                         string s;
308                         int line = 0;
309                         int beginerror = e.ErrorLines [0];
310                         int enderror = e.ErrorLines [1];
311                         int begin = beginerror - 3;
312                         int end = enderror + 3;
313                         if (begin <= 0)
314                                 begin = 1;
315                         
316                         TextReader reader = new StringReader (e.FileText);
317                         while ((s = reader.ReadLine ()) != null) {
318                                 line++;
319                                 if (line < begin)
320                                         continue;
321
322                                 if (line > end)
323                                         break;
324
325                                 if (beginerror == line)
326                                         builder.Append ("<span style=\"color: red\">");
327
328                                 builder.AppendFormat ("{0}\r\n", HtmlEncode (s));
329
330                                 if (enderror <= line) {
331                                         builder.Append ("</span>");
332                                         enderror = end + 1; // one shot
333                                 }
334                         }
335                 }
336                 
337                 public int GetHttpCode ()
338                 {
339                         return http_code;
340                 }
341
342                 public static HttpException CreateFromLastError (string message)
343                 {
344                         WebTrace.WriteLine ("CreateFromLastError");
345                         return new HttpException (message, 0);
346                 }
347         }
348 }
349