2003-10-06 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpUtility.cs
1 // \r
2 // System.Web.HttpUtility\r
3 //\r
4 // Authors:\r
5 //   Patrik Torstensson (Patrik.Torstensson@labs2.com)\r
6 //   Wictor WilĂ©n (decode/encode functions) (wictor@ibizkit.se)\r
7 //   Tim Coleman (tim@timcoleman.com)\r
8 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)\r
9 //\r
10 using System;\r
11 using System.Collections;\r
12 using System.Globalization;\r
13 using System.IO;\r
14 using System.Text;\r
15 using System.Web.Util;\r
16 \r
17 namespace System.Web {\r
18         public sealed class HttpUtility {\r
19 \r
20                 #region Fields\r
21         \r
22                 const string _hex = "0123456789ABCDEF";\r
23                 const string _chars = "<>;:.?=&@*+%/\\";\r
24                 static Hashtable entities;\r
25         \r
26                 #endregion // Fields\r
27         \r
28                 #region Constructors\r
29 \r
30                 static HttpUtility ()\r
31                 {\r
32                         // Build the hash table of HTML entity references.  This list comes\r
33                         // from the HTML 4.01 W3C recommendation.\r
34                         entities = new Hashtable ();\r
35                         entities.Add ("nbsp", '\u00A0');\r
36                         entities.Add ("iexcl", '\u00A1');\r
37                         entities.Add ("cent", '\u00A2');\r
38                         entities.Add ("pound", '\u00A3');\r
39                         entities.Add ("curren", '\u00A4');\r
40                         entities.Add ("yen", '\u00A5');\r
41                         entities.Add ("brvbar", '\u00A6');\r
42                         entities.Add ("sect", '\u00A7');\r
43                         entities.Add ("uml", '\u00A8');\r
44                         entities.Add ("copy", '\u00A9');\r
45                         entities.Add ("ordf", '\u00AA');\r
46                         entities.Add ("laquo", '\u00AB');\r
47                         entities.Add ("not", '\u00AC');\r
48                         entities.Add ("shy", '\u00AD');\r
49                         entities.Add ("reg", '\u00AE');\r
50                         entities.Add ("macr", '\u00AF');\r
51                         entities.Add ("deg", '\u00B0');\r
52                         entities.Add ("plusmn", '\u00B1');\r
53                         entities.Add ("sup2", '\u00B2');\r
54                         entities.Add ("sup3", '\u00B3');\r
55                         entities.Add ("acute", '\u00B4');\r
56                         entities.Add ("micro", '\u00B5');\r
57                         entities.Add ("para", '\u00B6');\r
58                         entities.Add ("middot", '\u00B7');\r
59                         entities.Add ("cedil", '\u00B8');\r
60                         entities.Add ("sup1", '\u00B9');\r
61                         entities.Add ("ordm", '\u00BA');\r
62                         entities.Add ("raquo", '\u00BB');\r
63                         entities.Add ("frac14", '\u00BC');\r
64                         entities.Add ("frac12", '\u00BD');\r
65                         entities.Add ("frac34", '\u00BE');\r
66                         entities.Add ("iquest", '\u00BF');\r
67                         entities.Add ("Agrave", '\u00C0');\r
68                         entities.Add ("Aacute", '\u00C1');\r
69                         entities.Add ("Acirc", '\u00C2');\r
70                         entities.Add ("Atilde", '\u00C3');\r
71                         entities.Add ("Auml", '\u00C4');\r
72                         entities.Add ("Aring", '\u00C5');\r
73                         entities.Add ("AElig", '\u00C6');\r
74                         entities.Add ("Ccedil", '\u00C7');\r
75                         entities.Add ("Egrave", '\u00C8');\r
76                         entities.Add ("Eacute", '\u00C9');\r
77                         entities.Add ("Ecirc", '\u00CA');\r
78                         entities.Add ("Euml", '\u00CB');\r
79                         entities.Add ("Igrave", '\u00CC');\r
80                         entities.Add ("Iacute", '\u00CD');\r
81                         entities.Add ("Icirc", '\u00CE');\r
82                         entities.Add ("Iuml", '\u00CF');\r
83                         entities.Add ("ETH", '\u00D0');\r
84                         entities.Add ("Ntilde", '\u00D1');\r
85                         entities.Add ("Ograve", '\u00D2');\r
86                         entities.Add ("Oacute", '\u00D3');\r
87                         entities.Add ("Ocirc", '\u00D4');\r
88                         entities.Add ("Otilde", '\u00D5');\r
89                         entities.Add ("Ouml", '\u00D6');\r
90                         entities.Add ("times", '\u00D7');\r
91                         entities.Add ("Oslash", '\u00D8');\r
92                         entities.Add ("Ugrave", '\u00D9');\r
93                         entities.Add ("Uacute", '\u00DA');\r
94                         entities.Add ("Ucirc", '\u00DB');\r
95                         entities.Add ("Uuml", '\u00DC');\r
96                         entities.Add ("Yacute", '\u00DD');\r
97                         entities.Add ("THORN", '\u00DE');\r
98                         entities.Add ("szlig", '\u00DF');\r
99                         entities.Add ("agrave", '\u00E0');\r
100                         entities.Add ("aacute", '\u00E1');\r
101                         entities.Add ("acirc", '\u00E2');\r
102                         entities.Add ("atilde", '\u00E3');\r
103                         entities.Add ("auml", '\u00E4');\r
104                         entities.Add ("aring", '\u00E5');\r
105                         entities.Add ("aelig", '\u00E6');\r
106                         entities.Add ("ccedil", '\u00E7');\r
107                         entities.Add ("egrave", '\u00E8');\r
108                         entities.Add ("eacute", '\u00E9');\r
109                         entities.Add ("ecirc", '\u00EA');\r
110                         entities.Add ("euml", '\u00EB');\r
111                         entities.Add ("igrave", '\u00EC');\r
112                         entities.Add ("iacute", '\u00ED');\r
113                         entities.Add ("icirc", '\u00EE');\r
114                         entities.Add ("iuml", '\u00EF');\r
115                         entities.Add ("eth", '\u00F0');\r
116                         entities.Add ("ntilde", '\u00F1');\r
117                         entities.Add ("ograve", '\u00F2');\r
118                         entities.Add ("oacute", '\u00F3');\r
119                         entities.Add ("ocirc", '\u00F4');\r
120                         entities.Add ("otilde", '\u00F5');\r
121                         entities.Add ("ouml", '\u00F6');\r
122                         entities.Add ("divide", '\u00F7');\r
123                         entities.Add ("oslash", '\u00F8');\r
124                         entities.Add ("ugrave", '\u00F9');\r
125                         entities.Add ("uacute", '\u00FA');\r
126                         entities.Add ("ucirc", '\u00FB');\r
127                         entities.Add ("uuml", '\u00FC');\r
128                         entities.Add ("yacute", '\u00FD');\r
129                         entities.Add ("thorn", '\u00FE');\r
130                         entities.Add ("yuml", '\u00FF');\r
131                         entities.Add ("fnof", '\u0192');\r
132                         entities.Add ("Alpha", '\u0391');\r
133                         entities.Add ("Beta", '\u0392');\r
134                         entities.Add ("Gamma", '\u0393');\r
135                         entities.Add ("Delta", '\u0394');\r
136                         entities.Add ("Epsilon", '\u0395');\r
137                         entities.Add ("Zeta", '\u0396');\r
138                         entities.Add ("Eta", '\u0397');\r
139                         entities.Add ("Theta", '\u0398');\r
140                         entities.Add ("Iota", '\u0399');\r
141                         entities.Add ("Kappa", '\u039A');\r
142                         entities.Add ("Lambda", '\u039B');\r
143                         entities.Add ("Mu", '\u039C');\r
144                         entities.Add ("Nu", '\u039D');\r
145                         entities.Add ("Xi", '\u039E');\r
146                         entities.Add ("Omicron", '\u039F');\r
147                         entities.Add ("Pi", '\u03A0');\r
148                         entities.Add ("Rho", '\u03A1');\r
149                         entities.Add ("Sigma", '\u03A3');\r
150                         entities.Add ("Tau", '\u03A4');\r
151                         entities.Add ("Upsilon", '\u03A5');\r
152                         entities.Add ("Phi", '\u03A6');\r
153                         entities.Add ("Chi", '\u03A7');\r
154                         entities.Add ("Psi", '\u03A8');\r
155                         entities.Add ("Omega", '\u03A9');\r
156                         entities.Add ("alpha", '\u03B1');\r
157                         entities.Add ("beta", '\u03B2');\r
158                         entities.Add ("gamma", '\u03B3');\r
159                         entities.Add ("delta", '\u03B4');\r
160                         entities.Add ("epsilon", '\u03B5');\r
161                         entities.Add ("zeta", '\u03B6');\r
162                         entities.Add ("eta", '\u03B7');\r
163                         entities.Add ("theta", '\u03B8');\r
164                         entities.Add ("iota", '\u03B9');\r
165                         entities.Add ("kappa", '\u03BA');\r
166                         entities.Add ("lambda", '\u03BB');\r
167                         entities.Add ("mu", '\u03BC');\r
168                         entities.Add ("nu", '\u03BD');\r
169                         entities.Add ("xi", '\u03BE');\r
170                         entities.Add ("omicron", '\u03BF');\r
171                         entities.Add ("pi", '\u03C0');\r
172                         entities.Add ("rho", '\u03C1');\r
173                         entities.Add ("sigmaf", '\u03C2');\r
174                         entities.Add ("sigma", '\u03C3');\r
175                         entities.Add ("tau", '\u03C4');\r
176                         entities.Add ("upsilon", '\u03C5');\r
177                         entities.Add ("phi", '\u03C6');\r
178                         entities.Add ("chi", '\u03C7');\r
179                         entities.Add ("psi", '\u03C8');\r
180                         entities.Add ("omega", '\u03C9');\r
181                         entities.Add ("thetasym", '\u03D1');\r
182                         entities.Add ("upsih", '\u03D2');\r
183                         entities.Add ("piv", '\u03D6');\r
184                         entities.Add ("bull", '\u2022');\r
185                         entities.Add ("hellip", '\u2026');\r
186                         entities.Add ("prime", '\u2032');\r
187                         entities.Add ("Prime", '\u2033');\r
188                         entities.Add ("oline", '\u203E');\r
189                         entities.Add ("frasl", '\u2044');\r
190                         entities.Add ("weierp", '\u2118');\r
191                         entities.Add ("image", '\u2111');\r
192                         entities.Add ("real", '\u211C');\r
193                         entities.Add ("trade", '\u2122');\r
194                         entities.Add ("alefsym", '\u2135');\r
195                         entities.Add ("larr", '\u2190');\r
196                         entities.Add ("uarr", '\u2191');\r
197                         entities.Add ("rarr", '\u2192');\r
198                         entities.Add ("darr", '\u2193');\r
199                         entities.Add ("harr", '\u2194');\r
200                         entities.Add ("crarr", '\u21B5');\r
201                         entities.Add ("lArr", '\u21D0');\r
202                         entities.Add ("uArr", '\u21D1');\r
203                         entities.Add ("rArr", '\u21D2');\r
204                         entities.Add ("dArr", '\u21D3');\r
205                         entities.Add ("hArr", '\u21D4');\r
206                         entities.Add ("forall", '\u2200');\r
207                         entities.Add ("part", '\u2202');\r
208                         entities.Add ("exist", '\u2203');\r
209                         entities.Add ("empty", '\u2205');\r
210                         entities.Add ("nabla", '\u2207');\r
211                         entities.Add ("isin", '\u2208');\r
212                         entities.Add ("notin", '\u2209');\r
213                         entities.Add ("ni", '\u220B');\r
214                         entities.Add ("prod", '\u220F');\r
215                         entities.Add ("sum", '\u2211');\r
216                         entities.Add ("minus", '\u2212');\r
217                         entities.Add ("lowast", '\u2217');\r
218                         entities.Add ("radic", '\u221A');\r
219                         entities.Add ("prop", '\u221D');\r
220                         entities.Add ("infin", '\u221E');\r
221                         entities.Add ("ang", '\u2220');\r
222                         entities.Add ("and", '\u2227');\r
223                         entities.Add ("or", '\u2228');\r
224                         entities.Add ("cap", '\u2229');\r
225                         entities.Add ("cup", '\u222A');\r
226                         entities.Add ("int", '\u222B');\r
227                         entities.Add ("there4", '\u2234');\r
228                         entities.Add ("sim", '\u223C');\r
229                         entities.Add ("cong", '\u2245');\r
230                         entities.Add ("asymp", '\u2248');\r
231                         entities.Add ("ne", '\u2260');\r
232                         entities.Add ("equiv", '\u2261');\r
233                         entities.Add ("le", '\u2264');\r
234                         entities.Add ("ge", '\u2265');\r
235                         entities.Add ("sub", '\u2282');\r
236                         entities.Add ("sup", '\u2283');\r
237                         entities.Add ("nsub", '\u2284');\r
238                         entities.Add ("sube", '\u2286');\r
239                         entities.Add ("supe", '\u2287');\r
240                         entities.Add ("oplus", '\u2295');\r
241                         entities.Add ("otimes", '\u2297');\r
242                         entities.Add ("perp", '\u22A5');\r
243                         entities.Add ("sdot", '\u22C5');\r
244                         entities.Add ("lceil", '\u2308');\r
245                         entities.Add ("rceil", '\u2309');\r
246                         entities.Add ("lfloor", '\u230A');\r
247                         entities.Add ("rfloor", '\u230B');\r
248                         entities.Add ("lang", '\u2329');\r
249                         entities.Add ("rang", '\u232A');\r
250                         entities.Add ("loz", '\u25CA');\r
251                         entities.Add ("spades", '\u2660');\r
252                         entities.Add ("clubs", '\u2663');\r
253                         entities.Add ("hearts", '\u2665');\r
254                         entities.Add ("diams", '\u2666');\r
255                         entities.Add ("quot", '\u0022');\r
256                         entities.Add ("amp", '\u0026');\r
257                         entities.Add ("lt", '\u003C');\r
258                         entities.Add ("gt", '\u003E');\r
259                         entities.Add ("OElig", '\u0152');\r
260                         entities.Add ("oelig", '\u0153');\r
261                         entities.Add ("Scaron", '\u0160');\r
262                         entities.Add ("scaron", '\u0161');\r
263                         entities.Add ("Yuml", '\u0178');\r
264                         entities.Add ("circ", '\u02C6');\r
265                         entities.Add ("tilde", '\u02DC');\r
266                         entities.Add ("ensp", '\u2002');\r
267                         entities.Add ("emsp", '\u2003');\r
268                         entities.Add ("thinsp", '\u2009');\r
269                         entities.Add ("zwnj", '\u200C');\r
270                         entities.Add ("zwj", '\u200D');\r
271                         entities.Add ("lrm", '\u200E');\r
272                         entities.Add ("rlm", '\u200F');\r
273                         entities.Add ("ndash", '\u2013');\r
274                         entities.Add ("mdash", '\u2014');\r
275                         entities.Add ("lsquo", '\u2018');\r
276                         entities.Add ("rsquo", '\u2019');\r
277                         entities.Add ("sbquo", '\u201A');\r
278                         entities.Add ("ldquo", '\u201C');\r
279                         entities.Add ("rdquo", '\u201D');\r
280                         entities.Add ("bdquo", '\u201E');\r
281                         entities.Add ("dagger", '\u2020');\r
282                         entities.Add ("Dagger", '\u2021');\r
283                         entities.Add ("permil", '\u2030');\r
284                         entities.Add ("lsaquo", '\u2039');\r
285                         entities.Add ("rsaquo", '\u203A');\r
286                         entities.Add ("euro", '\u20AC');\r
287                 }\r
288         \r
289                 public HttpUtility () \r
290                 {\r
291                 }\r
292         \r
293                 #endregion // Constructors\r
294         \r
295                 #region Methods\r
296         \r
297                 public static void HtmlAttributeEncode (string s, TextWriter output) \r
298                 {\r
299                         output.Write(HtmlAttributeEncode(s));\r
300                 }\r
301         \r
302                 public static string HtmlAttributeEncode (string s) \r
303                 {\r
304                         if (null == s) \r
305                                 return null;\r
306         \r
307                         StringBuilder output = new StringBuilder ();\r
308         \r
309                         foreach (char c in s) \r
310                                 switch (c) {\r
311                                 case '&' : \r
312                                         output.Append ("&amp;");\r
313                                         break;\r
314                                 case '"' :\r
315                                         output.Append ("&quot;");\r
316                                         break;\r
317                                 default:\r
318                                         output.Append (c);\r
319                                         break;\r
320                                 }\r
321         \r
322                         return output.ToString();\r
323                 }\r
324         \r
325                 public static string UrlDecode (string str) \r
326                 {\r
327                         return UrlDecode(str, WebEncoding.Encoding);\r
328                 }\r
329         \r
330                 private static char [] GetChars (MemoryStream b, Encoding e)\r
331                 {\r
332                         return e.GetChars (b.GetBuffer (), 0, (int) b.Length);\r
333                 }\r
334                 \r
335                 public static string UrlDecode (string s, Encoding e)\r
336                 {\r
337                         if (null == s) \r
338                                 return null;\r
339 \r
340                         if (e == null)\r
341                                 e = WebEncoding.Encoding;\r
342         \r
343                         StringBuilder output = new StringBuilder ();\r
344                         long len = s.Length;\r
345                         NumberStyles hexa = NumberStyles.HexNumber;\r
346                         MemoryStream bytes = new MemoryStream ();\r
347         \r
348                         for (int i = 0; i < len; i++) {\r
349                                 if (s [i] == '%' && i + 2 < len) {\r
350                                         if (s [i + 1] == 'u' && i + 5 < len) {\r
351                                                 if (bytes.Length > 0) {\r
352                                                         output.Append (GetChars (bytes, e));\r
353                                                         bytes.SetLength (0);\r
354                                                 }\r
355                                                 output.Append ((char) Int32.Parse (s.Substring (i + 2, 4), hexa));\r
356                                                 i += 5;\r
357                                         } else {\r
358                                                 bytes.WriteByte ((byte) Int32.Parse (s.Substring (i + 1, 2), hexa));\r
359                                                 i += 2;\r
360                                         }\r
361                                         continue;\r
362                                 }\r
363 \r
364                                 if (bytes.Length > 0) {\r
365                                         output.Append (GetChars (bytes, e));\r
366                                         bytes.SetLength (0);\r
367                                 }\r
368 \r
369                                 if (s [i] == '+') {\r
370                                         output.Append (' ');\r
371                                 } else {\r
372                                         output.Append (s [i]);\r
373                                 }\r
374                         }\r
375         \r
376                         if (bytes.Length > 0) {\r
377                                 output.Append (GetChars (bytes, e));\r
378                         }\r
379 \r
380                         bytes = null;\r
381                         return output.ToString ();\r
382                 }\r
383         \r
384                 public static string UrlDecode (byte [] bytes, Encoding e)\r
385                 {\r
386                         if (bytes == null)\r
387                                 return null;\r
388 \r
389                         return UrlDecode (bytes, 0, bytes.Length, e);\r
390                 }\r
391 \r
392                 private static int GetInt (byte b)\r
393                 {\r
394                         char c = Char.ToUpper ((char) b);\r
395                         if (c >= '0' && c <= '9')\r
396                                 return c - '0';\r
397 \r
398                         if (c < 'A' || c > 'F')\r
399                                 return 0;\r
400 \r
401                         return (c - 'A' + 10);\r
402                 }\r
403 \r
404                 private static char GetChar (byte [] bytes, int offset, int length)\r
405                 {\r
406                         int value = 0;\r
407                         int end = length + offset;\r
408                         for (int i = offset; i < end; i++)\r
409                                 value = (value << 4) + GetInt (bytes [offset]);\r
410 \r
411                         return (char) value;\r
412                 }\r
413                 \r
414                 public static string UrlDecode (byte [] bytes, int offset, int count, Encoding e)\r
415                 {\r
416                         if (bytes == null || count == 0)\r
417                                 return null;\r
418 \r
419                         if (bytes == null)\r
420                                 throw new ArgumentNullException ("bytes");\r
421 \r
422                         if (offset < 0 || offset > bytes.Length)\r
423                                 throw new ArgumentOutOfRangeException ("offset");\r
424 \r
425                         if (count < 0 || offset + count > bytes.Length)\r
426                                 throw new ArgumentOutOfRangeException ("count");\r
427 \r
428                         StringBuilder output = new StringBuilder ();\r
429                         MemoryStream acc = new MemoryStream ();\r
430 \r
431                         int end = count + offset;\r
432                         for (int i = offset; i < end; i++) {\r
433                                 if (bytes [i] == '%' && i + 2 < count) {\r
434                                         if (bytes [i + 1] == (byte) 'u' && i + 5 < end) {\r
435                                                 if (acc.Length > 0) {\r
436                                                         output.Append (GetChars (acc, e));\r
437                                                         acc.SetLength (0);\r
438                                                 }\r
439                                                 output.Append (GetChar (bytes, offset + 2, 4));\r
440                                                 i += 5;\r
441                                         } else {\r
442                                                 acc.WriteByte ((byte) GetChar (bytes, offset + 1, 2));\r
443                                                 i += 2;\r
444                                         }\r
445                                         continue;\r
446                                 }\r
447 \r
448                                 if (acc.Length > 0) {\r
449                                         output.Append (GetChars (acc, e));\r
450                                         acc.SetLength (0);\r
451                                 }\r
452 \r
453                                 if (bytes [i] == '+') {\r
454                                         output.Append (' ');\r
455                                 } else {\r
456                                         output.Append ((char) bytes [i]);\r
457                                 }\r
458                         }\r
459 \r
460                         if (acc.Length > 0) {\r
461                                 output.Append (GetChars (acc, e));\r
462                         }\r
463                         \r
464                         acc = null;\r
465                         return output.ToString ();\r
466                 }\r
467         \r
468                 public static byte [] UrlDecodeToBytes (byte [] bytes)\r
469                 {\r
470                         if (bytes == null)\r
471                                 return null;\r
472 \r
473                         return UrlDecodeToBytes (bytes, 0, bytes.Length);\r
474                 }\r
475 \r
476                 public static byte [] UrlDecodeToBytes (string str)\r
477                 {\r
478                         return UrlDecodeToBytes (str, WebEncoding.Encoding);\r
479                 }\r
480 \r
481                 public static byte [] UrlDecodeToBytes (string str, Encoding e)\r
482                 {\r
483                         if (str == null)\r
484                                 return null;\r
485 \r
486                         if (e == null)\r
487                                 throw new ArgumentNullException ("e");\r
488 \r
489                         return UrlDecodeToBytes (e.GetBytes (str));\r
490                 }\r
491 \r
492                 public static byte [] UrlDecodeToBytes (byte [] bytes, int offset, int count)\r
493                 {\r
494                         if (bytes == null)\r
495                                 return null;\r
496 \r
497                         int len = bytes.Length;\r
498                         if (offset < 0 || offset >= len)\r
499                                 throw new ArgumentOutOfRangeException("offset");\r
500 \r
501                         if (count < 0 || offset <= len - count)\r
502                                 throw new ArgumentOutOfRangeException("count");\r
503 \r
504                         ArrayList result = new ArrayList ();\r
505                         int end = offset + count;\r
506                         for (int i = offset; i < end; i++){\r
507                                 char c = (char) bytes [i];\r
508                                 if (c == '+')\r
509                                         c = ' ';\r
510                                 else if (c == '%' && i < end - 2) {\r
511                                         c = GetChar (bytes, i, 2);\r
512                                         i += 2;\r
513                                 }\r
514                                 result.Add ((byte) c);\r
515                         }\r
516 \r
517                         return (byte []) result.ToArray (typeof (byte));\r
518                 }\r
519 \r
520                 public static string UrlEncode(string str) \r
521                 {\r
522                         return UrlEncode(str, WebEncoding.Encoding);\r
523                 }\r
524         \r
525                 public static string UrlEncode (string s, Encoding Enc) \r
526                 {\r
527                         if (s == null)\r
528                                 return null;\r
529 \r
530                         byte [] bytes = Enc.GetBytes (s);\r
531                         return Encoding.ASCII.GetString (UrlEncodeToBytes (bytes, 0, bytes.Length));\r
532                 }\r
533           \r
534                 public static string UrlEncode (byte [] bytes)\r
535                 {\r
536                         if (bytes == null)\r
537                                 return null;\r
538 \r
539                         return Encoding.ASCII.GetString (UrlEncodeToBytes (bytes, 0, bytes.Length));\r
540                 }\r
541 \r
542                 public static string UrlEncode (byte [] bytes, int offset, int count)\r
543                 {\r
544                         if (bytes == null)\r
545                                 return null;\r
546 \r
547                         return Encoding.ASCII.GetString (UrlEncodeToBytes (bytes, offset, count));\r
548                 }\r
549 \r
550                 public static byte [] UrlEncodeToBytes (string str)\r
551                 {\r
552                         return UrlEncodeToBytes (str, WebEncoding.Encoding);\r
553                 }\r
554 \r
555                 public static byte [] UrlEncodeToBytes (string str, Encoding e)\r
556                 {\r
557                         if (str == null)\r
558                                 return null;\r
559 \r
560                         byte [] bytes = e.GetBytes (str);\r
561                         return UrlEncodeToBytes (bytes, 0, bytes.Length);\r
562                 }\r
563 \r
564                 public static byte [] UrlEncodeToBytes (byte [] bytes)\r
565                 {\r
566                         if (bytes == null)\r
567                                 return null;\r
568 \r
569                         return UrlEncodeToBytes (bytes, 0, bytes.Length);\r
570                 }\r
571 \r
572                 static char [] hexChars = "0123456789ABCDEF".ToCharArray ();\r
573 \r
574                 public static byte [] UrlEncodeToBytes (byte [] bytes, int offset, int count)\r
575                 {\r
576                         if (bytes == null)\r
577                                 return null;\r
578 \r
579                         int len = bytes.Length;\r
580                         if (offset < 0 || offset >= len)\r
581                                 throw new ArgumentOutOfRangeException("offset");\r
582 \r
583                         if (count < 0 || offset < len - count)\r
584                                 throw new ArgumentOutOfRangeException("count");\r
585 \r
586                         ArrayList result = new ArrayList ();\r
587                         int end = offset + count;\r
588                         for (int i = offset; i < end; i++) {\r
589                                 char c = (char) bytes [i];\r
590                                 if (c == ' ')\r
591                                         result.Add ((byte) '+');\r
592                                 else if ((c < '0' && c != '-' && c != '.') ||\r
593                                          (c < 'A' && c > '9') ||\r
594                                          (c > 'Z' && c < 'a' && c != '_') ||\r
595                                          (c > 'z')) {\r
596                                         result.Add ((byte) '%');\r
597                                         int idx = ((int) c) >> 4;\r
598                                         result.Add ((byte) hexChars [idx]);\r
599                                         idx = ((int) c) & 0x0F;\r
600                                         result.Add ((byte) hexChars [idx]);\r
601                                 } else {\r
602                                         result.Add ((byte) c);\r
603                                 }\r
604                         }\r
605 \r
606                         return (byte []) result.ToArray (typeof (byte));\r
607                 }\r
608 \r
609                 public static string UrlEncodeUnicode (string str)\r
610                 {\r
611                         if (str == null)\r
612                                 return null;\r
613 \r
614                         StringBuilder result = new StringBuilder ();\r
615                         int end = str.Length;\r
616                         for (int i = 0; i < end; i++) {\r
617                                 int idx;\r
618                                 char c = str [i];\r
619                                 if (c == ' ') {\r
620                                         result.Append ('+');\r
621                                         continue;\r
622                                 } \r
623 \r
624                                 if (c > 255) {\r
625                                         result.Append ("%u");\r
626                                         idx = ((int) c) >> 24;\r
627                                         result.Append (hexChars [idx]);\r
628                                         idx = (((int) c) >> 16) & 0x0F;\r
629                                         result.Append (hexChars [idx]);\r
630                                         idx = (((int) c) >> 8) & 0x0F;\r
631                                         result.Append (hexChars [idx]);\r
632                                         idx = ((int) c) & 0x0F;\r
633                                         result.Append (hexChars [idx]);\r
634                                         continue;\r
635                                 }\r
636                                 \r
637                                 if ((c < '0' && c != '-' && c != '.') ||\r
638                                     (c < 'A' && c > '9') ||\r
639                                     (c > 'Z' && c < 'a' && c != '_') ||\r
640                                     (c > 'z')) {\r
641                                         result.Append ('%');\r
642                                         idx = ((int) c) >> 4;\r
643                                         result.Append (hexChars [idx]);\r
644                                         idx = ((int) c) & 0x0F;\r
645                                         result.Append (hexChars [idx]);\r
646                                         continue;\r
647                                 }\r
648 \r
649                                 result.Append (c);\r
650                         }\r
651 \r
652                         return result.ToString ();\r
653                 }\r
654 \r
655                 public static byte [] UrlEncodeUnicodeToBytes (string str)\r
656                 {\r
657                         if (str == null)\r
658                                 return null;\r
659 \r
660                         return Encoding.ASCII.GetBytes (UrlEncodeUnicode (str));\r
661                 }\r
662 \r
663                 /// <summary>\r
664                 /// Decodes an HTML-encoded string and returns the decoded string.\r
665                 /// </summary>\r
666                 /// <param name="s">The HTML string to decode. </param>\r
667                 /// <returns>The decoded text.</returns>\r
668                 public static string HtmlDecode (string s) \r
669                 {\r
670                         bool insideEntity = false; // used to indicate that we are in a potential entity\r
671                         string entity = String.Empty;\r
672                         StringBuilder output = new StringBuilder ();\r
673         \r
674                         foreach (char c in s) {\r
675                                 switch (c) {\r
676                                 case '&' :\r
677                                         output.Append (entity);\r
678                                         entity = "&";\r
679                                         insideEntity = true;\r
680                                         break;\r
681                                 case ';' :\r
682                                         if (!insideEntity) {\r
683                                                 output.Append (c);\r
684                                                 break;\r
685                                         }\r
686 \r
687                                         entity += c;\r
688                                         int length = entity.Length;\r
689                                         if (length >= 2 && entity[1] == '#' && entity[2] != ';')\r
690                                                 entity = ((char) Int32.Parse (entity.Substring (2, entity.Length - 3))).ToString();\r
691                                         else if (length > 1 && entities.ContainsKey (entity.Substring (1, entity.Length - 2)))\r
692                                                 entity = entities [entity.Substring (1, entity.Length - 2)].ToString ();\r
693                                         \r
694                                         output.Append (entity);\r
695                                         entity = String.Empty;\r
696                                         insideEntity = false;\r
697                                         break;\r
698                                 default :\r
699                                         if (insideEntity)\r
700                                                 entity += c;\r
701                                         else\r
702                                                 output.Append (c);\r
703                                         break;\r
704                                 }\r
705                         }\r
706                         output.Append (entity);\r
707                         return output.ToString ();\r
708                 }\r
709         \r
710                 /// <summary>\r
711                 /// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream.\r
712                 /// </summary>\r
713                 /// <param name="s">The HTML string to decode</param>\r
714                 /// <param name="output">The TextWriter output stream containing the decoded string. </param>\r
715                 public static void HtmlDecode(string s, TextWriter output) \r
716                 {\r
717                         output.Write (HtmlDecode (s));\r
718                 }\r
719         \r
720                 /// <summary>\r
721                 /// HTML-encodes a string and returns the encoded string.\r
722                 /// </summary>\r
723                 /// <param name="s">The text string to encode. </param>\r
724                 /// <returns>The HTML-encoded text.</returns>\r
725                 public static string HtmlEncode (string s) \r
726                 {\r
727                         StringBuilder output = new StringBuilder ();\r
728                         \r
729                         foreach (char c in s) \r
730                                 switch (c) {\r
731                                 case '&' :\r
732                                         output.Append ("&amp;");\r
733                                         break;\r
734                                 case '>' : \r
735                                         output.Append ("&gt;");\r
736                                         break;\r
737                                 case '<' :\r
738                                         output.Append ("&lt;");\r
739                                         break;\r
740                                 case '"' :\r
741                                         output.Append ("&quot;");\r
742                                         break;\r
743                                 default:\r
744                                         if ((int) c > 128) {\r
745                                                 output.Append ("&#");\r
746                                                 output.Append (((int) c).ToString ());\r
747                                                 output.Append (";");\r
748                                         }\r
749                                         else\r
750                                                 output.Append (c);\r
751                                         break;\r
752                                 }\r
753                         return output.ToString ();\r
754                 }\r
755         \r
756                 /// <summary>\r
757                 /// HTML-encodes a string and sends the resulting output to a TextWriter output stream.\r
758                 /// </summary>\r
759                 /// <param name="s">The string to encode. </param>\r
760                 /// <param name="output">The TextWriter output stream containing the encoded string. </param>\r
761                 public static void HtmlEncode(string s, TextWriter output) \r
762                 {\r
763                         output.Write (HtmlEncode (s));\r
764                 }\r
765 \r
766                 #endregion // Methods\r
767         }\r
768 }\r