898add1a7e3197a5f883a0d05aeebbbdb17824f3
[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
179 /***************** STRINGPREP *****************/
180 #ifdef USE_STRINGPREP_ICU
181
182 #include <unicode/usprep.h>
183 #include <unicode/ustring.h>
184 #include <unicode/utrace.h>
185
186 static int icu_stringprep_prep(lua_State *L, const UStringPrepProfile *profile)
187 {
188         size_t input_len;
189         int32_t unprepped_len, prepped_len, output_len;
190         const char *input;
191         char output[1024];
192
193         UChar unprepped[1024]; /* Temporary unicode buffer (1024 characters) */
194         UChar prepped[1024];
195         
196         UErrorCode err = U_ZERO_ERROR;
197
198         if(!lua_isstring(L, 1)) {
199                 lua_pushnil(L);
200                 return 1;
201         }
202         input = lua_tolstring(L, 1, &input_len);
203         if (input_len >= 1024) {
204                 lua_pushnil(L);
205                 return 1;
206         }
207         u_strFromUTF8(unprepped, 1024, &unprepped_len, input, input_len, &err);
208         if (U_FAILURE(err)) {
209                 lua_pushnil(L);
210                 return 1;
211         }
212         prepped_len = usprep_prepare(profile, unprepped, unprepped_len, prepped, 1024, 0, NULL, &err);
213         if (U_FAILURE(err)) {
214                 lua_pushnil(L);
215                 return 1;
216         } else {
217                 u_strToUTF8(output, 1024, &output_len, prepped, prepped_len, &err);
218                 if (U_SUCCESS(err) && output_len < 1024)
219                         lua_pushlstring(L, output, output_len);
220                 else
221                         lua_pushnil(L);
222                 return 1;
223         }
224 }
225
226 UStringPrepProfile *icu_nameprep;
227 UStringPrepProfile *icu_nodeprep;
228 UStringPrepProfile *icu_resourceprep; 
229 UStringPrepProfile *icu_saslprep;
230
231 /* initialize global ICU stringprep profiles */
232 void init_icu()
233 {
234         UErrorCode err = U_ZERO_ERROR;
235         utrace_setLevel(UTRACE_VERBOSE);
236         icu_nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, &err);
237         icu_nodeprep = usprep_openByType(USPREP_RFC3920_NODEPREP, &err);
238         icu_resourceprep = usprep_openByType(USPREP_RFC3920_RESOURCEPREP, &err);
239         icu_saslprep = usprep_openByType(USPREP_RFC4013_SASLPREP, &err);
240         if (U_FAILURE(err)) fprintf(stderr, "[c] util.encodings: error: %s\n", u_errorName((UErrorCode)err));
241 }
242
243 #define MAKE_PREP_FUNC(myFunc, prep) \
244 static int myFunc(lua_State *L) { return icu_stringprep_prep(L, prep); }
245
246 MAKE_PREP_FUNC(Lstringprep_nameprep, icu_nameprep)              /** stringprep.nameprep(s) */
247 MAKE_PREP_FUNC(Lstringprep_nodeprep, icu_nodeprep)              /** stringprep.nodeprep(s) */
248 MAKE_PREP_FUNC(Lstringprep_resourceprep, icu_resourceprep)              /** stringprep.resourceprep(s) */
249 MAKE_PREP_FUNC(Lstringprep_saslprep, icu_saslprep)              /** stringprep.saslprep(s) */
250
251 static const luaL_Reg Reg_stringprep[] =
252 {
253         { "nameprep",   Lstringprep_nameprep    },
254         { "nodeprep",   Lstringprep_nodeprep    },
255         { "resourceprep",       Lstringprep_resourceprep        },
256         { "saslprep",   Lstringprep_saslprep    },
257         { NULL,         NULL    }
258 };
259 #else /* USE_STRINGPREP_ICU */
260
261 /****************** libidn ********************/
262
263 #include <stringprep.h>
264
265 static int stringprep_prep(lua_State *L, const Stringprep_profile *profile)
266 {
267         size_t len;
268         const char *s;
269         char string[1024];
270         int ret;
271         if(!lua_isstring(L, 1)) {
272                 lua_pushnil(L);
273                 return 1;
274         }
275         s = check_utf8(L, 1, &len);
276         if (s == NULL || len >= 1024 || len != strlen(s)) {
277                 lua_pushnil(L);
278                 return 1; /* TODO return error message */
279         }
280         strcpy(string, s);
281         ret = stringprep(string, 1024, (Stringprep_profile_flags)0, profile);
282         if (ret == STRINGPREP_OK) {
283                 lua_pushstring(L, string);
284                 return 1;
285         } else {
286                 lua_pushnil(L);
287                 return 1; /* TODO return error message */
288         }
289 }
290
291 #define MAKE_PREP_FUNC(myFunc, prep) \
292 static int myFunc(lua_State *L) { return stringprep_prep(L, prep); }
293
294 MAKE_PREP_FUNC(Lstringprep_nameprep, stringprep_nameprep)               /** stringprep.nameprep(s) */
295 MAKE_PREP_FUNC(Lstringprep_nodeprep, stringprep_xmpp_nodeprep)          /** stringprep.nodeprep(s) */
296 MAKE_PREP_FUNC(Lstringprep_resourceprep, stringprep_xmpp_resourceprep)          /** stringprep.resourceprep(s) */
297 MAKE_PREP_FUNC(Lstringprep_saslprep, stringprep_saslprep)               /** stringprep.saslprep(s) */
298
299 static const luaL_Reg Reg_stringprep[] =
300 {
301         { "nameprep",   Lstringprep_nameprep    },
302         { "nodeprep",   Lstringprep_nodeprep    },
303         { "resourceprep",       Lstringprep_resourceprep        },
304         { "saslprep",   Lstringprep_saslprep    },
305         { NULL,         NULL    }
306 };
307 #endif
308
309 /***************** IDNA *****************/
310 #ifdef USE_STRINGPREP_ICU
311 #include <unicode/ustdio.h>
312 #include <unicode/uidna.h>
313 /* IDNA2003 or IDNA2008 ? ? ? */
314 static int Lidna_to_ascii(lua_State *L)         /** idna.to_ascii(s) */
315 {
316         size_t len;
317         int32_t ulen, dest_len, output_len;
318         const char *s = luaL_checklstring(L, 1, &len);
319         UChar ustr[1024];
320         UErrorCode err = U_ZERO_ERROR;
321         UChar dest[1024];
322         char output[1024];
323
324         u_strFromUTF8(ustr, 1024, &ulen, s, len, &err);
325         if (U_FAILURE(err)) {
326                 lua_pushnil(L);
327                 return 1;
328         }
329
330         dest_len = uidna_IDNToASCII(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err);
331         if (U_FAILURE(err)) {
332                 lua_pushnil(L);
333                 return 1;
334         } else {
335                 u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err);
336                 if (U_SUCCESS(err) && output_len < 1024)
337                         lua_pushlstring(L, output, output_len);
338                 else
339                         lua_pushnil(L);
340                 return 1;
341         }
342 }
343
344 static int Lidna_to_unicode(lua_State *L)               /** idna.to_unicode(s) */
345 {
346         size_t len;
347         int32_t ulen, dest_len, output_len;
348         const char *s = luaL_checklstring(L, 1, &len);
349         UChar ustr[1024];
350         UErrorCode err = U_ZERO_ERROR;
351         UChar dest[1024];
352         char output[1024];
353
354         u_strFromUTF8(ustr, 1024, &ulen, s, len, &err);
355         if (U_FAILURE(err)) {
356                 lua_pushnil(L);
357                 return 1;
358         }
359
360         dest_len = uidna_IDNToUnicode(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err);
361         if (U_FAILURE(err)) {
362                 lua_pushnil(L);
363                 return 1;
364         } else {
365                 u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err);
366                 if (U_SUCCESS(err) && output_len < 1024)
367                         lua_pushlstring(L, output, output_len);
368                 else
369                         lua_pushnil(L);
370                 return 1;
371         }
372 }
373
374 #else /* USE_STRINGPREP_ICU */
375 /****************** libidn ********************/
376
377 #include <idna.h>
378 #include <idn-free.h>
379
380 static int Lidna_to_ascii(lua_State *L)         /** idna.to_ascii(s) */
381 {
382         size_t len;
383         const char *s = check_utf8(L, 1, &len);
384         if (s == NULL || len != strlen(s)) {
385                 lua_pushnil(L);
386                 return 1; /* TODO return error message */
387         }
388         char* output = NULL;
389         int ret = idna_to_ascii_8z(s, &output, IDNA_USE_STD3_ASCII_RULES);
390         if (ret == IDNA_SUCCESS) {
391                 lua_pushstring(L, output);
392                 idn_free(output);
393                 return 1;
394         } else {
395                 lua_pushnil(L);
396                 idn_free(output);
397                 return 1; /* TODO return error message */
398         }
399 }
400
401 static int Lidna_to_unicode(lua_State *L)               /** idna.to_unicode(s) */
402 {
403         size_t len;
404         const char *s = luaL_checklstring(L, 1, &len);
405         char* output = NULL;
406         int ret = idna_to_unicode_8z8z(s, &output, 0);
407         if (ret == IDNA_SUCCESS) {
408                 lua_pushstring(L, output);
409                 idn_free(output);
410                 return 1;
411         } else {
412                 lua_pushnil(L);
413                 idn_free(output);
414                 return 1; /* TODO return error message */
415         }
416 }
417 #endif
418
419 static const luaL_Reg Reg_idna[] =
420 {
421         { "to_ascii",   Lidna_to_ascii  },
422         { "to_unicode", Lidna_to_unicode        },
423         { NULL,         NULL    }
424 };
425
426 /***************** end *****************/
427
428 static const luaL_Reg Reg[] =
429 {
430         { NULL,         NULL    }
431 };
432
433 LUALIB_API int luaopen_util_encodings(lua_State *L)
434 {
435 #ifdef USE_STRINGPREP_ICU
436         init_icu();
437 #endif
438         luaL_register(L, "encodings", Reg);
439
440         lua_pushliteral(L, "base64");
441         lua_newtable(L);
442         luaL_register(L, NULL, Reg_base64);
443         lua_settable(L,-3);
444
445         lua_pushliteral(L, "stringprep");
446         lua_newtable(L);
447         luaL_register(L, NULL, Reg_stringprep);
448         lua_settable(L,-3);
449
450         lua_pushliteral(L, "idna");
451         lua_newtable(L);
452         luaL_register(L, NULL, Reg_idna);
453         lua_settable(L,-3);
454
455         lua_pushliteral(L, "version");                  /** version */
456         lua_pushliteral(L, "-3.14");
457         lua_settable(L,-3);
458         return 1;
459 }