Developer Area

root/apps/outlook/branches/1.5/DotTelSystem/Punycode/Punycode.cs @ 580

Revision 580, 6.3 kB (checked in by jonmaycock, 10 months ago)
Line 
1/// <summary>
2/// *
3/// Author: Alexander Gnauck AG-Software, mailto:gnauck@ag-software.de
4/// *
5/// This file is part of GNU Libidn.
6/// *
7/// This library is free software; you can redistribute it and/or
8/// modify it under the terms of the GNU Lesser General Public License
9/// as published by the Free Software Foundation; either version 2.1 of
10/// the License, or (at your option) any later version.
11/// *
12/// This library is distributed in the hope that it will be useful, but
13/// WITHOUT ANY WARRANTY; without even the implied warranty of
14/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15/// Lesser General Public License for more details.
16/// *
17/// You should have received a copy of the GNU Lesser General Public
18/// License along with this library; if not, write to the Free Software
19/// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20/// USA
21/// </summary>
22
23using System;
24using System.Text;
25
26namespace Gnu.Inet.Encoding
27{       
28       
29        public class Punycode
30        {
31                /* Punycode parameters */
32                internal const int TMIN = 1;
33                internal const int TMAX = 26;
34                internal const int BASE = 36;
35                internal const int INITIAL_N = 128;
36                internal const int INITIAL_BIAS = 72;
37                internal const int DAMP = 700;
38                internal const int SKEW = 38;
39                internal const char DELIMITER = '-';
40               
41                /// <summary>
42        /// Punycodes a unicode string.
43                /// </summary>
44                /// <param name="input">Unicode string.</param>
45                /// <returns> Punycoded string.</returns>
46                public static string Encode(string input)
47                {
48                        int n = INITIAL_N;
49                        int delta = 0;
50                        int bias = INITIAL_BIAS;
51                        StringBuilder output = new StringBuilder();
52                       
53                        // Copy all basic code points to the output
54                        int b = 0;
55                        for (int i = 0; i < input.Length; i++)
56                        {
57                                char c = input[i];
58                                if (IsBasic(c))
59                                {
60                                        output.Append(c);
61                                        b++;
62                                }
63                        }
64                       
65                        // Append delimiter
66                        if (b > 0)
67                        {
68                                output.Append(DELIMITER);
69                        }
70                       
71                        int h = b;
72                        while (h < input.Length)
73                        {
74                                int m = System.Int32.MaxValue;
75                               
76                                // Find the minimum code point >= n
77                                for (int i = 0; i < input.Length; i++)
78                                {
79                                        int c = input[i];
80                                        if (c >= n && c < m)
81                                        {
82                                                m = c;
83                                        }
84                                }
85                               
86                                if (m - n > (System.Int32.MaxValue - delta) / (h + 1))
87                                {
88                                        throw new PunycodeException(PunycodeException.OVERFLOW);
89                                }
90                                delta = delta + (m - n) * (h + 1);
91                                n = m;
92                               
93                                for (int j = 0; j < input.Length; j++)
94                                {
95                                        int c = input[j];
96                                        if (c < n)
97                                        {
98                                                delta++;
99                                                if (0 == delta)
100                                                {
101                                                        throw new PunycodeException(PunycodeException.OVERFLOW);
102                                                }
103                                        }
104                                        if (c == n)
105                                        {
106                                                int q = delta;
107                                               
108                                                for (int k = BASE; ; k += BASE)
109                                                {
110                                                        int t;
111                                                        if (k <= bias)
112                                                        {
113                                                                t = TMIN;
114                                                        }
115                                                        else if (k >= bias + TMAX)
116                                                        {
117                                                                t = TMAX;
118                                                        }
119                                                        else
120                                                        {
121                                                                t = k - bias;
122                                                        }
123                                                        if (q < t)
124                                                        {
125                                                                break;
126                                                        }
127                                                        output.Append((char) Digit2Codepoint(t + (q - t) % (BASE - t)));
128                                                        q = (q - t) / (BASE - t);
129                                                }
130                                               
131                                                output.Append((char) Digit2Codepoint(q));
132                                                bias = Adapt(delta, h + 1, h == b);
133                                                delta = 0;
134                                                h++;
135                                        }
136                                }
137                               
138                                delta++;
139                                n++;
140                        }
141                       
142                        return output.ToString();
143                }
144               
145                /// <summary>
146        /// Decode a punycoded string.
147                /// </summary>
148                /// <param name="input">Punycode string</param>
149                /// <returns> Unicode string.</returns>
150                public static string Decode(string input)
151                {
152                        int n = INITIAL_N;
153                        int i = 0;
154                        int bias = INITIAL_BIAS;
155                        StringBuilder output = new StringBuilder();
156                       
157                        int d = input.LastIndexOf((System.Char) DELIMITER);
158                        if (d > 0)
159                        {
160                                for (int j = 0; j < d; j++)
161                                {
162                                        char c = input[j];
163                                        if (!IsBasic(c))
164                                        {
165                                                throw new PunycodeException(PunycodeException.BAD_INPUT);
166                                        }
167                                        output.Append(c);
168                                }
169                                d++;
170                        }
171                        else
172                        {
173                                d = 0;
174                        }
175                       
176                        while (d < input.Length)
177                        {
178                                int oldi = i;
179                                int w = 1;
180                               
181                                for (int k = BASE; ; k += BASE)
182                                {
183                                        if (d == input.Length)
184                                        {
185                                                throw new PunycodeException(PunycodeException.BAD_INPUT);
186                                        }
187                                        int c = input[d++];
188                                        int digit = Codepoint2Digit(c);
189                                        if (digit > (System.Int32.MaxValue - i) / w)
190                                        {
191                                                throw new PunycodeException(PunycodeException.OVERFLOW);
192                                        }
193                                       
194                                        i = i + digit * w;
195                                       
196                                        int t;
197                                        if (k <= bias)
198                                        {
199                                                t = TMIN;
200                                        }
201                                        else if (k >= bias + TMAX)
202                                        {
203                                                t = TMAX;
204                                        }
205                                        else
206                                        {
207                                                t = k - bias;
208                                        }
209                                        if (digit < t)
210                                        {
211                                                break;
212                                        }
213                                        w = w * (BASE - t);
214                                }
215                               
216                                bias = Adapt(i - oldi, output.Length + 1, oldi == 0);
217                               
218                                if (i / (output.Length + 1) > Int32.MaxValue - n)
219                                {
220                                        throw new PunycodeException(PunycodeException.OVERFLOW);
221                                }
222                               
223                                n = n + i / (output.Length + 1);
224                                i = i % (output.Length + 1);
225                                // following overload is not supported on CF
226                                //output.Insert(i,(char) n);
227                                output.Insert(i, new char[1] { (char) n });
228                                i++;
229                        }
230                       
231                        return output.ToString();
232                }
233               
234                public static int Adapt(int delta, int numpoints, bool first)
235                {
236                        if (first)
237                        {
238                                delta = delta / DAMP;
239                        }
240                        else
241                        {
242                                delta = delta / 2;
243                        }
244                       
245                        delta = delta + (delta / numpoints);
246                       
247                        int k = 0;
248                        while (delta > ((BASE - TMIN) * TMAX) / 2)
249                        {
250                                delta = delta / (BASE - TMIN);
251                                k = k + BASE;
252                        }
253                       
254                        return k + ((BASE - TMIN + 1) * delta) / (delta + SKEW);
255                }
256               
257                public static bool IsBasic(char c)
258                {
259                        return c < 0x80;
260                }
261               
262                public static int Digit2Codepoint(int d)
263                {
264                        if (d < 26)
265                        {
266                                // 0..25 : 'a'..'z'
267                                return d + 'a';
268                        }
269                        else if (d < 36)
270                        {
271                                // 26..35 : '0'..'9';
272                                return d - 26 + '0';
273                        }
274                        else
275                        {
276                                throw new PunycodeException(PunycodeException.BAD_INPUT);
277                        }
278                }
279               
280                public static int Codepoint2Digit(int c)
281                {
282                        if (c - '0' < 10)
283                        {
284                                // '0'..'9' : 26..35
285                                return c - '0' + 26;
286                        }
287                        else if (c - 'a' < 26)
288                        {
289                                // 'a'..'z' : 0..25
290                                return c - 'a';
291                        }
292                        else
293                        {
294                                throw new PunycodeException(PunycodeException.BAD_INPUT);
295                        }
296                }
297        }
298}
Note: See TracBrowser for help on using the browser.
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us