Merge with Zash
[prosody.git] / util-src / encodings.c
1 /* Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 -- Copyright (C) 1994-2015 Lua.org, PUC-Rio.
5 -- 
6 -- This project is MIT/X11 licensed. Please see the
7 -- COPYING file in the source package for more information.
8 --
9 */
10
11 /*
12 * encodings.c
13 * Lua library for base64, stringprep and idna encodings
14 */
15
16 /* Newer MSVC compilers deprecate strcpy as unsafe, but we use it in a safe way */
17 #define _CRT_SECURE_NO_DEPRECATE
18
19 #include <string.h>
20 #include <stdlib.h>
21 #include "lua.h"
22 #include "lauxlib.h"
23
24 /***************** BASE64 *****************/
25
26 static const char code[]=
27 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
28
29 static void base64_encode(luaL_Buffer *b, unsigned int c1, unsigned int c2, unsigned int c3, int n)
30 {
31         unsigned long tuple=c3+256UL*(c2+256UL*c1);
32         int i;
33         char s[4];
34         for (i=0; i<4; i++) {
35                 s[3-i] = code[tuple % 64];
36                 tuple /= 64;
37         }
38         for (i=n+1; i<4; i++) s[i]='=';
39         luaL_addlstring(b,s,4);
40 }
41
42 static int Lbase64_encode(lua_State *L)         /** encode(s) */
43 {
44         size_t l;
45         const unsigned char *s=(const unsigned char*)luaL_checklstring(L,1,&l);
46         luaL_Buffer b;
47         int n;
48         luaL_buffinit(L,&b);
49         for (n=l/3; n--; s+=3) base64_encode(&b,s[0],s[1],s[2],3);
50         switch (l%3)
51         {
52                 case 1: base64_encode(&b,s[0],0,0,1);           break;
53                 case 2: base64_encode(&b,s[0],s[1],0,2);                break;
54         }
55         luaL_pushresult(&b);
56         return 1;
57 }
58
59 static void base64_decode(luaL_Buffer *b, int c1, int c2, int c3, int c4, int n)
60 {
61         unsigned long tuple=c4+64L*(c3+64L*(c2+64L*c1));
62         char s[3];
63         switch (--n)
64         {
65                 case 3: s[2]=(char) tuple;
66                 case 2: s[1]=(char) (tuple >> 8);
67                 case 1: s[0]=(char) (tuple >> 16);
68         }
69         luaL_addlstring(b,s,n);
70 }
71
72 static int Lbase64_decode(lua_State *L)         /** decode(s) */
73 {
74         size_t l;
75         const char *s=luaL_checklstring(L,1,&l);
76         luaL_Buffer b;
77         int n=0;
78         char t[4];
79         luaL_buffinit(L,&b);
80         for (;;)
81         {
82                 int c=*s++;
83                 switch (c)
84                 {
85                         const char *p;
86                         default:
87                                 p=strchr(code,c); if (p==NULL) return 0;
88                                 t[n++]= (char) (p-code);
89                                 if (n==4)
90                                 {
91                                         base64_decode(&b,t[0],t[1],t[2],t[3],4);
92                                         n=0;
93                                 }
94                                 break;
95                         case '=':
96                                 switch (n)
97                                 {
98                                         case 1: base64_decode(&b,t[0],0,0,0,1);         break;
99                                         case 2: base64_decode(&b,t[0],t[1],0,0,2);      break;
100                                         case 3: base64_decode(&b,t[0],t[1],t[2],0,3);   break;
101                                 }
102                                 n=0;
103                                 break;
104                         case 0:
105                                 luaL_pushresult(&b);
106                                 return 1;
107                         case '\n': case '\r': case '\t': case ' ': case '\f': case '\b':
108                                 break;
109                 }
110         }
111 }
112
113 static const luaL_Reg Reg_base64[] =
114 {
115         { "encode",     Lbase64_encode  },
116         { "decode",     Lbase64_decode  },
117         { NULL,         NULL    }
118 };
119
120 /******************* UTF-8 ********************/
121
122 /*
123  * Adapted from Lua 5.3
124  * Needed because libidn does not validate that input is valid UTF-8
125  */
126
127 #define MAXUNICODE      0x10FFFF
128
129 /*
130  * Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
131  */
132 static const char *utf8_decode (const char *o, int *val) {
133         static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
134         const unsigned char *s = (const unsigned char *)o;
135         unsigned int c = s[0];
136         unsigned int res = 0;  /* final result */
137         if (c < 0x80)  /* ascii? */
138                 res = c;
139         else {
140                 int count = 0;  /* to count number of continuation bytes */
141                 while (c & 0x40) {  /* still have continuation bytes? */
142                         int cc = s[++count];  /* read next byte */
143                         if ((cc & 0xC0) != 0x80)  /* not a continuation byte? */
144                                 return NULL;  /* invalid byte sequence */
145                         res = (res << 6) | (cc & 0x3F);  /* add lower 6 bits from cont. byte */
146                         c <<= 1;  /* to test next bit */
147                 }
148                 res |= ((c & 0x7F) << (count * 5));  /* add first byte */
149                 if (count > 3 || res > MAXUNICODE || res <= limits[count] || (0xd800 <= res && res <= 0xdfff) )
150                         return NULL;  /* invalid byte sequence */
151                 s += count;  /* skip continuation bytes read */
152         }
153         if (val) *val = res;
154         return (const char *)s + 1;  /* +1 to include first byte */
155 }
156
157 /*
158  * Check that a string is valid UTF-8
159  * Returns NULL if not
160  */
161 const char* check_utf8 (lua_State *L, int idx, size_t *l) {
162         size_t pos, len;
163         const char *s = luaL_checklstring(L, 1, &len);
164         pos = 0;
165         while (pos <= len) {
166                 const char *s1 = utf8_decode(s + pos, NULL);
167                 if (s1 == NULL) {  /* conversion error? */
168                         return NULL;
169                 }
170                 pos = s1 - s;
171         }
172         if(l != NULL) {
173                 *l = len;
174         }
175         return s;
176 }
177
178 static int Lutf8_valid(lua_State *L) {
179         lua_pushboolean(L, check_utf8(L, 1, NULL) != NULL);
180         return 1;
181 }
182
183 static int Lutf8_length(lua_State *L) {
184         size_t len;
185         if(!check_utf8(L, 1, &len)) {
186                 lua_pushnil(L);
187                 lua_pushliteral(L, "invalid utf8");
188                 return 2;
189         }
190         lua_pushinteger(L, len);
191         return 1;
192 }
193
194 static const luaL_Reg Reg_utf8[] =
195 {
196         { "valid",      Lutf8_valid     },
197         { "length",     Lutf8_length    },
198         { NULL,         NULL    }
199 };
200
201
202 /***************** STRINGPREP *****************/
203 #ifdef USE_STRINGPREP_ICU
204
205 #include <unicode/usprep.h>
206 #include <unicode/ustring.h>
207 #include <unicode/utrace.h>
208
209 static int icu_stringprep_prep(lua_State *L, const UStringPrepProfile *profile)
210 {
211         size_t input_len;
212         int32_t unprepped_len, prepped_len, output_len;
213         const char *input;
214         char output[1024];
215
216         UChar unprepped[1024]; /* Temporary unicode buffer (1024 characters) */
217         UChar prepped[1024];
218         
219         UErrorCode err = U_ZERO_ERROR;
220
221         if(!lua_isstring(L, 1)) {
222                 lua_pushnil(L);
223                 return 1;
224         }
225         input = lua_tolstring(L, 1, &input_len);
226         if (input_len >= 1024) {
227                 lua_pushnil(L);
228                 return 1;
229         }
230         u_strFromUTF8(unprepped, 1024, &unprepped_len, input, input_len, &err);
231         if (U_FAILURE(err)) {
232                 lua_pushnil(L);
233                 return 1;
234         }
235         prepped_len = usprep_prepare(profile, unprepped, unprepped_len, prepped, 1024, 0, NULL, &err);
236         if (U_FAILURE(err)) {
237                 lua_pushnil(L);
238                 return 1;
239         } else {
240                 u_strToUTF8(output, 1024, &output_len, prepped, prepped_len, &err);
241                 if (U_SUCCESS(err) && output_len < 1024)
242                         lua_pushlstring(L, output, output_len);
243                 else
244                         lua_pushnil(L);
245                 return 1;
246         }
247 }
248
249 UStringPrepProfile *icu_nameprep;
250 UStringPrepProfile *icu_nodeprep;
251 UStringPrepProfile *icu_resourceprep; 
252 UStringPrepProfile *icu_saslprep;
253
254 /* initialize global ICU stringprep profiles */
255 void init_icu()
256 {
257         UErrorCode err = U_ZERO_ERROR;
258         utrace_setLevel(UTRACE_VERBOSE);
259         icu_nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, &err);
260         icu_nodeprep = usprep_openByType(USPREP_RFC3920_NODEPREP, &err);
261         icu_resourceprep = usprep_openByType(USPREP_RFC3920_RESOURCEPREP, &err);
262         icu_saslprep = usprep_openByType(USPREP_RFC4013_SASLPREP, &err);
263         if (U_FAILURE(err)) fprintf(stderr, "[c] util.encodings: error: %s\n", u_errorName((UErrorCode)err));
264 }
265
266 #define MAKE_PREP_FUNC(myFunc, prep) \
267 static int myFunc(lua_State *L) { return icu_stringprep_prep(L, prep); }
268
269 MAKE_PREP_FUNC(Lstringprep_nameprep, icu_nameprep)              /** stringprep.nameprep(s) */
270 MAKE_PREP_FUNC(Lstringprep_nodeprep, icu_nodeprep)              /** stringprep.nodeprep(s) */
271 MAKE_PREP_FUNC(Lstringprep_resourceprep, icu_resourceprep)              /** stringprep.resourceprep(s) */
272 MAKE_PREP_FUNC(Lstringprep_saslprep, icu_saslprep)              /** stringprep.saslprep(s) */
273
274 static const luaL_Reg Reg_stringprep[] =
275 {
276         { "nameprep",   Lstringprep_nameprep    },
277         { "nodeprep",   Lstringprep_nodeprep    },
278         { "resourceprep",       Lstringprep_resourceprep        },
279         { "saslprep",   Lstringprep_saslprep    },
280         { NULL,         NULL    }
281 };
282 #else /* USE_STRINGPREP_ICU */
283
284 /****************** libidn ********************/
285
286 #include <stringprep.h>
287
288 static int stringprep_prep(lua_State *L, const Stringprep_profile *profile)
289 {
290         size_t len;
291         const char *s;
292         char string[1024];
293         int ret;
294         if(!lua_isstring(L, 1)) {
295                 lua_pushnil(L);
296                 return 1;
297         }
298         s = check_utf8(L, 1, &len);
299         if (s == NULL || len >= 1024 || len != strlen(s)) {
300                 lua_pushnil(L);
301                 return 1; /* TODO return error message */
302         }
303         strcpy(string, s);
304         ret = stringprep(string, 1024, (Stringprep_profile_flags)0, profile);
305         if (ret == STRINGPREP_OK) {
306                 lua_pushstring(L, string);
307                 return 1;
308         } else {
309                 lua_pushnil(L);
310                 return 1; /* TODO return error message */
311         }
312 }
313
314 #define MAKE_PREP_FUNC(myFunc, prep) \
315 static int myFunc(lua_State *L) { return stringprep_prep(L, prep); }
316
317 MAKE_PREP_FUNC(Lstringprep_nameprep, stringprep_nameprep)               /** stringprep.nameprep(s) */
318 MAKE_PREP_FUNC(Lstringprep_nodeprep, stringprep_xmpp_nodeprep)          /** stringprep.nodeprep(s) */
319 MAKE_PREP_FUNC(Lstringprep_resourceprep, stringprep_xmpp_resourceprep)          /** stringprep.resourceprep(s) */
320 MAKE_PREP_FUNC(Lstringprep_saslprep, stringprep_saslprep)               /** stringprep.saslprep(s) */
321
322 static const luaL_Reg Reg_stringprep[] =
323 {
324         { "nameprep",   Lstringprep_nameprep    },
325         { "nodeprep",   Lstringprep_nodeprep    },
326         { "resourceprep",       Lstringprep_resourceprep        },
327         { "saslprep",   Lstringprep_saslprep    },
328         { NULL,         NULL    }
329 };
330 #endif
331
332 /***************** IDNA *****************/
333 #ifdef USE_STRINGPREP_ICU
334 #include <unicode/ustdio.h>
335 #include <unicode/uidna.h>
336 /* IDNA2003 or IDNA2008 ? ? ? */
337 static int Lidna_to_ascii(lua_State *L)         /** idna.to_ascii(s) */
338 {
339         size_t len;
340         int32_t ulen, dest_len, output_len;
341         const char *s = luaL_checklstring(L, 1, &len);
342         UChar ustr[1024];
343         UErrorCode err = U_ZERO_ERROR;
344         UChar dest[1024];
345         char output[1024];
346
347         u_strFromUTF8(ustr, 1024, &ulen, s, len, &err);
348         if (U_FAILURE(err)) {
349                 lua_pushnil(L);
350                 return 1;
351         }
352
353         dest_len = uidna_IDNToASCII(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err);
354         if (U_FAILURE(err)) {
355                 lua_pushnil(L);
356                 return 1;
357         } else {
358                 u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err);
359                 if (U_SUCCESS(err) && output_len < 1024)
360                         lua_pushlstring(L, output, output_len);
361                 else
362                         lua_pushnil(L);
363                 return 1;
364         }
365 }
366
367 static int Lidna_to_unicode(lua_State *L)               /** idna.to_unicode(s) */
368 {
369         size_t len;
370         int32_t ulen, dest_len, output_len;
371         const char *s = luaL_checklstring(L, 1, &len);
372         UChar ustr[1024];
373         UErrorCode err = U_ZERO_ERROR;
374         UChar dest[1024];
375         char output[1024];
376
377         u_strFromUTF8(ustr, 1024, &ulen, s, len, &err);
378         if (U_FAILURE(err)) {
379                 lua_pushnil(L);
380                 return 1;
381         }
382
383         dest_len = uidna_IDNToUnicode(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err);
384         if (U_FAILURE(err)) {
385                 lua_pushnil(L);
386                 return 1;
387         } else {
388                 u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err);
389                 if (U_SUCCESS(err) && output_len < 1024)
390                         lua_pushlstring(L, output, output_len);
391                 else
392                         lua_pushnil(L);
393                 return 1;
394         }
395 }
396
397 #else /* USE_STRINGPREP_ICU */
398 /****************** libidn ********************/
399
400 #include <idna.h>
401 #include <idn-free.h>
402
403 static int Lidna_to_ascii(lua_State *L)         /** idna.to_ascii(s) */
404 {
405         size_t len;
406         const char *s = check_utf8(L, 1, &len);
407         if (s == NULL || len != strlen(s)) {
408                 lua_pushnil(L);
409                 return 1; /* TODO return error message */
410         }
411         char* output = NULL;
412         int ret = idna_to_ascii_8z(s, &output, IDNA_USE_STD3_ASCII_RULES);
413         if (ret == IDNA_SUCCESS) {
414                 lua_pushstring(L, output);
415                 idn_free(output);
416                 return 1;
417         } else {
418                 lua_pushnil(L);
419                 idn_free(output);
420                 return 1; /* TODO return error message */
421         }
422 }
423
424 static int Lidna_to_unicode(lua_State *L)               /** idna.to_unicode(s) */
425 {
426         size_t len;
427         const char *s = luaL_checklstring(L, 1, &len);
428         char* output = NULL;
429         int ret = idna_to_unicode_8z8z(s, &output, 0);
430         if (ret == IDNA_SUCCESS) {
431                 lua_pushstring(L, output);
432                 idn_free(output);
433                 return 1;
434         } else {
435                 lua_pushnil(L);
436                 idn_free(output);
437                 return 1; /* TODO return error message */
438         }
439 }
440 #endif
441
442 static const luaL_Reg Reg_idna[] =
443 {
444         { "to_ascii",   Lidna_to_ascii  },
445         { "to_unicode", Lidna_to_unicode        },
446         { NULL,         NULL    }
447 };
448
449 /***************** end *****************/
450
451 static const luaL_Reg Reg[] =
452 {
453         { NULL,         NULL    }
454 };
455
456 LUALIB_API int luaopen_util_encodings(lua_State *L)
457 {
458 #ifdef USE_STRINGPREP_ICU
459         init_icu();
460 #endif
461         luaL_register(L, "encodings", Reg);
462
463         lua_pushliteral(L, "base64");
464         lua_newtable(L);
465         luaL_register(L, NULL, Reg_base64);
466         lua_settable(L,-3);
467
468         lua_pushliteral(L, "stringprep");
469         lua_newtable(L);
470         luaL_register(L, NULL, Reg_stringprep);
471         lua_settable(L,-3);
472
473         lua_pushliteral(L, "idna");
474         lua_newtable(L);
475         luaL_register(L, NULL, Reg_idna);
476         lua_settable(L,-3);
477
478         lua_pushliteral(L, "utf8");
479         lua_newtable(L);
480         luaL_register(L, NULL, Reg_utf8);
481         lua_settable(L, -3);
482
483         lua_pushliteral(L, "version");                  /** version */
484         lua_pushliteral(L, "-3.14");
485         lua_settable(L,-3);
486         return 1;
487 }