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