Merge pull request #496 from nicolas-raoul/unit-test-for-issue2907
[mono.git] / mcs / class / System.Web / System.Web.Util / HttpEncoder.cs
1 //
2 // Authors:
3 //   Patrik Torstensson (Patrik.Torstensson@labs2.com)
4 //   Wictor WilĂ©n (decode/encode functions) (wictor@ibizkit.se)
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
7
8 //   Marek Habersack <mhabersack@novell.com>
9 //
10 // (C) 2005-2010 Novell, Inc (http://novell.com/)
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 using System;
34 using System.Collections.Generic;
35 using System.Configuration;
36 using System.IO;
37 using System.Text;
38 #if NET_4_0 && !MOBILE
39 using System.Web.Configuration;
40 #endif
41
42 namespace System.Web.Util
43 {
44 #if NET_4_0
45         public
46 #endif
47         class HttpEncoder
48         {
49                 static char [] hexChars = "0123456789abcdef".ToCharArray ();
50                 static object entitiesLock = new object ();
51                 static SortedDictionary <string, char> entities;
52 #if NET_4_0
53                 static Lazy <HttpEncoder> defaultEncoder;
54                 static Lazy <HttpEncoder> currentEncoderLazy;
55 #else
56                 static HttpEncoder defaultEncoder;
57 #endif
58                 static HttpEncoder currentEncoder;
59
60                 static IDictionary <string, char> Entities {
61                         get {
62                                 lock (entitiesLock) {
63                                         if (entities == null)
64                                                 InitEntities ();
65
66                                         return entities;
67                                 }
68                         }
69                 }
70                 
71                 public static HttpEncoder Current {
72                         get {
73 #if NET_4_0
74                                 if (currentEncoder == null)
75                                         currentEncoder = currentEncoderLazy.Value;
76 #endif
77                                 return currentEncoder;
78                         }
79 #if NET_4_0
80                         set {
81                                 if (value == null)
82                                         throw new ArgumentNullException ("value");
83                                 currentEncoder = value;
84                         }
85 #endif
86                 }
87
88                 public static HttpEncoder Default {
89                         get {
90 #if NET_4_0
91                                 return defaultEncoder.Value;
92 #else
93                                 return defaultEncoder;
94 #endif
95                         }
96                 }
97
98                 static HttpEncoder ()
99                 {
100 #if NET_4_0
101                         defaultEncoder = new Lazy <HttpEncoder> (() => new HttpEncoder ());
102                         currentEncoderLazy = new Lazy <HttpEncoder> (new Func <HttpEncoder> (GetCustomEncoderFromConfig));
103 #else
104                         defaultEncoder = new HttpEncoder ();
105                         currentEncoder = defaultEncoder;
106 #endif
107                 }
108                 
109                 public HttpEncoder ()
110                 {
111                 }
112 #if NET_4_0     
113                 protected internal virtual
114 #else
115                 internal static
116 #endif
117                 void HeaderNameValueEncode (string headerName, string headerValue, out string encodedHeaderName, out string encodedHeaderValue)
118                 {
119                         if (String.IsNullOrEmpty (headerName))
120                                 encodedHeaderName = headerName;
121                         else
122                                 encodedHeaderName = EncodeHeaderString (headerName);
123
124                         if (String.IsNullOrEmpty (headerValue))
125                                 encodedHeaderValue = headerValue;
126                         else
127                                 encodedHeaderValue = EncodeHeaderString (headerValue);
128                 }
129
130                 static void StringBuilderAppend (string s, ref StringBuilder sb)
131                 {
132                         if (sb == null)
133                                 sb = new StringBuilder (s);
134                         else
135                                 sb.Append (s);
136                 }
137                 
138                 static string EncodeHeaderString (string input)
139                 {
140                         StringBuilder sb = null;
141                         char ch;
142                         
143                         for (int i = 0; i < input.Length; i++) {
144                                 ch = input [i];
145
146                                 if ((ch < 32 && ch != 9) || ch == 127)
147                                         StringBuilderAppend (String.Format ("%{0:x2}", (int)ch), ref sb);
148                         }
149
150                         if (sb != null)
151                                 return sb.ToString ();
152
153                         return input;
154                 }
155 #if NET_4_0             
156                 protected internal virtual void HtmlAttributeEncode (string value, TextWriter output)
157                 {
158
159                         if (output == null)
160                                 throw new ArgumentNullException ("output");
161
162                         if (String.IsNullOrEmpty (value))
163                                 return;
164
165                         output.Write (HtmlAttributeEncode (value));
166                 }
167
168                 protected internal virtual void HtmlDecode (string value, TextWriter output)
169                 {
170                         if (output == null)
171                                 throw new ArgumentNullException ("output");
172
173                         output.Write (HtmlDecode (value));
174                 }
175
176                 protected internal virtual void HtmlEncode (string value, TextWriter output)
177                 {
178                         if (output == null)
179                                 throw new ArgumentNullException ("output");
180
181                         output.Write (HtmlEncode (value));
182                 }
183
184                 protected internal virtual byte[] UrlEncode (byte[] bytes, int offset, int count)
185                 {
186                         return UrlEncodeToBytes (bytes, offset, count);
187                 }
188
189                 static HttpEncoder GetCustomEncoderFromConfig ()
190                 {
191 #if MOBILE
192                         return defaultEncoder.Value;
193 #else
194                         var cfg = HttpRuntime.Section;
195                         string typeName = cfg.EncoderType;
196
197                         if (String.Compare (typeName, "System.Web.Util.HttpEncoder", StringComparison.OrdinalIgnoreCase) == 0)
198                                 return Default;
199                         
200                         Type t = Type.GetType (typeName, false);
201                         if (t == null)
202                                 throw new ConfigurationErrorsException (String.Format ("Could not load type '{0}'.", typeName));
203                         
204                         if (!typeof (HttpEncoder).IsAssignableFrom (t))
205                                 throw new ConfigurationErrorsException (
206                                         String.Format ("'{0}' is not allowed here because it does not extend class 'System.Web.Util.HttpEncoder'.", typeName)
207                                 );
208
209                         return Activator.CreateInstance (t, false) as HttpEncoder;
210 #endif
211                 }
212 #endif
213 #if NET_4_0
214                 protected internal virtual
215 #else
216                 internal static
217 #endif
218                 string UrlPathEncode (string value)
219                 {
220                         if (String.IsNullOrEmpty (value))
221                                 return value;
222
223                         MemoryStream result = new MemoryStream ();
224                         int length = value.Length;
225                         for (int i = 0; i < length; i++)
226                                 UrlPathEncodeChar (value [i], result);
227                         
228                         return Encoding.ASCII.GetString (result.ToArray ());
229                 }
230                 
231                 internal static byte[] UrlEncodeToBytes (byte[] bytes, int offset, int count)
232                 {
233                         if (bytes == null)
234                                 throw new ArgumentNullException ("bytes");
235                         
236                         int blen = bytes.Length;
237                         if (blen == 0)
238                                 return new byte [0];
239                         
240                         if (offset < 0 || offset >= blen)
241                                 throw new ArgumentOutOfRangeException("offset");
242
243                         if (count < 0 || count > blen - offset)
244                                 throw new ArgumentOutOfRangeException("count");
245
246                         MemoryStream result = new MemoryStream (count);
247                         int end = offset + count;
248                         for (int i = offset; i < end; i++)
249                                 UrlEncodeChar ((char)bytes [i], result, false);
250
251                         return result.ToArray();
252                 }
253                 
254                 internal static string HtmlEncode (string s) 
255                 {
256                         if (s == null)
257                                 return null;
258
259                         if (s.Length == 0)
260                                 return String.Empty;
261                         
262                         bool needEncode = false;
263                         for (int i = 0; i < s.Length; i++) {
264                                 char c = s [i];
265                                 if (c == '&' || c == '"' || c == '<' || c == '>' || c > 159
266 #if NET_4_0
267                                     || c == '\''
268 #endif
269                                 ) {
270                                         needEncode = true;
271                                         break;
272                                 }
273                         }
274
275                         if (!needEncode)
276                                 return s;
277
278                         StringBuilder output = new StringBuilder ();
279                         char ch;
280                         int len = s.Length;
281                         
282                         for (int i = 0; i < len; i++) {
283                                 switch (s [i]) {
284                                         case '&' :
285                                                 output.Append ("&amp;");
286                                                 break;
287                                         case '>' : 
288                                                 output.Append ("&gt;");
289                                                 break;
290                                         case '<' :
291                                                 output.Append ("&lt;");
292                                                 break;
293                                         case '"' :
294                                                 output.Append ("&quot;");
295                                                 break;
296 #if NET_4_0
297                                         case '\'':
298                                                 output.Append ("&#39;");
299                                                 break;
300 #endif
301                                         case '\uff1c':
302                                                 output.Append ("&#65308;");
303                                                 break;
304
305                                         case '\uff1e':
306                                                 output.Append ("&#65310;");
307                                                 break;
308                                                 
309                                         default:
310                                                 ch = s [i];
311                                                 if (ch > 159 && ch < 256) {
312                                                         output.Append ("&#");
313                                                         output.Append (((int) ch).ToString (Helpers.InvariantCulture));
314                                                         output.Append (";");
315                                                 } else
316                                                         output.Append (ch);
317                                                 break;
318                                 }       
319                         }
320                         
321                         return output.ToString ();                      
322                 }
323                 
324                 internal static string HtmlAttributeEncode (string s) 
325                 {
326 #if NET_4_0
327                         if (String.IsNullOrEmpty (s))
328                                 return String.Empty;
329 #else
330                         if (s == null) 
331                                 return null;
332                         
333                         if (s.Length == 0)
334                                 return String.Empty;
335 #endif                  
336                         bool needEncode = false;
337                         for (int i = 0; i < s.Length; i++) {
338                                 char c = s [i];
339                                 if (c == '&' || c == '"' || c == '<'
340 #if NET_4_0
341                                     || c == '\''
342 #endif
343                                 ) {
344                                         needEncode = true;
345                                         break;
346                                 }
347                         }
348
349                         if (!needEncode)
350                                 return s;
351
352                         StringBuilder output = new StringBuilder ();
353                         int len = s.Length;
354                         for (int i = 0; i < len; i++)
355                                 switch (s [i]) {
356                                 case '&' : 
357                                         output.Append ("&amp;");
358                                         break;
359                                 case '"' :
360                                         output.Append ("&quot;");
361                                         break;
362                                 case '<':
363                                         output.Append ("&lt;");
364                                         break;
365 #if NET_4_0
366                                 case '\'':
367                                         output.Append ("&#39;");
368                                         break;
369 #endif
370                                 default:
371                                         output.Append (s [i]);
372                                         break;
373                                 }
374         
375                         return output.ToString();
376                 }
377                 
378                 internal static string HtmlDecode (string s)
379                 {
380                         if (s == null)
381                                 return null;
382
383                         if (s.Length == 0)
384                                 return String.Empty;
385                         
386                         if (s.IndexOf ('&') == -1)
387                                 return s;
388 #if NET_4_0
389                         StringBuilder rawEntity = new StringBuilder ();
390 #endif
391                         StringBuilder entity = new StringBuilder ();
392                         StringBuilder output = new StringBuilder ();
393                         int len = s.Length;
394                         // 0 -> nothing,
395                         // 1 -> right after '&'
396                         // 2 -> between '&' and ';' but no '#'
397                         // 3 -> '#' found after '&' and getting numbers
398                         int state = 0;
399                         int number = 0;
400                         bool is_hex_value = false;
401                         bool have_trailing_digits = false;
402         
403                         for (int i = 0; i < len; i++) {
404                                 char c = s [i];
405                                 if (state == 0) {
406                                         if (c == '&') {
407                                                 entity.Append (c);
408 #if NET_4_0
409                                                 rawEntity.Append (c);
410 #endif
411                                                 state = 1;
412                                         } else {
413                                                 output.Append (c);
414                                         }
415                                         continue;
416                                 }
417
418                                 if (c == '&') {
419                                         state = 1;
420                                         if (have_trailing_digits) {
421                                                 entity.Append (number.ToString (Helpers.InvariantCulture));
422                                                 have_trailing_digits = false;
423                                         }
424
425                                         output.Append (entity.ToString ());
426                                         entity.Length = 0;
427                                         entity.Append ('&');
428                                         continue;
429                                 }
430
431                                 if (state == 1) {
432                                         if (c == ';') {
433                                                 state = 0;
434                                                 output.Append (entity.ToString ());
435                                                 output.Append (c);
436                                                 entity.Length = 0;
437                                         } else {
438                                                 number = 0;
439                                                 is_hex_value = false;
440                                                 if (c != '#') {
441                                                         state = 2;
442                                                 } else {
443                                                         state = 3;
444                                                 }
445                                                 entity.Append (c);
446 #if NET_4_0
447                                                 rawEntity.Append (c);
448 #endif
449                                         }
450                                 } else if (state == 2) {
451                                         entity.Append (c);
452                                         if (c == ';') {
453                                                 string key = entity.ToString ();
454                                                 if (key.Length > 1 && Entities.ContainsKey (key.Substring (1, key.Length - 2)))
455                                                         key = Entities [key.Substring (1, key.Length - 2)].ToString ();
456
457                                                 output.Append (key);
458                                                 state = 0;
459                                                 entity.Length = 0;
460 #if NET_4_0
461                                                 rawEntity.Length = 0;
462 #endif
463                                         }
464                                 } else if (state == 3) {
465                                         if (c == ';') {
466 #if NET_4_0
467                                                 if (number == 0)
468                                                         output.Append (rawEntity.ToString () + ";");
469                                                 else
470 #endif
471                                                 if (number > 65535) {
472                                                         output.Append ("&#");
473                                                         output.Append (number.ToString (Helpers.InvariantCulture));
474                                                         output.Append (";");
475                                                 } else {
476                                                         output.Append ((char) number);
477                                                 }
478                                                 state = 0;
479                                                 entity.Length = 0;
480 #if NET_4_0
481                                                 rawEntity.Length = 0;
482 #endif
483                                                 have_trailing_digits = false;
484                                         } else if (is_hex_value &&  Uri.IsHexDigit(c)) {
485                                                 number = number * 16 + Uri.FromHex(c);
486                                                 have_trailing_digits = true;
487 #if NET_4_0
488                                                 rawEntity.Append (c);
489 #endif
490                                         } else if (Char.IsDigit (c)) {
491                                                 number = number * 10 + ((int) c - '0');
492                                                 have_trailing_digits = true;
493 #if NET_4_0
494                                                 rawEntity.Append (c);
495 #endif
496                                         } else if (number == 0 && (c == 'x' || c == 'X')) {
497                                                 is_hex_value = true;
498 #if NET_4_0
499                                                 rawEntity.Append (c);
500 #endif
501                                         } else {
502                                                 state = 2;
503                                                 if (have_trailing_digits) {
504                                                         entity.Append (number.ToString (Helpers.InvariantCulture));
505                                                         have_trailing_digits = false;
506                                                 }
507                                                 entity.Append (c);
508                                         }
509                                 }
510                         }
511
512                         if (entity.Length > 0) {
513                                 output.Append (entity.ToString ());
514                         } else if (have_trailing_digits) {
515                                 output.Append (number.ToString (Helpers.InvariantCulture));
516                         }
517                         return output.ToString ();
518                 }
519
520                 internal static bool NotEncoded (char c)
521                 {
522                         return (c == '!' || c == '(' || c == ')' || c == '*' || c == '-' || c == '.' || c == '_'
523 #if !NET_4_0
524                                 || c == '\''
525 #endif
526                         );
527                 }
528                 
529                 internal static void UrlEncodeChar (char c, Stream result, bool isUnicode) {
530                         if (c > 255) {
531                                 //FIXME: what happens when there is an internal error?
532                                 //if (!isUnicode)
533                                 //      throw new ArgumentOutOfRangeException ("c", c, "c must be less than 256");
534                                 int idx;
535                                 int i = (int) c;
536
537                                 result.WriteByte ((byte)'%');
538                                 result.WriteByte ((byte)'u');
539                                 idx = i >> 12;
540                                 result.WriteByte ((byte)hexChars [idx]);
541                                 idx = (i >> 8) & 0x0F;
542                                 result.WriteByte ((byte)hexChars [idx]);
543                                 idx = (i >> 4) & 0x0F;
544                                 result.WriteByte ((byte)hexChars [idx]);
545                                 idx = i & 0x0F;
546                                 result.WriteByte ((byte)hexChars [idx]);
547                                 return;
548                         }
549                         
550                         if (c > ' ' && NotEncoded (c)) {
551                                 result.WriteByte ((byte)c);
552                                 return;
553                         }
554                         if (c==' ') {
555                                 result.WriteByte ((byte)'+');
556                                 return;
557                         }
558                         if (    (c < '0') ||
559                                 (c < 'A' && c > '9') ||
560                                 (c > 'Z' && c < 'a') ||
561                                 (c > 'z')) {
562                                 if (isUnicode && c > 127) {
563                                         result.WriteByte ((byte)'%');
564                                         result.WriteByte ((byte)'u');
565                                         result.WriteByte ((byte)'0');
566                                         result.WriteByte ((byte)'0');
567                                 }
568                                 else
569                                         result.WriteByte ((byte)'%');
570                                 
571                                 int idx = ((int) c) >> 4;
572                                 result.WriteByte ((byte)hexChars [idx]);
573                                 idx = ((int) c) & 0x0F;
574                                 result.WriteByte ((byte)hexChars [idx]);
575                         }
576                         else
577                                 result.WriteByte ((byte)c);
578                 }
579
580                 internal static void UrlPathEncodeChar (char c, Stream result)
581                 {
582                         if (c < 33 || c > 126) {
583                                 byte [] bIn = Encoding.UTF8.GetBytes (c.ToString ());
584                                 for (int i = 0; i < bIn.Length; i++) {
585                                         result.WriteByte ((byte) '%');
586                                         int idx = ((int) bIn [i]) >> 4;
587                                         result.WriteByte ((byte) hexChars [idx]);
588                                         idx = ((int) bIn [i]) & 0x0F;
589                                         result.WriteByte ((byte) hexChars [idx]);
590                                 }
591                         }
592                         else if (c == ' ') {
593                                 result.WriteByte ((byte) '%');
594                                 result.WriteByte ((byte) '2');
595                                 result.WriteByte ((byte) '0');
596                         }
597                         else
598                                 result.WriteByte ((byte) c);
599                 }
600                 
601                 static void InitEntities ()
602                 {
603                         // Build the hash table of HTML entity references.  This list comes
604                         // from the HTML 4.01 W3C recommendation.
605                         entities = new SortedDictionary <string, char> (StringComparer.Ordinal);
606                         
607                         entities.Add ("nbsp", '\u00A0');
608                         entities.Add ("iexcl", '\u00A1');
609                         entities.Add ("cent", '\u00A2');
610                         entities.Add ("pound", '\u00A3');
611                         entities.Add ("curren", '\u00A4');
612                         entities.Add ("yen", '\u00A5');
613                         entities.Add ("brvbar", '\u00A6');
614                         entities.Add ("sect", '\u00A7');
615                         entities.Add ("uml", '\u00A8');
616                         entities.Add ("copy", '\u00A9');
617                         entities.Add ("ordf", '\u00AA');
618                         entities.Add ("laquo", '\u00AB');
619                         entities.Add ("not", '\u00AC');
620                         entities.Add ("shy", '\u00AD');
621                         entities.Add ("reg", '\u00AE');
622                         entities.Add ("macr", '\u00AF');
623                         entities.Add ("deg", '\u00B0');
624                         entities.Add ("plusmn", '\u00B1');
625                         entities.Add ("sup2", '\u00B2');
626                         entities.Add ("sup3", '\u00B3');
627                         entities.Add ("acute", '\u00B4');
628                         entities.Add ("micro", '\u00B5');
629                         entities.Add ("para", '\u00B6');
630                         entities.Add ("middot", '\u00B7');
631                         entities.Add ("cedil", '\u00B8');
632                         entities.Add ("sup1", '\u00B9');
633                         entities.Add ("ordm", '\u00BA');
634                         entities.Add ("raquo", '\u00BB');
635                         entities.Add ("frac14", '\u00BC');
636                         entities.Add ("frac12", '\u00BD');
637                         entities.Add ("frac34", '\u00BE');
638                         entities.Add ("iquest", '\u00BF');
639                         entities.Add ("Agrave", '\u00C0');
640                         entities.Add ("Aacute", '\u00C1');
641                         entities.Add ("Acirc", '\u00C2');
642                         entities.Add ("Atilde", '\u00C3');
643                         entities.Add ("Auml", '\u00C4');
644                         entities.Add ("Aring", '\u00C5');
645                         entities.Add ("AElig", '\u00C6');
646                         entities.Add ("Ccedil", '\u00C7');
647                         entities.Add ("Egrave", '\u00C8');
648                         entities.Add ("Eacute", '\u00C9');
649                         entities.Add ("Ecirc", '\u00CA');
650                         entities.Add ("Euml", '\u00CB');
651                         entities.Add ("Igrave", '\u00CC');
652                         entities.Add ("Iacute", '\u00CD');
653                         entities.Add ("Icirc", '\u00CE');
654                         entities.Add ("Iuml", '\u00CF');
655                         entities.Add ("ETH", '\u00D0');
656                         entities.Add ("Ntilde", '\u00D1');
657                         entities.Add ("Ograve", '\u00D2');
658                         entities.Add ("Oacute", '\u00D3');
659                         entities.Add ("Ocirc", '\u00D4');
660                         entities.Add ("Otilde", '\u00D5');
661                         entities.Add ("Ouml", '\u00D6');
662                         entities.Add ("times", '\u00D7');
663                         entities.Add ("Oslash", '\u00D8');
664                         entities.Add ("Ugrave", '\u00D9');
665                         entities.Add ("Uacute", '\u00DA');
666                         entities.Add ("Ucirc", '\u00DB');
667                         entities.Add ("Uuml", '\u00DC');
668                         entities.Add ("Yacute", '\u00DD');
669                         entities.Add ("THORN", '\u00DE');
670                         entities.Add ("szlig", '\u00DF');
671                         entities.Add ("agrave", '\u00E0');
672                         entities.Add ("aacute", '\u00E1');
673                         entities.Add ("acirc", '\u00E2');
674                         entities.Add ("atilde", '\u00E3');
675                         entities.Add ("auml", '\u00E4');
676                         entities.Add ("aring", '\u00E5');
677                         entities.Add ("aelig", '\u00E6');
678                         entities.Add ("ccedil", '\u00E7');
679                         entities.Add ("egrave", '\u00E8');
680                         entities.Add ("eacute", '\u00E9');
681                         entities.Add ("ecirc", '\u00EA');
682                         entities.Add ("euml", '\u00EB');
683                         entities.Add ("igrave", '\u00EC');
684                         entities.Add ("iacute", '\u00ED');
685                         entities.Add ("icirc", '\u00EE');
686                         entities.Add ("iuml", '\u00EF');
687                         entities.Add ("eth", '\u00F0');
688                         entities.Add ("ntilde", '\u00F1');
689                         entities.Add ("ograve", '\u00F2');
690                         entities.Add ("oacute", '\u00F3');
691                         entities.Add ("ocirc", '\u00F4');
692                         entities.Add ("otilde", '\u00F5');
693                         entities.Add ("ouml", '\u00F6');
694                         entities.Add ("divide", '\u00F7');
695                         entities.Add ("oslash", '\u00F8');
696                         entities.Add ("ugrave", '\u00F9');
697                         entities.Add ("uacute", '\u00FA');
698                         entities.Add ("ucirc", '\u00FB');
699                         entities.Add ("uuml", '\u00FC');
700                         entities.Add ("yacute", '\u00FD');
701                         entities.Add ("thorn", '\u00FE');
702                         entities.Add ("yuml", '\u00FF');
703                         entities.Add ("fnof", '\u0192');
704                         entities.Add ("Alpha", '\u0391');
705                         entities.Add ("Beta", '\u0392');
706                         entities.Add ("Gamma", '\u0393');
707                         entities.Add ("Delta", '\u0394');
708                         entities.Add ("Epsilon", '\u0395');
709                         entities.Add ("Zeta", '\u0396');
710                         entities.Add ("Eta", '\u0397');
711                         entities.Add ("Theta", '\u0398');
712                         entities.Add ("Iota", '\u0399');
713                         entities.Add ("Kappa", '\u039A');
714                         entities.Add ("Lambda", '\u039B');
715                         entities.Add ("Mu", '\u039C');
716                         entities.Add ("Nu", '\u039D');
717                         entities.Add ("Xi", '\u039E');
718                         entities.Add ("Omicron", '\u039F');
719                         entities.Add ("Pi", '\u03A0');
720                         entities.Add ("Rho", '\u03A1');
721                         entities.Add ("Sigma", '\u03A3');
722                         entities.Add ("Tau", '\u03A4');
723                         entities.Add ("Upsilon", '\u03A5');
724                         entities.Add ("Phi", '\u03A6');
725                         entities.Add ("Chi", '\u03A7');
726                         entities.Add ("Psi", '\u03A8');
727                         entities.Add ("Omega", '\u03A9');
728                         entities.Add ("alpha", '\u03B1');
729                         entities.Add ("beta", '\u03B2');
730                         entities.Add ("gamma", '\u03B3');
731                         entities.Add ("delta", '\u03B4');
732                         entities.Add ("epsilon", '\u03B5');
733                         entities.Add ("zeta", '\u03B6');
734                         entities.Add ("eta", '\u03B7');
735                         entities.Add ("theta", '\u03B8');
736                         entities.Add ("iota", '\u03B9');
737                         entities.Add ("kappa", '\u03BA');
738                         entities.Add ("lambda", '\u03BB');
739                         entities.Add ("mu", '\u03BC');
740                         entities.Add ("nu", '\u03BD');
741                         entities.Add ("xi", '\u03BE');
742                         entities.Add ("omicron", '\u03BF');
743                         entities.Add ("pi", '\u03C0');
744                         entities.Add ("rho", '\u03C1');
745                         entities.Add ("sigmaf", '\u03C2');
746                         entities.Add ("sigma", '\u03C3');
747                         entities.Add ("tau", '\u03C4');
748                         entities.Add ("upsilon", '\u03C5');
749                         entities.Add ("phi", '\u03C6');
750                         entities.Add ("chi", '\u03C7');
751                         entities.Add ("psi", '\u03C8');
752                         entities.Add ("omega", '\u03C9');
753                         entities.Add ("thetasym", '\u03D1');
754                         entities.Add ("upsih", '\u03D2');
755                         entities.Add ("piv", '\u03D6');
756                         entities.Add ("bull", '\u2022');
757                         entities.Add ("hellip", '\u2026');
758                         entities.Add ("prime", '\u2032');
759                         entities.Add ("Prime", '\u2033');
760                         entities.Add ("oline", '\u203E');
761                         entities.Add ("frasl", '\u2044');
762                         entities.Add ("weierp", '\u2118');
763                         entities.Add ("image", '\u2111');
764                         entities.Add ("real", '\u211C');
765                         entities.Add ("trade", '\u2122');
766                         entities.Add ("alefsym", '\u2135');
767                         entities.Add ("larr", '\u2190');
768                         entities.Add ("uarr", '\u2191');
769                         entities.Add ("rarr", '\u2192');
770                         entities.Add ("darr", '\u2193');
771                         entities.Add ("harr", '\u2194');
772                         entities.Add ("crarr", '\u21B5');
773                         entities.Add ("lArr", '\u21D0');
774                         entities.Add ("uArr", '\u21D1');
775                         entities.Add ("rArr", '\u21D2');
776                         entities.Add ("dArr", '\u21D3');
777                         entities.Add ("hArr", '\u21D4');
778                         entities.Add ("forall", '\u2200');
779                         entities.Add ("part", '\u2202');
780                         entities.Add ("exist", '\u2203');
781                         entities.Add ("empty", '\u2205');
782                         entities.Add ("nabla", '\u2207');
783                         entities.Add ("isin", '\u2208');
784                         entities.Add ("notin", '\u2209');
785                         entities.Add ("ni", '\u220B');
786                         entities.Add ("prod", '\u220F');
787                         entities.Add ("sum", '\u2211');
788                         entities.Add ("minus", '\u2212');
789                         entities.Add ("lowast", '\u2217');
790                         entities.Add ("radic", '\u221A');
791                         entities.Add ("prop", '\u221D');
792                         entities.Add ("infin", '\u221E');
793                         entities.Add ("ang", '\u2220');
794                         entities.Add ("and", '\u2227');
795                         entities.Add ("or", '\u2228');
796                         entities.Add ("cap", '\u2229');
797                         entities.Add ("cup", '\u222A');
798                         entities.Add ("int", '\u222B');
799                         entities.Add ("there4", '\u2234');
800                         entities.Add ("sim", '\u223C');
801                         entities.Add ("cong", '\u2245');
802                         entities.Add ("asymp", '\u2248');
803                         entities.Add ("ne", '\u2260');
804                         entities.Add ("equiv", '\u2261');
805                         entities.Add ("le", '\u2264');
806                         entities.Add ("ge", '\u2265');
807                         entities.Add ("sub", '\u2282');
808                         entities.Add ("sup", '\u2283');
809                         entities.Add ("nsub", '\u2284');
810                         entities.Add ("sube", '\u2286');
811                         entities.Add ("supe", '\u2287');
812                         entities.Add ("oplus", '\u2295');
813                         entities.Add ("otimes", '\u2297');
814                         entities.Add ("perp", '\u22A5');
815                         entities.Add ("sdot", '\u22C5');
816                         entities.Add ("lceil", '\u2308');
817                         entities.Add ("rceil", '\u2309');
818                         entities.Add ("lfloor", '\u230A');
819                         entities.Add ("rfloor", '\u230B');
820                         entities.Add ("lang", '\u2329');
821                         entities.Add ("rang", '\u232A');
822                         entities.Add ("loz", '\u25CA');
823                         entities.Add ("spades", '\u2660');
824                         entities.Add ("clubs", '\u2663');
825                         entities.Add ("hearts", '\u2665');
826                         entities.Add ("diams", '\u2666');
827                         entities.Add ("quot", '\u0022');
828                         entities.Add ("amp", '\u0026');
829                         entities.Add ("lt", '\u003C');
830                         entities.Add ("gt", '\u003E');
831                         entities.Add ("OElig", '\u0152');
832                         entities.Add ("oelig", '\u0153');
833                         entities.Add ("Scaron", '\u0160');
834                         entities.Add ("scaron", '\u0161');
835                         entities.Add ("Yuml", '\u0178');
836                         entities.Add ("circ", '\u02C6');
837                         entities.Add ("tilde", '\u02DC');
838                         entities.Add ("ensp", '\u2002');
839                         entities.Add ("emsp", '\u2003');
840                         entities.Add ("thinsp", '\u2009');
841                         entities.Add ("zwnj", '\u200C');
842                         entities.Add ("zwj", '\u200D');
843                         entities.Add ("lrm", '\u200E');
844                         entities.Add ("rlm", '\u200F');
845                         entities.Add ("ndash", '\u2013');
846                         entities.Add ("mdash", '\u2014');
847                         entities.Add ("lsquo", '\u2018');
848                         entities.Add ("rsquo", '\u2019');
849                         entities.Add ("sbquo", '\u201A');
850                         entities.Add ("ldquo", '\u201C');
851                         entities.Add ("rdquo", '\u201D');
852                         entities.Add ("bdquo", '\u201E');
853                         entities.Add ("dagger", '\u2020');
854                         entities.Add ("Dagger", '\u2021');
855                         entities.Add ("permil", '\u2030');
856                         entities.Add ("lsaquo", '\u2039');
857                         entities.Add ("rsaquo", '\u203A');
858                         entities.Add ("euro", '\u20AC');
859                 }
860         }
861 }