--- a/mcabber/configure.ac Sun Oct 25 01:15:31 2009 +0200
+++ b/mcabber/configure.ac Sun Oct 25 23:25:14 2009 +0100
@@ -152,6 +152,21 @@
AC_SUBST(LOUDMOUTH_CFLAGS)
AC_SUBST(LOUDMOUTH_LIBS)
+# Check for libidn
+AC_ARG_WITH(libidn, AC_HELP_STRING([--with-libidn=[DIR]],
+ [Support IDN (needs GNU Libidn)]),
+ libidn=$withval, libidn=yes)
+if test "$libidn" != "no" ; then
+ PKG_CHECK_MODULES(LIBIDN, libidn >= 0.0.0, [libidn=yes], [libidn=no])
+ if test "$libidn" != "yes" ; then
+ libidn=no
+ AC_MSG_WARN([Libidn not found])
+ else
+ libidn=yes
+ AC_DEFINE(HAVE_LIBIDN, 1, [Define to 1 if you want Libidn.])
+ fi
+fi
+
# Check for gpgme
AC_ARG_ENABLE(gpgme, AC_HELP_STRING([--disable-gpgme], [disable GPGME support]),
[ if test x"$enableval" = x"no"; then
--- a/mcabber/src/utils.c Sun Oct 25 01:15:31 2009 +0200
+++ b/mcabber/src/utils.c Sun Oct 25 23:25:14 2009 +0100
@@ -21,11 +21,20 @@
* USA
*/
+#include <config.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#ifdef HAVE_LIBIDN
+#include <idna.h>
+#include <stringprep.h>
+static char idnprep[1024];
+#endif
+
+#include <glib.h>
#include <glib/gprintf.h>
/* For Cygwin (thanks go to Yitzchak Scott-Thoennes) */
@@ -38,9 +47,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
-#include <glib.h>
-#include <config.h>
#include "utils.h"
#include "logprint.h"
@@ -402,6 +409,10 @@
const char *str;
const char *domain, *resource;
int domlen;
+#ifdef HAVE_LIBIDN
+ char *idnpp, *ascidnp;
+ int r;
+#endif
if (!fjid) return 1;
@@ -416,6 +427,28 @@
return 1;
domain++;
+#ifdef HAVE_LIBIDN
+ idnpp = idnprep;
+ str = fjid;
+ while (*str != JID_DOMAIN_SEPARATOR)
+ *idnpp++ = *str++;
+ *idnpp = 0;
+
+ r = stringprep(idnprep, 1023, 0, stringprep_xmpp_nodeprep);
+ if (r != STRINGPREP_OK || !idnprep[0])
+ return 1;
+
+ // check the string hasn't been modified, in which case we consider
+ // it's a failure (as fjid is read-only)
+ idnpp = idnprep;
+ str = fjid;
+ while (*idnpp) {
+ if (*idnpp++ != *str++)
+ return 1;
+ }
+ scr_LogPrint(LPRINT_LOGNORM, "Stringprep'd node: [%s]", idnprep); // XXX
+ /* the username looks okay */
+#else
/* check for low and invalid ascii characters in the username */
for (str = fjid; *str != JID_DOMAIN_SEPARATOR; str++) {
if (*str <= ' ' || *str == ':' || *str == JID_DOMAIN_SEPARATOR ||
@@ -425,6 +458,7 @@
}
}
/* the username is okay as far as we can tell without LIBIDN */
+#endif
}
resource = strchr(domain, JID_RESOURCE_SEPARATOR);
@@ -436,6 +470,12 @@
/* resources may not be longer than 1023 bytes */
if ((*resource == '\0') || strlen(resource) > 1023)
return 1;
+#ifdef HAVE_LIBIDN
+ strncpy(idnprep, resource, sizeof(idnprep));
+ r = stringprep(idnprep, 1023, 0, stringprep_xmpp_resourceprep);
+ if (r != STRINGPREP_OK || !idnprep[0])
+ return 1;
+#endif
} else {
domlen = strlen(domain);
}
@@ -446,13 +486,40 @@
/* and it must not be longer than 1023 bytes */
if (domlen > 1023) return 1;
+#ifdef HAVE_LIBIDN
+ idnpp = idnprep;
+ str = domain;
+ while (*str != '\0' && *str != JID_RESOURCE_SEPARATOR)
+ *idnpp++ = *str++;
+ *idnpp = 0;
+
+ r = stringprep_nameprep(idnprep, 1023);
+ if (r != STRINGPREP_OK || !idnprep[0])
+ return 1;
+
+ if (idna_to_ascii_8z(idnprep, &ascidnp, IDNA_USE_STD3_ASCII_RULES) !=
+ IDNA_SUCCESS)
+ return 1;
+ else
+ free(ascidnp);
+
+ // check the string hasn't been modified, in which case we consider
+ // it's a failure (as fjid is read-only)
+ idnpp = idnprep;
+ str = domain;
+ while (*idnpp) {
+ if (*idnpp++ != *str++)
+ return 1;
+ }
+#else
/* make sure the hostname is valid characters */
for (str = domain; *str != '\0' && *str != JID_RESOURCE_SEPARATOR; str++) {
if (!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_'))
return 1;
}
+#endif
- /* it's okay as far as we can tell without LIBIDN */
+ /* it's okay as far as we can tell */
return 0;
}