ReactOS  0.4.14-dev-41-g31d7680
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 
10 enum {
11  BASE = 36,
12  TMIN = 1,
13  TMAX = 26,
14  SKEW = 38,
15  DAMP = 700,
16  INIT_BIAS = 72,
17  INIT_N = 128
18 };
19 
20 static 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 
32 static 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 
37 INT 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 
249 INT 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;) {
276  INT n = INIT_N, bias = INIT_BIAS;
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 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
disp
Definition: i386-dis.c:3181
#define TRUE
Definition: types.h:120
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: lang.c:2195
GLdouble n
Definition: glext.h:7729
GLdouble GLdouble t
Definition: gl.h:2047
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static unsigned short get_table_entry(const unsigned short *table, WCHAR ch)
Definition: IdnToAscii.c:32
#define MAP_FOLDCZONE
Definition: winnls.h:210
const unsigned short nameprep_char_type[4432]
Definition: nameprep.c:5
int32_t INT
Definition: typedefs.h:56
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
GLenum GLint GLuint mask
Definition: glext.h:6028
unsigned int BOOL
Definition: ntddk_ex.h:94
static PVOID ptr
Definition: dispmode.c:27
GLfloat bias
Definition: glext.h:7909
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
const unsigned short nameprep_mapping[5856]
Definition: nameprep.c:565
#define b
Definition: ke_i.h:79
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define WINAPI
Definition: msvc.h:8
unsigned short WORD
Definition: ntddk_ex.h:93
static FILE * out
Definition: regtests2xml.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:409
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLbitfield flags
Definition: glext.h:7161
#define ERROR_NO_UNICODE_TRANSLATION
Definition: winerror.h:649
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static INT adapt(INT delta, INT numpoints, BOOL firsttime)
Definition: IdnToAscii.c:20
INT WINAPI IdnToNameprepUnicode(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpNameprepCharStr, INT cchNameprepChar)
Definition: IdnToAscii.c:37
unsigned int UINT
Definition: ndis.h:50
#define ERROR_INVALID_NAME
Definition: compat.h:93
WCHAR * LPWSTR
Definition: xmlstorage.h:184
int k
Definition: mpi.c:3369
#define HeapFree(x, y, z)
Definition: compat.h:394
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpASCIICharStr, INT cchASCIIChar)
Definition: IdnToAscii.c:249