2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 -- Copyright (C) 1994-2015 Lua.org, PUC-Rio.
6 -- This project is MIT/X11 licensed. Please see the
7 -- COPYING file in the source package for more information.
13 * Lua library for base64, stringprep and idna encodings
16 /* Newer MSVC compilers deprecate strcpy as unsafe, but we use it in a safe way */
17 #define _CRT_SECURE_NO_DEPRECATE
24 #if (LUA_VERSION_NUM == 501)
25 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R)
28 /***************** BASE64 *****************/
30 static const char code
[] =
31 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
33 static void base64_encode(luaL_Buffer
*b
, unsigned int c1
, unsigned int c2
, unsigned int c3
, int n
) {
34 unsigned long tuple
= c3
+ 256UL * (c2
+ 256UL * c1
);
38 for(i
= 0; i
< 4; i
++) {
39 s
[3 - i
] = code
[tuple
% 64];
43 for(i
= n
+ 1; i
< 4; i
++) {
47 luaL_addlstring(b
, s
, 4);
50 static int Lbase64_encode(lua_State
*L
) { /** encode(s) */
52 const unsigned char *s
= (const unsigned char *)luaL_checklstring(L
, 1, &l
);
57 for(n
= l
/ 3; n
--; s
+= 3) {
58 base64_encode(&b
, s
[0], s
[1], s
[2], 3);
63 base64_encode(&b
, s
[0], 0, 0, 1);
67 base64_encode(&b
, s
[0], s
[1], 0, 2);
75 static void base64_decode(luaL_Buffer
*b
, int c1
, int c2
, int c3
, int c4
, int n
) {
76 unsigned long tuple
= c4
+ 64L * (c3
+ 64L * (c2
+ 64L * c1
));
84 s
[1] = (char)(tuple
>> 8);
87 s
[0] = (char)(tuple
>> 16);
90 luaL_addlstring(b
, s
, n
);
93 static int Lbase64_decode(lua_State
*L
) { /** decode(s) */
95 const char *s
= luaL_checklstring(L
, 1, &l
);
114 t
[n
++] = (char)(p
- code
);
117 base64_decode(&b
, t
[0], t
[1], t
[2], t
[3], 4);
127 base64_decode(&b
, t
[0], 0, 0, 0, 1);
131 base64_decode(&b
, t
[0], t
[1], 0, 0, 2);
135 base64_decode(&b
, t
[0], t
[1], t
[2], 0, 3);
157 static const luaL_Reg Reg_base64
[] = {
158 { "encode", Lbase64_encode
},
159 { "decode", Lbase64_decode
},
163 /******************* UTF-8 ********************/
166 * Adapted from Lua 5.3
167 * Needed because libidn does not validate that input is valid UTF-8
170 #define MAXUNICODE 0x10FFFF
173 * Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
175 static const char *utf8_decode(const char *o
, int *val
) {
176 static const unsigned int limits
[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
177 const unsigned char *s
= (const unsigned char *)o
;
178 unsigned int c
= s
[0];
179 unsigned int res
= 0; /* final result */
181 if(c
< 0x80) { /* ascii? */
184 int count
= 0; /* to count number of continuation bytes */
186 while(c
& 0x40) { /* still have continuation bytes? */
187 int cc
= s
[++count
]; /* read next byte */
189 if((cc
& 0xC0) != 0x80) { /* not a continuation byte? */
190 return NULL
; /* invalid byte sequence */
193 res
= (res
<< 6) | (cc
& 0x3F); /* add lower 6 bits from cont. byte */
194 c
<<= 1; /* to test next bit */
197 res
|= ((c
& 0x7F) << (count
* 5)); /* add first byte */
199 if(count
> 3 || res
> MAXUNICODE
|| res
<= limits
[count
] || (0xd800 <= res
&& res
<= 0xdfff)) {
200 return NULL
; /* invalid byte sequence */
203 s
+= count
; /* skip continuation bytes read */
210 return (const char *)s
+ 1; /* +1 to include first byte */
214 * Check that a string is valid UTF-8
215 * Returns NULL if not
217 const char *check_utf8(lua_State
*L
, int idx
, size_t *l
) {
219 const char *s
= luaL_checklstring(L
, 1, &len
);
223 const char *s1
= utf8_decode(s
+ pos
, NULL
);
225 if(s1
== NULL
) { /* conversion error? */
239 static int Lutf8_valid(lua_State
*L
) {
240 lua_pushboolean(L
, check_utf8(L
, 1, NULL
) != NULL
);
244 static int Lutf8_length(lua_State
*L
) {
247 if(!check_utf8(L
, 1, &len
)) {
249 lua_pushliteral(L
, "invalid utf8");
253 lua_pushinteger(L
, len
);
257 static const luaL_Reg Reg_utf8
[] = {
258 { "valid", Lutf8_valid
},
259 { "length", Lutf8_length
},
263 /***************** STRINGPREP *****************/
264 #ifdef USE_STRINGPREP_ICU
266 #include <unicode/usprep.h>
267 #include <unicode/ustring.h>
268 #include <unicode/utrace.h>
270 static int icu_stringprep_prep(lua_State
*L
, const UStringPrepProfile
*profile
) {
272 int32_t unprepped_len
, prepped_len
, output_len
;
276 UChar unprepped
[1024]; /* Temporary unicode buffer (1024 characters) */
279 UErrorCode err
= U_ZERO_ERROR
;
281 if(!lua_isstring(L
, 1)) {
286 input
= lua_tolstring(L
, 1, &input_len
);
288 if(input_len
>= 1024) {
293 u_strFromUTF8(unprepped
, 1024, &unprepped_len
, input
, input_len
, &err
);
300 prepped_len
= usprep_prepare(profile
, unprepped
, unprepped_len
, prepped
, 1024, 0, NULL
, &err
);
306 u_strToUTF8(output
, 1024, &output_len
, prepped
, prepped_len
, &err
);
308 if(U_SUCCESS(err
) && output_len
< 1024) {
309 lua_pushlstring(L
, output
, output_len
);
318 UStringPrepProfile
*icu_nameprep
;
319 UStringPrepProfile
*icu_nodeprep
;
320 UStringPrepProfile
*icu_resourceprep
;
321 UStringPrepProfile
*icu_saslprep
;
323 /* initialize global ICU stringprep profiles */
325 UErrorCode err
= U_ZERO_ERROR
;
326 utrace_setLevel(UTRACE_VERBOSE
);
327 icu_nameprep
= usprep_openByType(USPREP_RFC3491_NAMEPREP
, &err
);
328 icu_nodeprep
= usprep_openByType(USPREP_RFC3920_NODEPREP
, &err
);
329 icu_resourceprep
= usprep_openByType(USPREP_RFC3920_RESOURCEPREP
, &err
);
330 icu_saslprep
= usprep_openByType(USPREP_RFC4013_SASLPREP
, &err
);
333 fprintf(stderr
, "[c] util.encodings: error: %s\n", u_errorName((UErrorCode
)err
));
337 #define MAKE_PREP_FUNC(myFunc, prep) \
338 static int myFunc(lua_State *L) { return icu_stringprep_prep(L, prep); }
340 MAKE_PREP_FUNC(Lstringprep_nameprep
, icu_nameprep
) /** stringprep.nameprep(s) */
341 MAKE_PREP_FUNC(Lstringprep_nodeprep
, icu_nodeprep
) /** stringprep.nodeprep(s) */
342 MAKE_PREP_FUNC(Lstringprep_resourceprep
, icu_resourceprep
) /** stringprep.resourceprep(s) */
343 MAKE_PREP_FUNC(Lstringprep_saslprep
, icu_saslprep
) /** stringprep.saslprep(s) */
345 static const luaL_Reg Reg_stringprep
[] = {
346 { "nameprep", Lstringprep_nameprep
},
347 { "nodeprep", Lstringprep_nodeprep
},
348 { "resourceprep", Lstringprep_resourceprep
},
349 { "saslprep", Lstringprep_saslprep
},
352 #else /* USE_STRINGPREP_ICU */
354 /****************** libidn ********************/
356 #include <stringprep.h>
358 static int stringprep_prep(lua_State
*L
, const Stringprep_profile
*profile
) {
364 if(!lua_isstring(L
, 1)) {
369 s
= check_utf8(L
, 1, &len
);
371 if(s
== NULL
|| len
>= 1024 || len
!= strlen(s
)) {
373 return 1; /* TODO return error message */
377 ret
= stringprep(string
, 1024, (Stringprep_profile_flags
)0, profile
);
379 if(ret
== STRINGPREP_OK
) {
380 lua_pushstring(L
, string
);
384 return 1; /* TODO return error message */
388 #define MAKE_PREP_FUNC(myFunc, prep) \
389 static int myFunc(lua_State *L) { return stringprep_prep(L, prep); }
391 MAKE_PREP_FUNC(Lstringprep_nameprep
, stringprep_nameprep
) /** stringprep.nameprep(s) */
392 MAKE_PREP_FUNC(Lstringprep_nodeprep
, stringprep_xmpp_nodeprep
) /** stringprep.nodeprep(s) */
393 MAKE_PREP_FUNC(Lstringprep_resourceprep
, stringprep_xmpp_resourceprep
) /** stringprep.resourceprep(s) */
394 MAKE_PREP_FUNC(Lstringprep_saslprep
, stringprep_saslprep
) /** stringprep.saslprep(s) */
396 static const luaL_Reg Reg_stringprep
[] = {
397 { "nameprep", Lstringprep_nameprep
},
398 { "nodeprep", Lstringprep_nodeprep
},
399 { "resourceprep", Lstringprep_resourceprep
},
400 { "saslprep", Lstringprep_saslprep
},
405 /***************** IDNA *****************/
406 #ifdef USE_STRINGPREP_ICU
407 #include <unicode/ustdio.h>
408 #include <unicode/uidna.h>
409 /* IDNA2003 or IDNA2008 ? ? ? */
410 static int Lidna_to_ascii(lua_State
*L
) { /** idna.to_ascii(s) */
412 int32_t ulen
, dest_len
, output_len
;
413 const char *s
= luaL_checklstring(L
, 1, &len
);
415 UErrorCode err
= U_ZERO_ERROR
;
419 u_strFromUTF8(ustr
, 1024, &ulen
, s
, len
, &err
);
426 dest_len
= uidna_IDNToASCII(ustr
, ulen
, dest
, 1024, UIDNA_USE_STD3_RULES
, NULL
, &err
);
432 u_strToUTF8(output
, 1024, &output_len
, dest
, dest_len
, &err
);
434 if(U_SUCCESS(err
) && output_len
< 1024) {
435 lua_pushlstring(L
, output
, output_len
);
444 static int Lidna_to_unicode(lua_State
*L
) { /** idna.to_unicode(s) */
446 int32_t ulen
, dest_len
, output_len
;
447 const char *s
= luaL_checklstring(L
, 1, &len
);
449 UErrorCode err
= U_ZERO_ERROR
;
453 u_strFromUTF8(ustr
, 1024, &ulen
, s
, len
, &err
);
460 dest_len
= uidna_IDNToUnicode(ustr
, ulen
, dest
, 1024, UIDNA_USE_STD3_RULES
, NULL
, &err
);
466 u_strToUTF8(output
, 1024, &output_len
, dest
, dest_len
, &err
);
468 if(U_SUCCESS(err
) && output_len
< 1024) {
469 lua_pushlstring(L
, output
, output_len
);
478 #else /* USE_STRINGPREP_ICU */
479 /****************** libidn ********************/
482 #include <idn-free.h>
484 static int Lidna_to_ascii(lua_State
*L
) { /** idna.to_ascii(s) */
486 const char *s
= check_utf8(L
, 1, &len
);
490 if(s
== NULL
|| len
!= strlen(s
)) {
492 return 1; /* TODO return error message */
495 ret
= idna_to_ascii_8z(s
, &output
, IDNA_USE_STD3_ASCII_RULES
);
497 if(ret
== IDNA_SUCCESS
) {
498 lua_pushstring(L
, output
);
504 return 1; /* TODO return error message */
508 static int Lidna_to_unicode(lua_State
*L
) { /** idna.to_unicode(s) */
510 const char *s
= luaL_checklstring(L
, 1, &len
);
512 int ret
= idna_to_unicode_8z8z(s
, &output
, 0);
514 if(ret
== IDNA_SUCCESS
) {
515 lua_pushstring(L
, output
);
521 return 1; /* TODO return error message */
526 static const luaL_Reg Reg_idna
[] = {
527 { "to_ascii", Lidna_to_ascii
},
528 { "to_unicode", Lidna_to_unicode
},
532 /***************** end *****************/
534 LUALIB_API
int luaopen_util_encodings(lua_State
*L
) {
535 #if (LUA_VERSION_NUM > 501)
536 luaL_checkversion(L
);
538 #ifdef USE_STRINGPREP_ICU
544 luaL_setfuncs(L
, Reg_base64
, 0);
545 lua_setfield(L
, -2, "base64");
548 luaL_setfuncs(L
, Reg_stringprep
, 0);
549 lua_setfield(L
, -2, "stringprep");
552 luaL_setfuncs(L
, Reg_idna
, 0);
553 lua_setfield(L
, -2, "idna");
556 luaL_setfuncs(L
, Reg_utf8
, 0);
557 lua_setfield(L
, -2, "utf8");
559 lua_pushliteral(L
, "-3.14");
560 lua_setfield(L
, -2, "version");