pidgin: edb54b59: Move the IDN support into the DNS routin...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Sun Jul 19 19:50:28 EDT 2009
-----------------------------------------------------------------
Revision: edb54b594e0ce2d7d9e63f52b22b5060df6bf8e8
Ancestor: 5a9bc2484cf71a19b7299f25f624cadd66341e7b
Author: darkrain42 at pidgin.im
Date: 2009-07-19T23:45:13
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/edb54b594e0ce2d7d9e63f52b22b5060df6bf8e8
Modified files:
ChangeLog ChangeLog.API libpurple/Makefile.am
libpurple/dnsquery.c libpurple/dnssrv.c libpurple/network.c
libpurple/network.h libpurple/protocols/jabber/jabber.c
libpurple/protocols/jabber/jutil.c
libpurple/protocols/jabber/jutil.h
ChangeLog:
Move the IDN support into the DNS routines.
This turned out to be cleaner than I first thought, so here we go.
All libpurple DNS routines support IDN when built against GNU libidn.
-------------- next part --------------
============================================================
--- ChangeLog 488513d5d5cbd9ed9991141e5ca772661138a12e
+++ ChangeLog 50d2f0cd8b6e7815ad8ad6e582a3efc8a43ef211
@@ -38,6 +38,8 @@ version 2.6.0 (??/??/2009):
* Better handling of corrupt certificates in the TLS Peers cache.
* More efficient purple_find_buddies() and purple_find_group() functions.
(Jan Kaluza and Aman Gupta)
+ * Internationalized Domain Names are supported when libpurple is compiled
+ against the GNU IDN library.
AIM and ICQ:
* Preliminary support for a new authentication scheme called
@@ -106,9 +108,8 @@ version 2.6.0 (??/??/2009):
* Removed support for obsoleted XEP-0022 (Message Events) and XEP-0091
(Legacy Entity Time).
* When the GNU IDN library (libidn) is available, it is used for
- normalization of Jabber IDs and support for internationalized domain
- names (IDNA). When unavailable, internal routines are used (as in
- previous versions) for normalization and IDNA is unavailable.
+ normalization of Jabber IDs. When unavailable, internal routines are
+ used (as in previous versions).
Yahoo!/Yahoo! JAPAN:
* P2P file transfers. (Sulabh Mahajan)
============================================================
--- ChangeLog.API 1dce09a26f44b3a5e82c94edd3268d201c6e5462
+++ ChangeLog.API 67b4d5fbb18237919c1678cde0b730511737978f
@@ -42,6 +42,7 @@ version 2.6.0 (??/??/2009):
* purple_log_get_activity_score
* purple_markup_is_rtl
* purple_markup_escape_text
+ * purple_network_convert_idn_to_ascii
* purple_network_force_online
* purple_network_set_stun_server
* purple_network_set_turn_server
@@ -83,6 +84,8 @@ version 2.6.0 (??/??/2009):
* purple_find_buddies is now more efficient in the case where
it is enumerating all the buddies for an account.
* purple_find_group is now more efficient for large numbers of groups.
+ * All DNS routines support internationalized domain names (IDNs) when
+ libpurple is compiled with GNU libidn.
Deprecated:
* buddy-added and buddy-removed blist signals
============================================================
--- libpurple/Makefile.am 110ecf025dac225f77512e246fea22507cd1f0ff
+++ libpurple/Makefile.am 211156598125ca2c4071bd2b8e70fda5572e4747
@@ -293,6 +293,7 @@ libpurple_la_LIBADD = \
$(FARSIGHT_LIBS) \
$(GSTREAMER_LIBS) \
$(GSTINTERFACES_LIBS) \
+ $(IDN_LIBS) \
-lm
AM_CPPFLAGS = \
@@ -308,6 +309,7 @@ AM_CPPFLAGS = \
$(FARSIGHT_CFLAGS) \
$(GSTREAMER_CFLAGS) \
$(GSTINTERFACES_CFLAGS) \
+ $(IDN_CFLAGS) \
$(NETWORKMANAGER_CFLAGS)
# INSTALL_SSL_CERTIFICATES is true when SSL_CERTIFICATES_DIR is empty.
============================================================
--- libpurple/dnsquery.c 8064f297839ca0007b2fb9cbebd1e5e8389d899e
+++ libpurple/dnsquery.c 485dbf82046fe5d16c260274432fa90cc23bb909
@@ -28,6 +28,7 @@
#include "internal.h"
#include "debug.h"
#include "dnsquery.h"
+#include "network.h"
#include "notify.h"
#include "prefs.h"
#include "util.h"
@@ -171,6 +172,18 @@ resolve_ip(PurpleDnsQueryData *query_dat
return FALSE;
}
+static gboolean
+dns_str_is_ascii(const char *name)
+{
+ guchar *c;
+ for (c = (guchar *)name; c && *c; ++c) {
+ if (*c > 0x7f)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
#if defined(PURPLE_DNSQUERY_USE_FORK)
/*
@@ -230,6 +243,7 @@ purple_dnsquery_resolver_run(int child_o
struct sockaddr_in sin;
const size_t addrlen = sizeof(sin);
#endif
+ char *hostname;
#ifdef HAVE_SIGNAL_H
purple_restore_default_signal_handlers();
@@ -274,6 +288,22 @@ purple_dnsquery_resolver_run(int child_o
_exit(1);
}
+#ifdef USE_IDN
+ if (!dns_str_is_ascii(dns_params.hostname)) {
+ rc = purple_network_convert_idn_to_ascii(dns_params.hostname, &hostname);
+ if (rc != 0) {
+ write_to_parent(child_out, &rc, sizeof(rc));
+ close(child_out);
+ if (show_debug)
+ fprintf(stderr, "dns[%d] Error: IDN conversion returned "
+ "%d\n", getpid(), rc);
+ dns_params.hostname[0] = '\0';
+ continue;
+ }
+ } else /* intentional to execute the g_strdup */
+#endif
+ hostname = g_strdup(dns_params.hostname);
+
/* We have the hostname and port, now resolve the IP */
#ifdef HAVE_GETADDRINFO
@@ -290,7 +320,7 @@ purple_dnsquery_resolver_run(int child_o
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif /* AI_ADDRCONFIG */
- rc = getaddrinfo(dns_params.hostname, servname, &hints, &res);
+ rc = getaddrinfo(hostname, servname, &hints, &res);
write_to_parent(child_out, &rc, sizeof(rc));
if (rc != 0) {
close(child_out);
@@ -309,9 +339,9 @@ purple_dnsquery_resolver_run(int child_o
}
freeaddrinfo(tmp);
#else
- if (!inet_aton(dns_params.hostname, &sin.sin_addr)) {
+ if (!inet_aton(hostname, &sin.sin_addr)) {
struct hostent *hp;
- if (!(hp = gethostbyname(dns_params.hostname))) {
+ if (!(hp = gethostbyname(hostname))) {
write_to_parent(child_out, &h_errno, sizeof(int));
close(child_out);
if (show_debug)
@@ -332,6 +362,9 @@ purple_dnsquery_resolver_run(int child_o
#endif
write_to_parent(child_out, &zero, sizeof(zero));
dns_params.hostname[0] = '\0';
+
+ g_free(hostname);
+ hostname = NULL;
}
close(child_out);
@@ -733,9 +766,27 @@ dns_thread(gpointer data)
struct sockaddr_in sin;
struct hostent *hp;
#endif
+ char *hostname;
query_data = data;
+#ifdef USE_IDN
+ if (!dns_str_is_ascii(dns_params.hostname)) {
+ rc = purple_network_convert_idn_to_ascii(dns_params.hostname, &hostname);
+ if (rc != 0) {
+ /* FIXME: Dirty 2.6.0 string freeze hack */
+ char tmp[8];
+ g_snprintf(tmp, sizeof(tmp), "%d", rc);
+ query_data->error_message = g_strdup_printf(_("Error resolving %s:\n%s"),
+ query_data->hostname, tmp);
+ /* back to main thread */
+ purple_timeout_add(0, dns_main_thread_cb, query_data);
+ return 0;
+ }
+ } else /* intentional fallthru */
+#endif
+ hostname = g_strdup(dns_params.hostname);
+
#ifdef HAVE_GETADDRINFO
g_snprintf(servname, sizeof(servname), "%d", query_data->port);
memset(&hints,0,sizeof(hints));
@@ -751,7 +802,7 @@ dns_thread(gpointer data)
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif /* AI_ADDRCONFIG */
- if ((rc = getaddrinfo(query_data->hostname, servname, &hints, &res)) == 0) {
+ if ((rc = getaddrinfo(hostname, servname, &hints, &res)) == 0) {
tmp = res;
while(res) {
query_data->hosts = g_slist_append(query_data->hosts,
@@ -765,7 +816,7 @@ dns_thread(gpointer data)
query_data->error_message = g_strdup_printf(_("Error resolving %s:\n%s"), query_data->hostname, purple_gai_strerror(rc));
}
#else
- if ((hp = gethostbyname(query_data->hostname))) {
+ if ((hp = gethostbyname(hostname))) {
memset(&sin, 0, sizeof(struct sockaddr_in));
memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
sin.sin_family = hp->h_addrtype;
@@ -779,6 +830,7 @@ dns_thread(gpointer data)
query_data->error_message = g_strdup_printf(_("Error resolving %s: %d"), query_data->hostname, h_errno);
}
#endif
+ g_free(hostname);
/* back to main thread */
purple_timeout_add(0, dns_main_thread_cb, query_data);
@@ -866,6 +918,7 @@ resolve_host(gpointer data)
PurpleDnsQueryData *query_data;
struct sockaddr_in sin;
GSList *hosts = NULL;
+ char *hostname;
query_data = data;
query_data->timeout = 0;
@@ -878,7 +931,22 @@ resolve_host(gpointer data)
if (!inet_aton(query_data->hostname, &sin.sin_addr)) {
struct hostent *hp;
- if(!(hp = gethostbyname(query_data->hostname))) {
+#ifdef USE_IDN
+ if (!dns_str_is_ascii(query_data->hostname)) {
+ int ret = purple_network_convert_idn_to_ascii(query_data->hostname,
+ &hostname);
+ if (ret != 0) {
+ char message[1024];
+ g_snprintf(message, sizeof(message), _("Error resolving %s: %d"),
+ query_data->hostname, ret);
+ purple_dnsquery_failed(query_data, message);
+ return FALSE;
+ }
+ } else /* fallthrough is intentional to the g_strdup */
+#endif
+ hostname = g_strdup(query_data->hostname);
+
+ if(!(hp = gethostbyname(hostname))) {
char message[1024];
g_snprintf(message, sizeof(message), _("Error resolving %s: %d"),
query_data->hostname, h_errno);
@@ -892,6 +960,7 @@ resolve_host(gpointer data)
sin.sin_family = AF_INET;
sin.sin_port = htons(query_data->port);
+ g_free(hostname);
hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin)));
hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin)));
============================================================
--- libpurple/dnssrv.c 2d426a2bf5916bba7e3c944b8b83b8e80053fa47
+++ libpurple/dnssrv.c d273768620eac040e9406a8fd3290b8ca0db6fc6
@@ -47,9 +47,10 @@
#endif
#endif
+#include "debug.h"
#include "dnssrv.h"
#include "eventloop.h"
-#include "debug.h"
+#include "network.h"
#ifndef _WIN32
typedef union {
@@ -247,6 +248,18 @@ purple_srv_sort(GList *list)
return list;
}
+static gboolean
+dns_str_is_ascii(const char *name)
+{
+ guchar *c;
+ for (c = (guchar *)name; c && *c; ++c) {
+ if (*c > 0x7f)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
#ifndef _WIN32
G_GNUC_NORETURN static void
@@ -588,6 +601,7 @@ purple_srv_resolve(const char *protocol,
purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata)
{
char *query;
+ char *hostname;
PurpleSrvQueryData *query_data;
#ifndef _WIN32
PurpleSrvInternalQuery internal_query;
@@ -604,9 +618,23 @@ purple_srv_resolve(const char *protocol,
g_return_val_if_reached(NULL);
}
- query = g_strdup_printf("_%s._%s.%s", protocol, transport, domain);
- purple_debug_info("dnssrv","querying SRV record for %s\n", query);
+#ifdef USE_IDN
+ if (!dns_str_is_ascii(domain)) {
+ int ret = purple_network_convert_idn_to_ascii(domain, &hostname);
+ if (ret != 0) {
+ purple_debug_error("dnssrv", "IDNA ToASCII failed\n");
+ cb(NULL, 0, extradata);
+ return NULL;
+ }
+ } else /* Fallthru is intentional */
+#endif
+ hostname = g_strdup(domain);
+ query = g_strdup_printf("_%s._%s.%s", protocol, transport, hostname);
+ purple_debug_info("dnssrv","querying SRV record for %s: %s\n", domain,
+ query);
+ g_free(hostname);
+
#ifndef _WIN32
if(pipe(in) || pipe(out)) {
purple_debug_error("dnssrv", "Could not create pipe\n");
@@ -692,6 +720,7 @@ PurpleSrvQueryData *purple_txt_resolve(c
PurpleSrvQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata)
{
char *query;
+ char *hostname;
PurpleSrvQueryData *query_data;
#ifndef _WIN32
PurpleSrvInternalQuery internal_query;
@@ -702,9 +731,23 @@ PurpleSrvQueryData *purple_txt_resolve(c
static gboolean initialized = FALSE;
#endif
- query = g_strdup_printf("%s.%s", owner, domain);
- purple_debug_info("dnssrv","querying TXT record for %s\n", query);
+#ifdef USE_IDN
+ if (!dns_str_is_ascii(domain)) {
+ int ret = purple_network_convert_idn_to_ascii(domain, &hostname);
+ if (ret != 0) {
+ purple_debug_error("dnssrv", "IDNA ToASCII failed\n");
+ cb(NULL, extradata);
+ return NULL;
+ }
+ } else /* fallthru is intentional */
+#endif
+ hostname = g_strdup(domain);
+ query = g_strdup_printf("%s.%s", owner, hostname);
+ purple_debug_info("dnssrv","querying TXT record for %s: %s\n", domain,
+ query);
+ g_free(hostname);
+
#ifndef _WIN32
if(pipe(in) || pipe(out)) {
purple_debug_error("dnssrv", "Could not create pipe\n");
============================================================
--- libpurple/network.c 9ecaecb9542db2ca146d8c5c7ba0fd6d03eb27b5
+++ libpurple/network.c 14ce71dc03dff47e6c4a2d6efc9642c4299eeb13
@@ -50,6 +50,10 @@
#include "upnp.h"
#include "dnsquery.h"
+#ifdef USE_IDN
+#include <idna.h>
+#endif
+
/*
* Calling sizeof(struct ifreq) isn't always correct on
* Mac OS X (and maybe others).
@@ -966,7 +970,33 @@ purple_network_remove_port_mapping(gint
}
}
}
-
+
+int purple_network_convert_idn_to_ascii(const gchar *in, gchar **out)
+{
+#ifdef USE_IDN
+ char *tmp;
+ int ret;
+
+ g_return_val_if_fail(out != NULL, -1);
+
+ ret = idna_to_ascii_8z(in, &tmp, IDNA_USE_STD3_ASCII_RULES);
+ if (ret != IDNA_SUCCESS) {
+ *out = NULL;
+ return ret;
+ }
+
+ *out = g_strdup(tmp);
+ /* This *MUST* be freed with free, not g_free */
+ free(tmp);
+ return 0;
+#else
+ g_return_val_if_fail(out != NULL, -1);
+
+ *out = g_strdup(in);
+ return 0;
+#endif
+}
+
void
purple_network_init(void)
{
============================================================
--- libpurple/network.h 66b3f6b9692af5951613d849e5347841bfd72ea3
+++ libpurple/network.h 6f562422909bac377b6448a1214c7ae9757c2a59
@@ -268,6 +268,25 @@ void purple_network_remove_port_mapping(
void purple_network_remove_port_mapping(gint fd);
/**
+ * Convert a UTF-8 domain name to ASCII in accordance with the IDNA
+ * specification. If libpurple is compiled without IDN support, this function
+ * copies the input into the output buffer.
+ *
+ * Because this function is used by DNS resolver child/threads, it uses no
+ * other libpurple API and is threadsafe.
+ *
+ * In general, a buffer of about 512 bytes is the appropriate size to use.
+ *
+ * @param in The hostname to be converted.
+ * @param out The output buffer where an allocated string will be returned.
+ * The caller is responsible for freeing this.
+ * @returns 0 on success, -1 if the out is NULL, or an error code
+ * that currently corresponds to the Idna_rc enum in libidn.
+ * @since 2.6.0
+ */
+int purple_network_convert_idn_to_ascii(const gchar *in, gchar **out);
+
+/**
* Initializes the network subsystem.
*/
void purple_network_init(void);
============================================================
--- libpurple/protocols/jabber/jabber.c 064736e1e67a91377d696f8fc4e4b12a748239ec
+++ libpurple/protocols/jabber/jabber.c c208d2e9faf039ac3e9b861563bf6802ac4036e6
@@ -657,11 +657,9 @@ jabber_login_callback(gpointer data, gin
purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record.\n", error);
try_srv_connect(js);
} else {
- char *ascii_domain = jabber_try_idna_to_ascii(js->user->domain);
purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
js->srv_query_data = purple_txt_resolve("_xmppconnect",
- ascii_domain, txt_resolved_cb, js);
- g_free(ascii_domain);
+ js->user->domain, txt_resolved_cb, js);
}
return;
}
@@ -704,17 +702,14 @@ static gboolean jabber_login_connect(Jab
}
static gboolean jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port,
- gboolean fatal_failure, gboolean use_domain)
+ gboolean fatal_failure)
{
/* host should be used in preference to domain to
* allow SASL authentication to work with FQDN of the server,
* but we use domain as fallback for when users enter IP address
- * in connect server.
- * We also want to use the domain if the hostname is the result of the
- * IDNA ToASCII operation.
- */
+ * in connect server */
g_free(js->serverFQDN);
- if (use_domain || purple_ip_address_is_valid(host))
+ if (purple_ip_address_is_valid(host))
js->serverFQDN = g_strdup(domain);
else
js->serverFQDN = g_strdup(host);
@@ -735,23 +730,19 @@ static void try_srv_connect(JabberStream
static void try_srv_connect(JabberStream *js)
{
- char *ascii_domain;
-
while (js->srv_rec != NULL && js->srv_rec_idx < js->max_srv_rec_idx) {
PurpleSrvResponse *tmp_resp = js->srv_rec + (js->srv_rec_idx++);
- if (jabber_login_connect(js, tmp_resp->hostname, tmp_resp->hostname, tmp_resp->port, FALSE, FALSE))
+ if (jabber_login_connect(js, tmp_resp->hostname, tmp_resp->hostname, tmp_resp->port, FALSE))
return;
}
g_free(js->srv_rec);
js->srv_rec = NULL;
- ascii_domain = jabber_try_idna_to_ascii(js->user->domain);
/* Fall back to the defaults (I'm not sure if we should actually do this) */
- jabber_login_connect(js, js->user->domain, ascii_domain,
+ jabber_login_connect(js, js->user->domain, js->user->domain,
purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
- TRUE, TRUE);
- g_free(ascii_domain);
+ TRUE);
}
static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data)
@@ -765,11 +756,9 @@ static void srv_resolved_cb(PurpleSrvRes
js->max_srv_rec_idx = results;
try_srv_connect(js);
} else {
- char *ascii_domain = jabber_try_idna_to_ascii(js->user->domain);
- jabber_login_connect(js, js->user->domain, ascii_domain,
+ jabber_login_connect(js, js->user->domain, js->user->domain,
purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
- TRUE, TRUE);
- g_free(ascii_domain);
+ TRUE);
}
}
@@ -860,7 +849,6 @@ jabber_stream_connect(JabberStream *js)
"connect_server", "");
const char *bosh_url = purple_account_get_string(account,
"bosh_url", "");
- char *ascii_domain;
jabber_stream_set_state(js, JABBER_STREAM_CONNECTING);
@@ -883,22 +871,12 @@ jabber_stream_connect(JabberStream *js)
js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
- ascii_domain = jabber_try_idna_to_ascii(js->certificate_CN);
- if (ascii_domain == NULL) {
- purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
- _("Invalid XMPP ID"));
- return;
- }
-
/* if they've got old-ssl mode going, we probably want to ignore SRV lookups */
if(purple_account_get_bool(account, "old_ssl", FALSE)) {
if(purple_ssl_is_supported()) {
- js->gsc = purple_ssl_connect_with_ssl_cn(account, ascii_domain,
+ js->gsc = purple_ssl_connect(account, js->certificate_CN,
purple_account_get_int(account, "port", 5223),
- jabber_login_callback_ssl, jabber_ssl_connect_failure,
- js->certificate_CN, gc);
- g_free(ascii_domain);
+ jabber_login_callback_ssl, jabber_ssl_connect_failure, gc);
if (!js->gsc) {
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
@@ -910,22 +888,18 @@ jabber_stream_connect(JabberStream *js)
_("SSL support unavailable"));
}
- g_free(ascii_domain);
return;
}
/* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll
* invoke the magic of SRV lookups, to figure out host and port */
if(connect_server[0]) {
- jabber_login_connect(js, js->user->domain, ascii_domain,
- purple_account_get_int(account, "port", 5222),
- TRUE, TRUE);
+ jabber_login_connect(js, js->user->domain, connect_server,
+ purple_account_get_int(account, "port", 5222), TRUE);
} else {
js->srv_query_data = purple_srv_resolve("xmpp-client",
- "tcp", ascii_domain, srv_resolved_cb, js);
+ "tcp", js->user->domain, srv_resolved_cb, js);
}
-
- g_free(ascii_domain);
}
void
============================================================
--- libpurple/protocols/jabber/jutil.c 749c1ad0819205e3e00a327ad7ad273cb4d71175
+++ libpurple/protocols/jabber/jutil.c bb6d561242630872379893b807e4304ce1e3777d
@@ -37,28 +37,6 @@ static char idn_buffer[1024];
static char idn_buffer[1024];
#endif
-gchar *jabber_try_idna_to_ascii(const char *input)
-{
-#ifndef USE_IDN
- return g_strdup(input);
-#else
- gchar *out;
- char *tmp;
-
- g_return_val_if_fail(input != NULL, NULL);
- g_return_val_if_fail(*input != '\0', NULL);
-
- if (idna_to_ascii_8z(input, &tmp, IDNA_USE_STD3_ASCII_RULES) != IDNA_SUCCESS) {
- return NULL;
- }
-
- out = g_strdup(tmp);
- /* This *MUST* be freed with free, not g_free */
- free(tmp);
- return out;
-#endif
-}
-
#ifdef USE_IDN
static gboolean jabber_nodeprep(char *str, size_t buflen)
{
============================================================
--- libpurple/protocols/jabber/jutil.h 6b4b14dcde04b3d98a9b29b465eb5293655721e6
+++ libpurple/protocols/jabber/jutil.h b646920f1c7d9a9d20ec8c613ab269a337584f5f
@@ -44,11 +44,6 @@ gboolean jabber_is_own_account(JabberStr
/* Returns true if JID is the bare JID of our account. */
gboolean jabber_is_own_account(JabberStream *js, const char *jid);
-/* Try to convert an IDNA domain name to something we can pass to a DNS lookup.
- * If IDN support is not available, returns a copy of the input string.
- */
-gchar *jabber_try_idna_to_ascii(const gchar *input);
-
gboolean jabber_nodeprep_validate(const char *);
gboolean jabber_domain_validate(const char *);
gboolean jabber_resourceprep_validate(const char *);
More information about the Commits
mailing list