aboutsummaryrefslogtreecommitdiffstats
path: root/util-src/encodings.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-src/encodings.c')
-rw-r--r--util-src/encodings.c191
1 files changed, 174 insertions, 17 deletions
diff --git a/util-src/encodings.c b/util-src/encodings.c
index d7aabc14..b9b6160a 100644
--- a/util-src/encodings.c
+++ b/util-src/encodings.c
@@ -1,6 +1,6 @@
-/* Prosody IM v0.4
--- Copyright (C) 2008-2009 Matthew Wild
--- Copyright (C) 2008-2009 Waqas Hussain
+/* Prosody IM
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
@@ -12,12 +12,11 @@
* Lua library for base64, stringprep and idna encodings
*/
-// Newer MSVC compilers deprecate strcpy as unsafe, but we use it in a safe way
+/* Newer MSVC compilers deprecate strcpy as unsafe, but we use it in a safe way */
#define _CRT_SECURE_NO_DEPRECATE
#include <string.h>
#include <stdlib.h>
-
#include "lua.h"
#include "lauxlib.h"
@@ -108,7 +107,6 @@ static int Lbase64_decode(lua_State *L) /** decode(s) */
break;
}
}
- return 0;
}
static const luaL_Reg Reg_base64[] =
@@ -119,27 +117,114 @@ static const luaL_Reg Reg_base64[] =
};
/***************** STRINGPREP *****************/
+#ifdef USE_STRINGPREP_ICU
+
+#include <unicode/usprep.h>
+#include <unicode/ustring.h>
+#include <unicode/utrace.h>
+
+static int icu_stringprep_prep(lua_State *L, const UStringPrepProfile *profile)
+{
+ size_t input_len;
+ int32_t unprepped_len, prepped_len, output_len;
+ const char *input;
+ char output[1024];
+
+ UChar unprepped[1024]; /* Temporary unicode buffer (1024 characters) */
+ UChar prepped[1024];
+
+ UErrorCode err = U_ZERO_ERROR;
+
+ if(!lua_isstring(L, 1)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ input = lua_tolstring(L, 1, &input_len);
+ if (input_len >= 1024) {
+ lua_pushnil(L);
+ return 1;
+ }
+ u_strFromUTF8(unprepped, 1024, &unprepped_len, input, input_len, &err);
+ if (U_FAILURE(err)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ prepped_len = usprep_prepare(profile, unprepped, unprepped_len, prepped, 1024, 0, NULL, &err);
+ if (U_FAILURE(err)) {
+ lua_pushnil(L);
+ return 1;
+ } else {
+ u_strToUTF8(output, 1024, &output_len, prepped, prepped_len, &err);
+ if (U_SUCCESS(err) && output_len < 1024)
+ lua_pushlstring(L, output, output_len);
+ else
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+UStringPrepProfile *icu_nameprep;
+UStringPrepProfile *icu_nodeprep;
+UStringPrepProfile *icu_resourceprep;
+UStringPrepProfile *icu_saslprep;
+
+/* initialize global ICU stringprep profiles */
+void init_icu()
+{
+ UErrorCode err = U_ZERO_ERROR;
+ utrace_setLevel(UTRACE_VERBOSE);
+ icu_nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, &err);
+ icu_nodeprep = usprep_openByType(USPREP_RFC3920_NODEPREP, &err);
+ icu_resourceprep = usprep_openByType(USPREP_RFC3920_RESOURCEPREP, &err);
+ icu_saslprep = usprep_openByType(USPREP_RFC4013_SASLPREP, &err);
+ if (U_FAILURE(err)) fprintf(stderr, "[c] util.encodings: error: %s\n", u_errorName((UErrorCode)err));
+}
+
+#define MAKE_PREP_FUNC(myFunc, prep) \
+static int myFunc(lua_State *L) { return icu_stringprep_prep(L, prep); }
+
+MAKE_PREP_FUNC(Lstringprep_nameprep, icu_nameprep) /** stringprep.nameprep(s) */
+MAKE_PREP_FUNC(Lstringprep_nodeprep, icu_nodeprep) /** stringprep.nodeprep(s) */
+MAKE_PREP_FUNC(Lstringprep_resourceprep, icu_resourceprep) /** stringprep.resourceprep(s) */
+MAKE_PREP_FUNC(Lstringprep_saslprep, icu_saslprep) /** stringprep.saslprep(s) */
+
+static const luaL_Reg Reg_stringprep[] =
+{
+ { "nameprep", Lstringprep_nameprep },
+ { "nodeprep", Lstringprep_nodeprep },
+ { "resourceprep", Lstringprep_resourceprep },
+ { "saslprep", Lstringprep_saslprep },
+ { NULL, NULL }
+};
+#else /* USE_STRINGPREP_ICU */
+
+/****************** libidn ********************/
#include <stringprep.h>
static int stringprep_prep(lua_State *L, const Stringprep_profile *profile)
{
size_t len;
- const char *s = luaL_checklstring(L, 1, &len);
+ const char *s;
char string[1024];
int ret;
+ if(!lua_isstring(L, 1)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ s = lua_tolstring(L, 1, &len);
if (len >= 1024) {
lua_pushnil(L);
- return 1; // TODO return error message
+ return 1; /* TODO return error message */
}
strcpy(string, s);
- ret = stringprep(string, 1024, 0, profile);
+ ret = stringprep(string, 1024, (Stringprep_profile_flags)0, profile);
if (ret == STRINGPREP_OK) {
lua_pushstring(L, string);
return 1;
} else {
lua_pushnil(L);
- return 1; // TODO return error message
+ return 1; /* TODO return error message */
}
}
@@ -159,25 +244,93 @@ static const luaL_Reg Reg_stringprep[] =
{ "saslprep", Lstringprep_saslprep },
{ NULL, NULL }
};
+#endif
/***************** IDNA *****************/
+#ifdef USE_STRINGPREP_ICU
+#include <unicode/ustdio.h>
+#include <unicode/uidna.h>
+/* IDNA2003 or IDNA2008 ? ? ? */
+static int Lidna_to_ascii(lua_State *L) /** idna.to_ascii(s) */
+{
+ size_t len;
+ int32_t ulen, dest_len, output_len;
+ const char *s = luaL_checklstring(L, 1, &len);
+ UChar ustr[1024];
+ UErrorCode err = U_ZERO_ERROR;
+ UChar dest[1024];
+ char output[1024];
+
+ u_strFromUTF8(ustr, 1024, &ulen, s, len, &err);
+ if (U_FAILURE(err)) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ dest_len = uidna_IDNToASCII(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err);
+ if (U_FAILURE(err)) {
+ lua_pushnil(L);
+ return 1;
+ } else {
+ u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err);
+ if (U_SUCCESS(err) && output_len < 1024)
+ lua_pushlstring(L, output, output_len);
+ else
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */
+{
+ size_t len;
+ int32_t ulen, dest_len, output_len;
+ const char *s = luaL_checklstring(L, 1, &len);
+ UChar ustr[1024];
+ UErrorCode err = U_ZERO_ERROR;
+ UChar dest[1024];
+ char output[1024];
+
+ u_strFromUTF8(ustr, 1024, &ulen, s, len, &err);
+ if (U_FAILURE(err)) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ dest_len = uidna_IDNToUnicode(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err);
+ if (U_FAILURE(err)) {
+ lua_pushnil(L);
+ return 1;
+ } else {
+ u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err);
+ if (U_SUCCESS(err) && output_len < 1024)
+ lua_pushlstring(L, output, output_len);
+ else
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+#else /* USE_STRINGPREP_ICU */
+/****************** libidn ********************/
#include <idna.h>
+#include <idn-free.h>
static int Lidna_to_ascii(lua_State *L) /** idna.to_ascii(s) */
{
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
char* output = NULL;
- int ret = idna_to_ascii_8z(s, &output, 0);
+ int ret = idna_to_ascii_8z(s, &output, IDNA_USE_STD3_ASCII_RULES);
if (ret == IDNA_SUCCESS) {
lua_pushstring(L, output);
- if (output) free(output);
+ idn_free(output);
return 1;
} else {
lua_pushnil(L);
- if (output) free(output);
- return 1; // TODO return error message
+ idn_free(output);
+ return 1; /* TODO return error message */
}
}
@@ -189,14 +342,15 @@ static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */
int ret = idna_to_unicode_8z8z(s, &output, 0);
if (ret == IDNA_SUCCESS) {
lua_pushstring(L, output);
- if (output) free(output);
+ idn_free(output);
return 1;
} else {
lua_pushnil(L);
- if (output) free(output);
- return 1; // TODO return error message
+ idn_free(output);
+ return 1; /* TODO return error message */
}
}
+#endif
static const luaL_Reg Reg_idna[] =
{
@@ -214,6 +368,9 @@ static const luaL_Reg Reg[] =
LUALIB_API int luaopen_util_encodings(lua_State *L)
{
+#ifdef USE_STRINGPREP_ICU
+ init_icu();
+#endif
luaL_register(L, "encodings", Reg);
lua_pushliteral(L, "base64");