2004-01-06 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[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 //
11 using System;
12 using System.IO;
13 using System.Runtime.Serialization;
14 using System.Runtime.InteropServices;
15 using System.Text;
16 using System.Web.Compilation;
17 using System.Web.Util;
18
19 namespace System.Web
20 {
21 #if NET_1_2
22         [Serializable]
23 #endif
24         public class HttpException : ExternalException
25         {
26                 int http_code = 500;
27                 int hr;
28                 string fileName;
29
30                 public HttpException () : base ()
31                 {
32                 }
33
34                 public HttpException (string sMessage) : base (sMessage)
35                 {
36                 }
37
38                 public HttpException (string sMessage, Exception InnerException)
39                         : base (sMessage, InnerException)
40                 {
41                 }
42
43                 public HttpException (int iHttpCode, string sMessage) : base (sMessage)
44                 {
45                         http_code = iHttpCode;
46                 }
47
48 #if NET_1_2
49                 protected HttpException (SerializationInfo info, StreamingContext sc) : base (info, sc)
50                 {
51                         http_code = info.GetInt32 ("_httpCode");
52                 }
53
54                 public override void GetObjectData (SerializationInfo info, StreamingContext context)
55                 {
56                         base.GetObjectData (info, context);
57                         info.AddValue ("_httpCode", http_code);
58                 }
59 #endif
60
61                 public HttpException (int iHttpCode, string sMessage, int iHR) : base (sMessage)
62                 {
63                         http_code = iHttpCode;
64                         hr = iHR;
65                 }
66
67                 public HttpException (string sMessage, int iHR) : base (sMessage)
68                 {
69                         hr = iHR;
70                 }
71         
72                 public HttpException (int iHttpCode,
73                                       string sMessage,
74                                       Exception InnerException)
75                         : base (sMessage, InnerException)
76                 {
77                         http_code = iHttpCode;
78                 }
79
80                 internal HttpException (string message, string fileName)
81                         : base (message)
82                 {
83                         this.fileName = fileName;
84                         
85                 }
86                 
87                 public string GetHtmlErrorMessage ()
88                 {
89                         if (!(this.InnerException is HtmlizedException))
90                                 return GetDefaultErrorMessage ();
91
92                         return GetHtmlizedErrorMessage ();
93                 }
94
95                 string GetDefaultErrorMessage ()
96                 {
97                         StringBuilder builder = new StringBuilder ("<html>\r\n<title>");
98                         builder.Append ("Error");
99                         if (http_code != 0)
100                                 builder.Append (" " + http_code);
101
102                         builder.AppendFormat ("</title><body bgcolor=\"white\">" + 
103                                               "<h1><font color=\"red\">Server error in '{0}' " + 
104                                               "application</font></h1><hr>\r\n",
105                                               HttpRuntime.AppDomainAppVirtualPath);
106
107                         builder.AppendFormat ("<h2><font color=\"maroon\"><i>{0}</i></font></h2>\r\n", Message);
108                         builder.AppendFormat ("<b>Description: </b>{0}\r\n<p>\r\n", "Error processing request.");
109                         builder.Append ("<b>Error Message: </b>");
110                         if (http_code != 0)
111                                 builder.AppendFormat ("HTTP {0}. ", http_code);
112
113                         builder.AppendFormat ("{0}\r\n<p>\r\n", HtmlEncode (this.Message));
114
115                         if (InnerException != null) {
116                                 builder.AppendFormat ("<b>Stack Trace: </b>");
117                                 builder.Append ("<table summary=\"Stack Trace\" width=\"100%\" " +
118                                                 "bgcolor=\"#ffffc\">\r\n<tr><td>");
119                                 WriteTextAsCode (builder, InnerException.ToString ());
120                                 builder.Append ("</td></tr>\r\n</table>\r\n<p>\r\n");
121                         }
122
123                         builder.Append ("<hr>\r\n</body>\r\n</html>\r\n");
124                         builder.AppendFormat ("<!--\r\n{0}\r\n-->\r\n", HttpUtility.HtmlEncode (this.ToString ()));
125
126                         return builder.ToString ();
127                 }
128
129                 static string HtmlEncode (string s)
130                 {
131                         if (s == null)
132                                 return s;
133
134                         string res = HttpUtility.HtmlEncode (s);
135                         return res.Replace ("\r\n", "<br />");
136                 }
137                 
138                 string GetHtmlizedErrorMessage ()
139                 {
140                         StringBuilder builder = new StringBuilder ("<html>\r\n<title>");
141                         HtmlizedException exc = (HtmlizedException) this.InnerException;
142                         builder.Append (exc.Title);
143                         builder.AppendFormat ("</title><body bgcolor=\"white\">" + 
144                                               "<h1><font color=\"red\">Server Error in '{0}' " + 
145                                               "Application</font></h1><hr>\r\n",
146                                               HttpRuntime.AppDomainAppVirtualPath);
147
148                         builder.AppendFormat ("<h2><font color=\"maroon\"><i>{0}</i></font></h2>\r\n", exc.Title);
149                         builder.AppendFormat ("<b>Description: </b>{0}\r\n<p>\r\n", HtmlEncode (exc.Description));
150                         builder.AppendFormat ("<b>Error message: </b>{0}\r\n<p>\r\n", HtmlEncode (exc.ErrorMessage));
151
152                         if (exc.FileName != null)
153                                 builder.AppendFormat ("<b>File name: </b> {0}", HtmlEncode (exc.FileName));
154
155                         if (exc.FileText != null) {
156                                 if (exc.SourceFile != exc.FileName)
157                                         builder.AppendFormat ("<p><b>Source File: </b>{0}", exc.SourceFile);
158
159                                 if (exc is ParseException) {
160                                         builder.Append ("&nbsp;&nbsp;&nbsp;&nbsp;<b>Line: <b>");
161                                         builder.Append (exc.ErrorLines [0]);
162                                 }
163
164                                 builder.Append ("\r\n<p>\r\n");
165
166                                 if (exc is ParseException) {
167                                         builder.Append ("<b>Source Error: </b>\r\n");
168                                         builder.Append ("<table summary=\"Source error\" width=\"100%\"" +
169                                                         " bgcolor=\"#ffffc\">\r\n<tr><td>");
170                                         WriteSource (builder, exc);
171                                         builder.Append ("</td></tr>\r\n</table>\r\n<p>\r\n");
172                                 } else {
173                                         builder.Append ("<table summary=\"Source file\" width=\"100%\" " +
174                                                         "bgcolor=\"#ffffc\">\r\n<tr><td>");
175                                         WriteSource (builder, exc);
176                                         builder.Append ("</td></tr>\r\n</table>\r\n<p>\r\n");
177                                 }
178                         }
179                         
180                         builder.Append ("<hr>\r\n</body>\r\n</html>\r\n");
181                         builder.AppendFormat ("<!--\r\n{0}\r\n-->\r\n", HtmlEncode (exc.ToString ()));
182                         return builder.ToString ();
183                 }
184
185                 static void WriteTextAsCode (StringBuilder builder, string text)
186                 {
187                         builder.Append ("<code><pre>\r\n");
188                         builder.AppendFormat ("{0}", HtmlEncode (text));
189                         builder.Append ("</pre></code>\r\n");
190                 }
191
192                 static void WriteSource (StringBuilder builder, HtmlizedException e)
193                 {
194                         builder.Append ("<code><pre>");
195                         if (e is CompilationException)
196                                 WriteCompilationSource (builder, e);
197                         else
198                                 WritePageSource (builder, e);
199
200                         builder.Append ("</pre></code>\r\n");
201                 }
202                 
203                 static void WriteCompilationSource (StringBuilder builder, HtmlizedException e)
204                 {
205                         int [] a = e.ErrorLines;
206                         string s;
207                         int line = 0;
208                         int index = 0;
209                         int errline = 0;
210
211                         if (a != null && a.Length > 0)
212                                 errline = a [0];
213                         
214                         TextReader reader = new StringReader (e.FileText);
215                         while ((s = reader.ReadLine ()) != null) {
216                                 line++;
217
218                                 if (errline == line)
219                                         builder.Append ("<span style=\"color: red\">");
220
221                                 builder.AppendFormat ("Line {0}: {1}\r\n", line, HtmlEncode (s));
222
223                                 if (line == errline) {
224                                         builder.Append ("</span>");
225                                         errline = (++index < a.Length) ? a [index] : 0;
226                                 }
227                         }
228                 }
229
230                 static void WritePageSource (StringBuilder builder, HtmlizedException e)
231                 {
232                         string s;
233                         int line = 0;
234                         int beginerror = e.ErrorLines [0];
235                         int enderror = e.ErrorLines [1];
236                         int begin = beginerror - 3;
237                         int end = enderror + 3;
238                         if (begin <= 0)
239                                 begin = 1;
240                         
241                         TextReader reader = new StringReader (e.FileText);
242                         while ((s = reader.ReadLine ()) != null) {
243                                 line++;
244                                 if (line < begin)
245                                         continue;
246
247                                 if (line > end)
248                                         break;
249
250                                 if (beginerror == line)
251                                         builder.Append ("<span style=\"color: red\">");
252
253                                 builder.AppendFormat ("{0}\r\n", HtmlEncode (s));
254
255                                 if (enderror <= line) {
256                                         builder.Append ("</span>");
257                                         enderror = end + 1; // one shot
258                                 }
259                         }
260                 }
261                 
262                 [MonoTODO("Check error type and Set the correct error code")]
263                 public int GetHttpCode ()
264                 {
265                         return http_code;
266                 }
267
268                 public static HttpException CreateFromLastError (string message)
269                 {
270                         WebTrace.WriteLine ("CreateFromLastError");
271                         return new HttpException (message, 0);
272                 }
273         }
274 }
275