ReactOS 0.4.15-dev-7113-g9ea2222
IdnToAscii.c
Go to the documentation of this file.
1
2#define WIN32_NO_STATUS
3#include <wine/unicode.h>
4
5#define NDEBUG
6#include <debug.h>
7
8/* Taken from Wine kernel32/locale.c */
9
10enum {
11 BASE = 36,
12 TMIN = 1,
13 TMAX = 26,
14 SKEW = 38,
15 DAMP = 700,
17 INIT_N = 128
18};
19
20static inline INT adapt(INT delta, INT numpoints, BOOL firsttime)
21{
22 INT k;
23
24 delta /= (firsttime ? DAMP : 2);
25 delta += delta/numpoints;
26
27 for(k=0; delta>((BASE-TMIN)*TMAX)/2; k+=BASE)
28 delta /= BASE-TMIN;
29 return k+((BASE-TMIN+1)*delta)/(delta+SKEW);
30}
31
32static inline unsigned short get_table_entry( const unsigned short *table, WCHAR ch )
33{
34 return table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0xf)];
35}
36
37INT WINAPI IdnToNameprepUnicode(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar,
38 LPWSTR lpNameprepCharStr, INT cchNameprepChar)
39{
40 enum {
41 UNASSIGNED = 0x1,
42 PROHIBITED = 0x2,
43 BIDI_RAL = 0x4,
44 BIDI_L = 0x8
45 };
46
47 extern const unsigned short nameprep_char_type[];
48 extern const WCHAR nameprep_mapping[];
49 const WCHAR *ptr;
50 WORD flags;
51 WCHAR buf[64], *map_str, norm_str[64], ch;
52 DWORD i, map_len, norm_len, mask, label_start, label_end, out = 0;
53 BOOL have_bidi_ral, prohibit_bidi_ral, ascii_only;
54
55 DPRINT("%x %p %d %p %d\n", dwFlags, lpUnicodeCharStr, cchUnicodeChar,
56 lpNameprepCharStr, cchNameprepChar);
57
58 if(dwFlags & ~(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES)) {
60 return 0;
61 }
62
63 if(!lpUnicodeCharStr || cchUnicodeChar<-1) {
65 return 0;
66 }
67
68 if(cchUnicodeChar == -1)
69 cchUnicodeChar = (UINT)strlenW(lpUnicodeCharStr)+1;
70 if(!cchUnicodeChar || (cchUnicodeChar==1 && lpUnicodeCharStr[0]==0)) {
72 return 0;
73 }
74
75 for(label_start=0; label_start<(UINT)cchUnicodeChar;) {
76 ascii_only = TRUE;
77 for(i=label_start; i<(UINT)cchUnicodeChar; i++) {
78 ch = lpUnicodeCharStr[i];
79
80 if(i!=cchUnicodeChar-1 && !ch) {
82 return 0;
83 }
84 /* check if ch is one of label separators defined in RFC3490 */
85 if(!ch || ch=='.' || ch==0x3002 || ch==0xff0e || ch==0xff61)
86 break;
87
88 if(ch > 0x7f) {
89 ascii_only = FALSE;
90 continue;
91 }
92
93 if((dwFlags&IDN_USE_STD3_ASCII_RULES) == 0)
94 continue;
95 if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z')
96 || (ch>='0' && ch<='9') || ch=='-')
97 continue;
98
100 return 0;
101 }
102 label_end = i;
103 /* last label may be empty */
104 if(label_start==label_end && ch) {
106 return 0;
107 }
108
109 if((dwFlags&IDN_USE_STD3_ASCII_RULES) && (lpUnicodeCharStr[label_start]=='-' ||
110 lpUnicodeCharStr[label_end-1]=='-')) {
112 return 0;
113 }
114
115 if(ascii_only) {
116 /* maximal label length is 63 characters */
117 if(label_end-label_start > 63) {
119 return 0;
120 }
121 if(label_end < (UINT)cchUnicodeChar)
122 label_end++;
123
124 if(!lpNameprepCharStr) {
125 out += label_end-label_start;
126 }else if(out+label_end-label_start <= (UINT)cchNameprepChar) {
127 memcpy(lpNameprepCharStr+out, lpUnicodeCharStr+label_start,
128 (label_end-label_start)*sizeof(WCHAR));
129 if(lpUnicodeCharStr[label_end-1] > 0x7f)
130 lpNameprepCharStr[out+label_end-label_start-1] = '.';
131 out += label_end-label_start;
132 }else {
134 return 0;
135 }
136
137 label_start = label_end;
138 continue;
139 }
140
141 map_len = 0;
142 for(i=label_start; i<label_end; i++) {
143 ch = lpUnicodeCharStr[i];
145 ptr = nameprep_mapping + ptr[(ch>>4)&0x0f] + 3*(ch&0x0f);
146
147 if(!ptr[0]) map_len++;
148 else if(!ptr[1]) map_len++;
149 else if(!ptr[2]) map_len += 2;
150 else if(ptr[0]!=0xffff || ptr[1]!=0xffff || ptr[2]!=0xffff) map_len += 3;
151 }
152 if(map_len*sizeof(WCHAR) > sizeof(buf)) {
153 map_str = HeapAlloc(GetProcessHeap(), 0, map_len*sizeof(WCHAR));
154 if(!map_str) {
156 return 0;
157 }
158 }else {
159 map_str = buf;
160 }
161 map_len = 0;
162 for(i=label_start; i<label_end; i++) {
163 ch = lpUnicodeCharStr[i];
165 ptr = nameprep_mapping + ptr[(ch>>4)&0x0f] + 3*(ch&0x0f);
166
167 if(!ptr[0]) {
168 map_str[map_len++] = ch;
169 }else if(!ptr[1]) {
170 map_str[map_len++] = ptr[0];
171 }else if(!ptr[2]) {
172 map_str[map_len++] = ptr[0];
173 map_str[map_len++] = ptr[1];
174 }else if(ptr[0]!=0xffff || ptr[1]!=0xffff || ptr[2]!=0xffff) {
175 map_str[map_len++] = ptr[0];
176 map_str[map_len++] = ptr[1];
177 map_str[map_len++] = ptr[2];
178 }
179 }
180
181 norm_len = FoldStringW(MAP_FOLDCZONE, map_str, map_len,
182 norm_str, sizeof(norm_str)/sizeof(WCHAR)-1);
183 if(map_str != buf)
184 HeapFree(GetProcessHeap(), 0, map_str);
185 if(!norm_len) {
188 return 0;
189 }
190
191 if(label_end < (UINT)cchUnicodeChar) {
192 norm_str[norm_len++] = lpUnicodeCharStr[label_end] ? '.' : 0;
193 label_end++;
194 }
195
196 if(!lpNameprepCharStr) {
197 out += norm_len;
198 }else if(out+norm_len <= (UINT)cchNameprepChar) {
199 memcpy(lpNameprepCharStr+out, norm_str, norm_len*sizeof(WCHAR));
200 out += norm_len;
201 }else {
203 return 0;
204 }
205
206 have_bidi_ral = prohibit_bidi_ral = FALSE;
207 mask = PROHIBITED;
208 if((dwFlags&IDN_ALLOW_UNASSIGNED) == 0)
209 mask |= UNASSIGNED;
210 for(i=0; i<norm_len; i++) {
211 ch = norm_str[i];
213
214 if(flags & mask) {
215 SetLastError((flags & PROHIBITED) ? ERROR_INVALID_NAME
217 return 0;
218 }
219
220 if(flags & BIDI_RAL)
221 have_bidi_ral = TRUE;
222 if(flags & BIDI_L)
223 prohibit_bidi_ral = TRUE;
224 }
225
226 if(have_bidi_ral) {
227 ch = norm_str[0];
229 if((flags & BIDI_RAL) == 0)
230 prohibit_bidi_ral = TRUE;
231
232 ch = norm_str[norm_len-1];
234 if((flags & BIDI_RAL) == 0)
235 prohibit_bidi_ral = TRUE;
236 }
237
238 if(have_bidi_ral && prohibit_bidi_ral) {
240 return 0;
241 }
242
243 label_start = label_end;
244 }
245
246 return out;
247}
248
249INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar,
250 LPWSTR lpASCIICharStr, INT cchASCIIChar)
251{
252 static const WCHAR prefixW[] = {'x','n','-','-'};
253
254 WCHAR *norm_str;
255 INT i, label_start, label_end, norm_len, out_label, out = 0;
256
257 DPRINT("%x %p %d %p %d\n", dwFlags, lpUnicodeCharStr, cchUnicodeChar,
258 lpASCIICharStr, cchASCIIChar);
259
260 norm_len = IdnToNameprepUnicode(dwFlags, lpUnicodeCharStr, cchUnicodeChar, NULL, 0);
261 if(!norm_len)
262 return 0;
263 norm_str = HeapAlloc(GetProcessHeap(), 0, norm_len*sizeof(WCHAR));
264 if(!norm_str) {
266 return 0;
267 }
268 norm_len = IdnToNameprepUnicode(dwFlags, lpUnicodeCharStr,
269 cchUnicodeChar, norm_str, norm_len);
270 if(!norm_len) {
271 HeapFree(GetProcessHeap(), 0, norm_str);
272 return 0;
273 }
274
275 for(label_start=0; label_start<norm_len;) {
277 INT delta = 0, b = 0, h;
278
279 out_label = out;
280 for(i=label_start; i<norm_len && norm_str[i]!='.' &&
281 norm_str[i]!=0x3002 && norm_str[i]!='\0'; i++)
282 if(norm_str[i] < 0x80)
283 b++;
284 label_end = i;
285
286 if(b == label_end-label_start) {
287 if(label_end < norm_len)
288 b++;
289 if(!lpASCIICharStr) {
290 out += b;
291 }else if(out+b <= cchASCIIChar) {
292 memcpy(lpASCIICharStr+out, norm_str+label_start, b*sizeof(WCHAR));
293 out += b;
294 }else {
295 HeapFree(GetProcessHeap(), 0, norm_str);
297 return 0;
298 }
299 label_start = label_end+1;
300 continue;
301 }
302
303 if(!lpASCIICharStr) {
304 out += 5+b; /* strlen(xn--...-) */
305 }else if(out+5+b <= cchASCIIChar) {
306 memcpy(lpASCIICharStr+out, prefixW, sizeof(prefixW));
307 out += 4;
308 for(i=label_start; i<label_end; i++)
309 if(norm_str[i] < 0x80)
310 lpASCIICharStr[out++] = norm_str[i];
311 lpASCIICharStr[out++] = '-';
312 }else {
313 HeapFree(GetProcessHeap(), 0, norm_str);
315 return 0;
316 }
317 if(!b)
318 out--;
319
320 for(h=b; h<label_end-label_start;) {
321 INT m = 0xffff, q, k;
322
323 for(i=label_start; i<label_end; i++) {
324 if(norm_str[i]>=n && m>norm_str[i])
325 m = norm_str[i];
326 }
327 delta += (m-n)*(h+1);
328 n = m;
329
330 for(i=label_start; i<label_end; i++) {
331 if(norm_str[i] < n) {
332 delta++;
333 }else if(norm_str[i] == n) {
334 for(q=delta, k=BASE; ; k+=BASE) {
335 INT t = k<=bias ? TMIN : k>=bias+TMAX ? TMAX : k-bias;
336 INT disp = q<t ? q : t+(q-t)%(BASE-t);
337 if(!lpASCIICharStr) {
338 out++;
339 }else if(out+1 <= cchASCIIChar) {
340 lpASCIICharStr[out++] = disp<='z'-'a' ?
341 'a'+disp : '0'+disp-'z'+'a'-1;
342 }else {
343 HeapFree(GetProcessHeap(), 0, norm_str);
345 return 0;
346 }
347 if(q < t)
348 break;
349 q = (q-t)/(BASE-t);
350 }
351 bias = adapt(delta, h+1, h==b);
352 delta = 0;
353 h++;
354 }
355 }
356 delta++;
357 n++;
358 }
359
360 if(out-out_label > 63) {
361 HeapFree(GetProcessHeap(), 0, norm_str);
363 return 0;
364 }
365
366 if(label_end < norm_len) {
367 if(!lpASCIICharStr) {
368 out++;
369 }else if(out+1 <= cchASCIIChar) {
370 lpASCIICharStr[out++] = norm_str[label_end] ? '.' : 0;
371 }else {
372 HeapFree(GetProcessHeap(), 0, norm_str);
374 return 0;
375 }
376 }
377 label_start = label_end+1;
378 }
379
380 HeapFree(GetProcessHeap(), 0, norm_str);
381 return out;
382}
static INT adapt(INT delta, INT numpoints, BOOL firsttime)
Definition: IdnToAscii.c:20
@ INIT_N
Definition: IdnToAscii.c:17
@ DAMP
Definition: IdnToAscii.c:15
@ SKEW
Definition: IdnToAscii.c:14
@ BASE
Definition: IdnToAscii.c:11
@ TMIN
Definition: IdnToAscii.c:12
@ TMAX
Definition: IdnToAscii.c:13
@ INIT_BIAS
Definition: IdnToAscii.c:16
INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpASCIICharStr, INT cchASCIIChar)
Definition: IdnToAscii.c:249
static unsigned short get_table_entry(const unsigned short *table, WCHAR ch)
Definition: IdnToAscii.c:32
INT WINAPI IdnToNameprepUnicode(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpNameprepCharStr, INT cchNameprepChar)
Definition: IdnToAscii.c:37
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_NAME
Definition: compat.h:103
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLdouble n
Definition: glext.h:7729
GLfloat bias
Definition: glext.h:7909
GLenum GLint GLuint mask
Definition: glext.h:6028
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
const GLfloat * m
Definition: glext.h:10848
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define b
Definition: ke_i.h:79
INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: lang.c:2591
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
int k
Definition: mpi.c:3369
const unsigned short nameprep_char_type[4432]
Definition: nameprep.c:5
const unsigned short nameprep_mapping[5856]
Definition: nameprep.c:565
unsigned int UINT
Definition: ndis.h:50
#define strlenW(s)
Definition: unicode.h:28
static FILE * out
Definition: regtests2xml.c:44
#define DPRINT
Definition: sndvol32.h:71
int32_t INT
Definition: typedefs.h:58
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define WINAPI
Definition: msvc.h:6
#define ERROR_NO_UNICODE_TRANSLATION
Definition: winerror.h:649
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
#define MAP_FOLDCZONE
Definition: winnls.h:213
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185