Hi All, Attached the IDn patch for Evolution Head. Hoping comments on this soon. See the attached files, README.idn explains what is this all about. Thanks, SureshHi All,
Attachment:
idnkit-1-0.i386.rpm
Description: idnkit-1-0.i386.rpm
Index: ChangeLog =================================================================== RCS file: /cvs/gnome/evolution/ChangeLog,v retrieving revision 1.1273 diff -u -r1.1273 ChangeLog --- ChangeLog 8 Dec 2003 01:46:03 -0000 1.1273 +++ ChangeLog 18 Dec 2003 20:39:04 -0000 @@ -1,3 +1,8 @@ +2003-12-15 Suresh Chandrasekharan <suresh chandrasekharan sun com> + + * configure.in: Changes to test for idnkit library. Added + for International Domain Names support. + 2003-12-07 JP Rosevear <jpr ximian com> * configure.in: update version reliance Index: configure.in =================================================================== RCS file: /cvs/gnome/evolution/configure.in,v retrieving revision 1.634 diff -u -r1.634 configure.in --- configure.in 8 Dec 2003 01:46:03 -0000 1.634 +++ configure.in 18 Dec 2003 20:39:05 -0000 @@ -314,6 +314,43 @@ dnl ************************************************** +dnl * idnkit support +dnl ************************************************** +AC_ARG_ENABLE(idn, [ --enable-idn=[no/yes] Enable support for supporting International Domain Names.],,enable_idn=no) +if test "x$enable_idn" = "xyes"; then +AC_CACHE_CHECK([if system has a working idnkit library installed], msg_idn, +[ + AC_TRY_COMPILE([ + #include "confdefs.h" + #include <sys/types.h> + #include <idn/api.h> + ],[ + const char *utf8 = "\xC2\xA9"; + idn_result_t r; + char ace_name[20]; + char changed_name[20]; + r = idn_encodename (IDN_DELIMMAP | IDN_LOCALMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_LENCHECK | IDN_ASCCHECK, utf8, ace_name, sizeof (ace_name)); + if (r != idn_success) + exit (1); + r = idn_decodename(IDN_DELIMMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK, ace_name, changed_name, sizeof (changed_name)); + if (r != idn_success) + exit (1); + ],[ + msg_idn=yes + ],[ + enable_idn=no + msg_idn=no + ]) +]) +else + msg_idn=no +fi +if test "x$enable_idn" = "xyes"; then + AC_DEFINE(ENABLE_IDN, 1, [Enable IDN support]) +fi + + +dnl ************************************************** dnl LDAP support. dnl ************************************************** EVO_LDAP_CHECK(no) @@ -1016,7 +1053,13 @@ AC_SUBST(E_NAME_CFLAGS) AC_SUBST(E_NAME_LIBS) -EVO_SET_COMPILE_FLAGS(E_UTIL, gthread-2.0 gconf-2.0 libxml-2.0 libbonoboui-2.0 libglade-2.0 gal-2.2 >= $GAL_REQUIRED libgnomeui-2.0 libgnome-2.0 libgnomecanvas-2.0 $mozilla_nspr, $THREADS_CFLAGS $MANUAL_NSPR_CFLAGS, $THREADS_LIBS $MANUAL_NSPR_LIBS) +E_UTILS_DEP=" gthread-2.0 gconf-2.0 libxml-2.0 libbonoboui-2.0 libglade-2.0 gal-2.2 >= $GAL_REQUIRED libgnomeui-2.0 libgnome-2.0 libgnomecanvas-2.0 $mozilla_nspr" + +if test "x$enable_idn" = "xyes"; then + E_UTILS_DEP="idnkit $E_UTILS_DEP" +fi + +EVO_SET_COMPILE_FLAGS(E_UTIL, $E_UTILS_DEP, $THREADS_CFLAGS $MANUAL_NSPR_CFLAGS, $THREADS_LIBS $MANUAL_NSPR_LIBS) AC_SUBST(E_UTIL_CFLAGS) AC_SUBST(E_UTIL_LIBS) @@ -1367,6 +1410,7 @@ SSL support: $msg_ssl SMIME support: $msg_smime IPv6 support: $msg_ipv6 + IDN support: $msg_idn Dot Locking: $msg_dot File Locking: $msg_file Gtk-doc: $enable_gtk_doc" Index: addressbook/ChangeLog =================================================================== RCS file: /cvs/gnome/evolution/addressbook/ChangeLog,v retrieving revision 1.1500 diff -u -r1.1500 ChangeLog --- addressbook/ChangeLog 11 Dec 2003 02:52:34 -0000 1.1500 +++ addressbook/ChangeLog 18 Dec 2003 20:39:05 -0000 @@ -1,3 +1,27 @@ +2003-12-15 Suresh Chandrasekharan <suresh chandrasekharan sun com> + + * gui/contact-editor/e-contact-editor.c: + + (fill_in_field) Convert the URL to be displayed in the contact editor + from ASCII Compatible Encoding (ACE) to UTF-8 encoding. + + (extract_field) When setting the contact book entry use ACE encoding. + + * gui/widgets/eab-contact-display.c: + (on_link_clicked) Call e_uri_gnome_show_idn_url to show convert + non-ASCII url to ACE and show it. + + (render_url) Convert the ACE encoded URL for UTF-8 url for display + in addressbook contact display. + + * gui/component/addressbook-config.c: + + (dialog_to_source) Convert the LDAP server name to ACE before + saving. + + (folder_page_prepare) Convert the LDAP server name to UTF-8 before + displaying. + 2003-12-10 Hans Petter Jansson <hpj ximian com> * gui/contact-editor/e-contact-editor-address.c Index: addressbook/gui/component/addressbook-config.c =================================================================== RCS file: /cvs/gnome/evolution/addressbook/gui/component/addressbook-config.c,v retrieving revision 1.62 diff -u -r1.62 addressbook-config.c --- addressbook/gui/component/addressbook-config.c 3 Dec 2003 15:38:32 -0000 1.62 +++ addressbook/gui/component/addressbook-config.c 18 Dec 2003 20:39:05 -0000 @@ -25,6 +25,10 @@ #include <glade/glade.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "addressbook.h" #include "addressbook-component.h" #include "addressbook-config.h" @@ -259,6 +263,12 @@ if (!strcmp ("ldap://", e_source_group_peek_base_uri (dialog->source_group))) { #ifdef HAVE_LDAP + +#ifdef ENABLE_IDN + char *t = NULL; + if (dialog && dialog->host) + t = e_uri_encode_host (gtk_entry_get_text (GTK_ENTRY (dialog->host))); +#endif e_source_set_property (source, "email_addr", gtk_entry_get_text (GTK_ENTRY (dialog->email))); e_source_set_property (source, "binddn", gtk_entry_get_text (GTK_ENTRY (dialog->binddn))); e_source_set_property (source, "limit", gtk_entry_get_text (GTK_ENTRY (dialog->limit_spinbutton))); @@ -266,12 +276,20 @@ e_source_set_property (source, "auth", ldap_unparse_auth (dialog->auth)); str = g_strdup_printf ("%s:%s/%s?" /* trigraph prevention */ "?%s", +#ifdef ENABLE_IDN + t, +#else gtk_entry_get_text (GTK_ENTRY (dialog->host)), +#endif gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (dialog->port_combo)->entry)), gtk_entry_get_text (GTK_ENTRY (dialog->rootdn)), ldap_unparse_scope (dialog->scope)); e_source_set_relative_uri (source, str); g_free (str); +#ifdef ENABLE_IDN + if (t) g_free (t); +#endif + #endif } else { const gchar *relative_uri; @@ -957,7 +975,13 @@ { if (!dialog->display_name_changed) { const char *server_name = gtk_entry_get_text (GTK_ENTRY (dialog->host)); +#ifdef ENABLE_IDN + char *t = e_uri_decode_host ((char*)server_name); + gtk_entry_set_text (GTK_ENTRY (dialog->display_name), t ? t : ""); + if (t) g_free (t); +#else gtk_entry_set_text (GTK_ENTRY (dialog->display_name), server_name); +#endif } gnome_druid_set_buttons_sensitive (GNOME_DRUID(dialog->druid), Index: addressbook/gui/contact-editor/e-contact-editor.c =================================================================== RCS file: /cvs/gnome/evolution/addressbook/gui/contact-editor/e-contact-editor.c,v retrieving revision 1.153 diff -u -r1.153 e-contact-editor.c --- addressbook/gui/contact-editor/e-contact-editor.c 21 Oct 2003 18:48:45 -0000 1.153 +++ addressbook/gui/contact-editor/e-contact-editor.c 18 Dec 2003 20:39:05 -0000 @@ -47,6 +47,10 @@ #include <e-util/e-categories-master-list-wombat.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "addressbook/printing/e-contact-print.h" #include "addressbook/printing/e-contact-print-envelope.h" #include "addressbook/gui/widgets/eab-gui-util.h" @@ -2072,13 +2076,23 @@ static void fill_in_field(EContactEditor *editor, char *id, char *value) { +#ifdef ENABLE_IDN + char *t = NULL; +#endif GtkWidget *widget = glade_xml_get_widget(editor->gui, id); if (!widget) return; - if (E_IS_URL_ENTRY (widget)) + if (E_IS_URL_ENTRY (widget)) { widget = e_url_entry_get_entry (E_URL_ENTRY (widget)); +#ifdef ENABLE_IDN + if (value) { + t = strdup (value); + e_uri_replace_with_decd_host (&t); + } +#endif + } if (GTK_IS_TEXT_VIEW (widget)) { if (value) @@ -2089,8 +2103,17 @@ int position = 0; GtkEditable *editable = GTK_EDITABLE(widget); gtk_editable_delete_text(editable, 0, -1); - if (value) +#ifdef ENABLE_IDN + if (t) { + gtk_editable_insert_text(editable, t, strlen(t), &position); + g_free (t); + } else if (value) { + gtk_editable_insert_text(editable, value, strlen(value), &position); + } +#else + if (value) gtk_editable_insert_text(editable, value, strlen(value), &position); +#endif } } @@ -2418,14 +2441,21 @@ static void extract_field(EContactEditor *editor, EContact *contact, char *editable_id, EContactField field) { +#ifdef ENABLE_IDN + gboolean is_url = FALSE; +#endif GtkWidget *widget = glade_xml_get_widget(editor->gui, editable_id); char *string = NULL; if (!widget) return; - if (E_IS_URL_ENTRY (widget)) + if (E_IS_URL_ENTRY (widget)) { +#ifdef ENABLE_IDN + is_url = TRUE; +#endif widget = e_url_entry_get_entry (E_URL_ENTRY (widget)); + } if (GTK_IS_EDITABLE (widget)) string = gtk_editable_get_chars(GTK_EDITABLE (widget), 0, -1); @@ -2440,10 +2470,15 @@ string = gtk_text_buffer_get_text (buffer, &start, &end, TRUE); } - if (string && *string) + if (string && *string) { +#ifdef ENABLE_IDN + if (is_url) + e_uri_replace_with_encd_host (&string); +#endif e_contact_set (contact, field, string); - else + } else { e_contact_set (contact, field, NULL); + } if (string) g_free(string); } Index: addressbook/gui/widgets/eab-contact-display.c =================================================================== RCS file: /cvs/gnome/evolution/addressbook/gui/widgets/eab-contact-display.c,v retrieving revision 1.2 diff -u -r1.2 eab-contact-display.c --- addressbook/gui/widgets/eab-contact-display.c 21 Oct 2003 18:48:56 -0000 1.2 +++ addressbook/gui/widgets/eab-contact-display.c 18 Dec 2003 20:39:05 -0000 @@ -20,11 +20,16 @@ * */ +#include <config.h> #include "eab-contact-display.h" #include "e-util/e-html-utils.h" #include "util/eab-destination.h" +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include <string.h> #include <libgnome/gnome-i18n.h> #include <libgnome/gnome-url.h> @@ -68,8 +73,12 @@ on_link_clicked (GtkHTML *html, const char *url, EABContactDisplay *display) { GError *err = NULL; - - gnome_url_show (url, &err); + +#ifdef ENABLE_IDN + e_uri_gnome_show_idn_url (url, &err); +#else + gnome_url_show (url, &err); +#endif if (err) { g_warning ("gnome_url_show: %s", err->message); @@ -138,7 +147,14 @@ const char *str; str = e_contact_get_const (contact, field); if (str && *str) { +#ifdef ENABLE_IDN + char *t = strdup (str); + e_uri_replace_with_decd_host (&t); + char *html = e_text_to_html (t, E_TEXT_TO_HTML_CONVERT_URLS); + g_free (t); +#else char *html = e_text_to_html (str, E_TEXT_TO_HTML_CONVERT_URLS); +#endif gtk_html_stream_printf (html_stream, "<b>%s:</b> %s<br>", html_label, html); g_free (html); Index: calendar/gui/dialogs/task-details-page.c =================================================================== RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/task-details-page.c,v retrieving revision 1.37 diff -u -r1.37 task-details-page.c --- calendar/gui/dialogs/task-details-page.c 20 Nov 2003 15:11:40 -0000 1.37 +++ calendar/gui/dialogs/task-details-page.c 18 Dec 2003 20:39:06 -0000 @@ -32,6 +32,9 @@ #include <widgets/misc/e-dateedit.h> #include <widgets/misc/e-url-entry.h> #include "e-util/e-dialog-widgets.h" +#ifdef ENABLE_IDN +#include "e-util/e-url.h" +#endif #include "../calendar-config.h" #include "../e-timezone-entry.h" #include "comp-editor-util.h" @@ -359,7 +362,17 @@ /* URL */ e_cal_component_get_url (comp, &url); +#ifdef ENABLE_IDN + do { + char *t = g_strdup (url); + e_uri_replace_with_decd_host (&t); + e_dialog_editable_set (priv->url, t); + g_free (t); + } while (0); + +#else e_dialog_editable_set (priv->url, url); +#endif priv->updating = FALSE; } Index: camel/ChangeLog =================================================================== RCS file: /cvs/gnome/evolution/camel/ChangeLog,v retrieving revision 1.1944 diff -u -r1.1944 ChangeLog --- camel/ChangeLog 11 Dec 2003 17:30:29 -0000 1.1944 +++ camel/ChangeLog 18 Dec 2003 20:39:06 -0000 @@ -1,3 +1,49 @@ +2003-12-15 Suresh Chandrasekharan <suresh chandrasekharan sun com> + + * International Domain Names (IDN) support for Evolution. + + * camel-url-scanner.c: (camel_url_web_end) The end of valid + hostname seach is modified to include non-ASCII. + + (is_idn_domain) New function added to determine whether a + non-ASCII hostname is valid. + + * camel-url.h: utf8_host is added to CamelURL. + + * camel-url.c: (camel_url_new_with_base) Coroesponding to each + host_name, store a utf8 hostname too. This will help save calls + to idn functions when the utf8_host is required repeatedly for a + utf8_host. Call to camel_url_decode is not made because + e_uri_decode_host will inturn call that. + + (camel_url_copy) Added utf8_host. + + * providers/imap/camel-imap-store.c: (imap_get_name) Show utf8 + hostname in user messages. + + (connect_to_server) Same as above + + (imap_auth_loop) Show utf8 hostname when asking for password. + + * providers/nntp/camel-nntp-store.c: (connect_to_server) Show utf8 + hostname in erro messages. + + (nntp_store_get_name) Show utf8 hostname in user messages. + + * providers/pop3/camel-pop3-store.c: (connect_to_server): Show utf8 + hostname in error messages. + + (query_auth_types) Same + + (pop3_try_authenticate) Show utf8 hostname when asking for password. + + * providers/smtp/camel-smtp-transport.c: (connect_to_server) utf8 + hostname in error messages when not able to connect. + + (smtp_connect) Same + + (get_name) utf8 name in status display. + 2003-12-11 Jeffrey Stedfast <fejj ximian com> * camel-gpg-context.c (gpg_ctx_parse_status): Don't immediately Index: camel/camel-http-stream.c =================================================================== RCS file: /cvs/gnome/evolution/camel/camel-http-stream.c,v retrieving revision 1.16 diff -u -r1.16 camel-http-stream.c --- camel/camel-http-stream.c 23 Oct 2003 19:57:58 -0000 1.16 +++ camel/camel-http-stream.c 18 Dec 2003 20:39:06 -0000 @@ -31,6 +31,10 @@ #include <ctype.h> #include <errno.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "camel-http-stream.h" #include "camel-mime-utils.h" @@ -43,6 +47,7 @@ #include "camel-session.h" #include "camel-service.h" /* for hostname stuff */ + #define d(x) x @@ -361,12 +366,16 @@ method, http->proxy ? url : http->url->path, http->user_agent ? http->user_agent : "CamelHttpStream/1.0", - http->url->host)); + e_uri_encode_host (http->url->host))); if (camel_stream_printf (http->raw, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n", method, http->proxy ? url : http->url->path, http->user_agent ? http->user_agent : "CamelHttpStream/1.0", +#ifdef ENABLE_IDN + e_uri_encode_host (http->url->host)) == -1) { +#else http->url->host) == -1) { +#endif http_disconnect(http); g_free (url); return -1; Index: camel/camel-url-scanner.c =================================================================== RCS file: /cvs/gnome/evolution/camel/camel-url-scanner.c,v retrieving revision 1.6 diff -u -r1.6 camel-url-scanner.c --- camel/camel-url-scanner.c 17 Apr 2003 16:43:06 -0000 1.6 +++ camel/camel-url-scanner.c 18 Dec 2003 20:39:06 -0000 @@ -27,6 +27,10 @@ #include <string.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "e-util/e-trie.h" #include "camel-url-scanner.h" @@ -36,6 +40,9 @@ ETrie *trie; }; +#ifdef ENABLE_IDN +static gboolean is_idn_domain ( const char **inptr, const char *inend) ; +#endif CamelUrlScanner * camel_url_scanner_new (void) @@ -209,10 +216,8 @@ inptr++; else break; - while (inptr < inend && is_domain (*inptr)) inptr++; - if (inptr < inend && *inptr == '.' && is_domain (inptr[1])) inptr++; } @@ -236,6 +241,7 @@ { '<', '>' }, }; + static char url_stop_at_brace (const char *in, size_t so) { @@ -251,6 +257,41 @@ return '\0'; } +#ifdef ENABLE_IDN +static gboolean +is_idn_domain ( const char **inptr, const char *inend) { + char *t; + char inbuf[16]; + gint len = 0; + +#if 0 + if (**inptr < 128) { + if (is_domain (**inptr)) { + *inptr++; + return TRUE; + } else + return FALSE; + } +#endif + + memset (inbuf, 0, sizeof (inbuf)); + g_utf8_strncpy (inbuf, *inptr, 1); + t = e_uri_encode_host (inbuf); + if (t) { + g_free (t); + len = strlen (inbuf); + if (*inptr + len <= inend ) { + *inptr += len; + return TRUE; + } + } else if (is_domain (**inptr)) { + *inptr += 1; + return TRUE; + } + return FALSE; +} +#endif + gboolean camel_url_file_start (const char *in, const char *pos, const char *inend, urlmatch_t *match) { @@ -294,7 +335,7 @@ gboolean camel_url_web_end (const char *in, const char *pos, const char *inend, urlmatch_t *match) { - register const char *inptr = pos; + const char *inptr = pos; int parts = 0, digits, port; char close_brace; @@ -320,18 +361,28 @@ inptr++; } while (parts < 4); +#ifdef ENABLE_IDN + } else if (is_idn_domain (&inptr, inend)) { +#else } else if (is_domain (*inptr)) { - while (inptr < inend) { +#endif + while (inptr < inend) { +#ifdef ENABLE_IDN + if (!is_idn_domain (&inptr, inend)) + break; + while (inptr < inend && is_idn_domain (&inptr, inend)); + if (inptr < inend && *inptr == '.' ) + is_idn_domain (&(inptr)+1, inend); +#else if (is_domain (*inptr)) inptr++; else break; - while (inptr < inend && is_domain (*inptr)) inptr++; - if (inptr < inend && *inptr == '.' && is_domain (inptr[1])) inptr++; +#endif } } else { return FALSE; Index: camel/camel-url.c =================================================================== RCS file: /cvs/gnome/evolution/camel/camel-url.c,v retrieving revision 1.38 diff -u -r1.38 camel-url.c --- camel/camel-url.c 9 Dec 2003 00:58:40 -0000 1.38 +++ camel/camel-url.c 18 Dec 2003 20:39:06 -0000 @@ -32,6 +32,10 @@ #include <stdlib.h> #include <string.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "camel-url.h" #include "camel-exception.h" #include "camel-mime-utils.h" @@ -126,10 +130,17 @@ colon = strchr (url_string, ':'); if (colon && colon < slash) { url->host = g_strndup (url_string, colon - url_string); +#ifdef ENABLE_IDN + url->utf8_host = e_uri_decode_host (url->host); +#endif url->port = strtoul (colon + 1, NULL, 10); } else { url->host = g_strndup (url_string, slash - url_string); - camel_url_decode (url->host); +#ifdef ENABLE_IDN + url->utf8_host = e_uri_decode_host (url->host); +#else /* Don't need decoding for utf8_host */ + camel_url_decode (url->host); +#endif url->port = 0; } @@ -187,6 +198,9 @@ else if (base && !url->protocol) { if (!url->user && !url->authmech && !url->passwd && !url->host && !url->port && !url->path && +#ifdef ENABLE_IDN + !url->utf8_host && +#endif !url->params && !url->query && !url->fragment) url->fragment = g_strdup (base->fragment); @@ -195,6 +209,9 @@ url->authmech = g_strdup (base->authmech); url->passwd = g_strdup (base->passwd); url->host = g_strdup (base->host); +#ifdef ENABLE_IDN + url->utf8_host = g_strdup (base->utf8_host); +#endif url->port = base->port; if (!url->path) { Index: camel/camel-url.h =================================================================== RCS file: /cvs/gnome/evolution/camel/camel-url.h,v retrieving revision 1.19 diff -u -r1.19 camel-url.h --- camel/camel-url.h 23 Apr 2003 01:34:02 -0000 1.19 +++ camel/camel-url.h 18 Dec 2003 20:39:06 -0000 @@ -42,6 +42,9 @@ char *authmech; char *passwd; char *host; +#ifdef ENABLE_IDN + char *utf8_host; +#endif int port; char *path; GData *params; Index: camel/providers/imap/camel-imap-store.c =================================================================== RCS file: /cvs/gnome/evolution/camel/providers/imap/camel-imap-store.c,v retrieving revision 1.262 diff -u -r1.262 camel-imap-store.c --- camel/providers/imap/camel-imap-store.c 10 Dec 2003 19:22:20 -0000 1.262 +++ camel/providers/imap/camel-imap-store.c 18 Dec 2003 20:39:06 -0000 @@ -65,6 +65,11 @@ #define d(x) +#ifdef ENABLE_IDN +#define UTF8_HOST (service->url->utf8_host ? service->url->utf8_host : \ + service->url->host) +#endif + /* Specified in RFC 2060 */ #define IMAP_PORT 143 #define SIMAP_PORT 993 @@ -456,10 +461,19 @@ imap_get_name (CamelService *service, gboolean brief) { if (brief) +#ifdef ENABLE_IDN + return g_strdup_printf (_("IMAP server %s"), UTF8_HOST); +#else return g_strdup_printf (_("IMAP server %s"), service->url->host); +#endif else +#ifdef ENABLE_IDN + return g_strdup_printf (_("IMAP service for %s on %s"), + service->url->user, UTF8_HOST); +#else return g_strdup_printf (_("IMAP service for %s on %s"), service->url->user, service->url->host); +#endif } static void @@ -600,7 +614,12 @@ else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Could not connect to %s (port %d): %s"), - service->url->host, port, g_strerror (errno)); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + port, g_strerror (errno)); camel_object_unref (CAMEL_OBJECT (tcp_stream)); @@ -663,7 +682,12 @@ /* server doesn't support STARTTLS, abort */ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL/TLS extension not supported.")); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + _("SSL/TLS extension not supported.")); /* we have the possibility of quitting cleanly here */ clean_quit = TRUE; goto exception; @@ -694,7 +718,12 @@ if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + _("SSL negotiations failed")); goto exception; } @@ -1246,7 +1275,11 @@ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("IMAP server %s does not support requested " "authentication type %s"), +#ifdef ENABLE_IDN + UTF8_HOST, +#else service->url->host, +#endif service->url->authmech); return FALSE; } @@ -1281,7 +1314,11 @@ "password for %s %s"), errbuf ? errbuf : "", service->url->user, +#ifdef ENABLE_IDN + UTF8_HOST); +#else service->url->host); +#endif service->url->passwd = camel_session_get_password (session, prompt, FALSE, TRUE, service, "password", ex); Index: camel/providers/nntp/camel-nntp-store.c =================================================================== RCS file: /cvs/gnome/evolution/camel/providers/nntp/camel-nntp-store.c,v retrieving revision 1.54 diff -u -r1.54 camel-nntp-store.c --- camel/providers/nntp/camel-nntp-store.c 22 Sep 2003 15:00:59 -0000 1.54 +++ camel/providers/nntp/camel-nntp-store.c 18 Dec 2003 20:39:06 -0000 @@ -49,6 +49,11 @@ extern int camel_verbose_debug; #define dd(x) (camel_verbose_debug?(x):0) +#ifdef ENABLE_IDN +#define UTF8_HOST (service->url->utf8_host ? service->url->utf8_host : \ + service->url->host) +#endif + #define NNTP_PORT 119 #define NNTPS_PORT 563 @@ -129,7 +134,12 @@ else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Could not connect to %s (port %d): %s"), - service->url->host, port, g_strerror (errno)); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + port, g_strerror (errno)); camel_object_unref (CAMEL_OBJECT (tcp_stream)); @@ -147,7 +157,12 @@ else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Could not read greeting from %s: %s"), - service->url->host, g_strerror (errno)); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + g_strerror (errno)); camel_object_unref (CAMEL_OBJECT (store->stream)); store->stream = NULL; @@ -159,7 +174,12 @@ if (len != 200 && len != 201) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("NNTP server %s returned error code %d: %s"), - service->url->host, len, buf); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + len, buf); camel_object_unref (CAMEL_OBJECT (store->stream)); store->stream = NULL; @@ -255,9 +275,19 @@ nntp_store_get_name (CamelService *service, gboolean brief) { if (brief) - return g_strdup_printf ("%s", service->url->host); + return g_strdup_printf ("%s", +#ifdef ENABLE_IDN + UTF8_HOST); +#else + service->url->host); +#endif else - return g_strdup_printf (_("USENET News via %s"), service->url->host); + return g_strdup_printf (_("USENET News via %s"), +#ifdef ENABLE_IDN + UTF8_HOST); +#else + service->url->host); +#endif } Index: camel/providers/pop3/camel-pop3-store.c =================================================================== RCS file: /cvs/gnome/evolution/camel/providers/pop3/camel-pop3-store.c,v retrieving revision 1.101 diff -u -r1.101 camel-pop3-store.c --- camel/providers/pop3/camel-pop3-store.c 28 Oct 2003 19:01:56 -0000 1.101 +++ camel/providers/pop3/camel-pop3-store.c 18 Dec 2003 20:39:06 -0000 @@ -58,6 +58,11 @@ /* Specified in RFC 1939 */ #define POP3_PORT 110 +#ifdef ENABLE_IDN +#define UTF8_HOST (service->url->utf8_host ? service->url->utf8_host : \ + service->url->host) +#endif + static CamelStoreClass *parent_class = NULL; static void finalize (CamelObject *object); @@ -195,7 +200,12 @@ else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Could not connect to POP server %s (port %d): %s"), - service->url->host, port, g_strerror (errno)); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + port, g_strerror (errno)); camel_object_unref (CAMEL_OBJECT (tcp_stream)); @@ -227,7 +237,12 @@ /* server doesn't support STARTTLS, abort */ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, _("SSL/TLS extension not supported.")); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + _("SSL/TLS extension not supported.")); /* we have the possibility of quitting cleanly here */ clean_quit = TRUE; goto stls_exception; @@ -256,7 +271,12 @@ if (ret == FALSE) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, store->engine->line); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + store->engine->line); goto stls_exception; } @@ -268,7 +288,12 @@ if (ret == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + _("SSL negotiations failed")); goto stls_exception; } @@ -366,7 +391,11 @@ } else { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Could not connect to POP server %s"), +#ifdef ENABLE_IDN + UTF8_HOST); +#else service->url->host); +#endif } return types; @@ -478,7 +507,11 @@ prompt = g_strdup_printf (_("%sPlease enter the POP password for %s %s"), errmsg ? errmsg : "", service->url->user, +#ifdef ENABLE_IDN + UTF8_HOST); +#else service->url->host); +#endif service->url->passwd = camel_session_get_password (camel_service_get_session (service), prompt, reprompt, TRUE, service, "password", ex); g_free (prompt); Index: camel/providers/smtp/camel-smtp-transport.c =================================================================== RCS file: /cvs/gnome/evolution/camel/providers/smtp/camel-smtp-transport.c,v retrieving revision 1.150 diff -u -r1.150 camel-smtp-transport.c --- camel/providers/smtp/camel-smtp-transport.c 9 Dec 2003 00:58:46 -0000 1.150 +++ camel/providers/smtp/camel-smtp-transport.c 18 Dec 2003 20:39:06 -0000 @@ -63,6 +63,11 @@ /* Specified in RFC 821 */ #define SMTP_PORT 25 +#ifdef ENABLE_IDN +#define UTF8_HOST (service->url->utf8_host ? service->url->utf8_host : \ + service->url->host) +#endif + /* camel smtp transport class prototypes */ static gboolean smtp_send_to (CamelTransport *transport, CamelMimeMessage *message, CamelAddress *from, CamelAddress *recipients, CamelException *ex); @@ -283,7 +288,12 @@ if (ret == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Could not connect to %s (port %d): %s"), - service->url->host, port, +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + port, g_strerror (errno)); camel_object_unref (tcp_stream); @@ -341,7 +351,12 @@ /* server doesn't support STARTTLS, abort */ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to SMTP server %s in secure mode: %s"), - service->url->host, _("server does not appear to support SSL")); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + _("server does not appear to support SSL")); goto exception_cleanup; } } @@ -380,7 +395,12 @@ if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to SMTP server %s in secure mode: %s"), - service->url->host, g_strerror (errno)); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + g_strerror (errno)); goto exception_cleanup; } @@ -475,7 +495,12 @@ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("SMTP server %s does not support requested " "authentication type %s."), - service->url->host, service->url->authmech); +#ifdef ENABLE_IDN + UTF8_HOST, +#else + service->url->host, +#endif + service->url->authmech); camel_service_disconnect (service, TRUE, NULL); return FALSE; } @@ -513,7 +538,11 @@ prompt = g_strdup_printf (_("%sPlease enter the SMTP password for %s %s"), errbuf ? errbuf : "", service->url->user, - service->url->host); +#ifdef ENABLE_IDN + UTF8_HOST); +#else + service->url->host); +#endif service->url->passwd = camel_session_get_password (session, prompt, FALSE, TRUE, service, "password", ex); @@ -663,10 +692,19 @@ get_name (CamelService *service, gboolean brief) { if (brief) - return g_strdup_printf (_("SMTP server %s"), service->url->host); + return g_strdup_printf (_("SMTP server %s"), +#ifdef ENABLE_IDN + UTF8_HOST); +#else + service->url->host); +#endif else { return g_strdup_printf (_("SMTP mail delivery via %s"), - service->url->host); +#ifdef ENABLE_IDN + UTF8_HOST); +#else + service->url->host); +#endif } } Index: e-util/ChangeLog =================================================================== RCS file: /cvs/gnome/evolution/e-util/ChangeLog,v retrieving revision 1.427 diff -u -r1.427 ChangeLog --- e-util/ChangeLog 6 Dec 2003 18:15:20 -0000 1.427 +++ e-util/ChangeLog 18 Dec 2003 20:39:06 -0000 @@ -1,3 +1,62 @@ +2003-12-15 Suresh Chandrasekharan <suresh chandrasekharan sun com> + + * e-account.c: (xml_set_service) When setting EAccount fileds from + xml source, put in hostname in ASCII compatible format. + + (e_account_to_xml) When writing out xmlDoc from EAccount write it + in ASCII compatible format. + + These two changes make sure that internal to evolution only the + ASCII compatible host name is used. + + * e-html-utils.c: (url_extract) Validate non-ASCII urls for + making them 'clickable' display in addressbook contact display. + + * e-url.c: (e_uri_new) Modified to return the right hostname part of a + uri, even if it does not contain a '://' part. Eg. "mailto:abc cde org" + now gets parsed correctly. uri_decode function won't be called if + ENABLE_IDN flag is set. + + (e_uri_copy) Added an additional parameter called host_offset, used + in replacing the original UTF-8 hostname by the ACE encoded or vice + versa. + + (e_uri_to_string) Fixed the bug causing the removal of the '/' + seperating the path name from the rest of url when EUri is converted + back to string. + + The folowing functions are added, + + (e_uri_encode_host) Pass in a UTF-8 host name and and ACE name will be + returned. Made robust by additional checks for encoded url etc. + + (e_uri_decode_host) Pass in an ACE host name and the equivalent UTF-8 + hostname will be returned. This functions is made robust by additonal + checks and it can take in UTF-8 string, encoded url with %hex codes. + + (e_uri_replace_with_decd_host) Replaces the UTF-8 hostname part of the + URI with ACE encoding extra memory if need will be allocated in place. + + (e_uri_replace_with_encd_host) Replaces the ACE hostname part of the + URI with UTF-8 encoding extra memory if need will be allocated in place. + + (e_uri_gnome_show_idn_url) Call browser with a supplied URL having + UTD-8 hostname. + + (replace_str) This static function is used to replace an oldstr + at offset oldstr_offset witha newstr, the additional memory needed + id allocated within. + + (cache_coded_host) A functions which will store and retrieve + ace_name/utf8_name pairs. Used to reduce the overhead in frequent + idnkit function calls. Thread safe. + + * e-url.h: + Added the parameter host_offset to EUri struct. Added + e_uri_encode_host, e_uri_decode_host, e_uri_replace_with_decd_host, + e_uri_replace_with_encd_host and e_uri_gnome_show_idn_url + as new function declarations. + 2003-12-06 JP Rosevear <jpr ximian com> * Makefile.am: Remove hard coded disable deprecated flags Index: e-util/e-account.c =================================================================== RCS file: /cvs/gnome/evolution/e-util/e-account.c,v retrieving revision 1.5 diff -u -r1.5 e-account.c --- e-util/e-account.c 31 Oct 2003 04:55:41 -0000 1.5 +++ e-util/e-account.c 18 Dec 2003 20:39:06 -0000 @@ -25,6 +25,10 @@ #include "e-uid.h" +#ifdef ENABLE_IDN +#include "e-url.h" +#endif + #include <string.h> #include <gal/util/e-util.h> @@ -268,7 +272,19 @@ for (node = node->children; node; node = node->next) { if (!strcmp (node->name, "url")) { +#ifdef ENABLE_IDN + gboolean url_changed = FALSE; + url_changed = xml_set_content (node, &service->url); + changed |= url_changed; + if (url_changed && service->url) { + char *t = g_strdup (service->url); + e_uri_replace_with_encd_host (&t); + g_free (service->url); + service->url = t; + } +#else changed |= xml_set_content (node, &service->url); +#endif break; } } @@ -478,13 +494,30 @@ xmlSetProp (src, "auto-check", account->source->auto_check ? "true" : "false"); sprintf (buf, "%d", account->source->auto_check_time); xmlSetProp (src, "auto-check-timeout", buf); - if (account->source->url) + if (account->source->url) { +#ifdef ENABLE_IDN + char *t = g_strdup (account->source->url); + e_uri_replace_with_encd_host (&t); + xmlNewTextChild (src, NULL, "url", t); + g_free (t); + +#else xmlNewTextChild (src, NULL, "url", account->source->url); +#endif + } xport = xmlNewChild (root, NULL, "transport", NULL); xmlSetProp (xport, "save-passwd", account->transport->save_passwd ? "true" : "false"); - if (account->transport->url) + if (account->transport->url) { +#ifdef ENABLE_IDN + char *t = g_strdup (account->transport->url); + e_uri_replace_with_encd_host (&t); + xmlNewTextChild (xport, NULL, "url", t); + g_free (t); +#else xmlNewTextChild (xport, NULL, "url", account->transport->url); +#endif + } xmlNewTextChild (root, NULL, "drafts-folder", account->drafts_folder_uri); xmlNewTextChild (root, NULL, "sent-folder", account->sent_folder_uri); Index: e-util/e-html-utils.c =================================================================== RCS file: /cvs/gnome/evolution/e-util/e-html-utils.c,v retrieving revision 1.40 diff -u -r1.40 e-html-utils.c --- e-util/e-html-utils.c 7 Nov 2003 21:27:34 -0000 1.40 +++ e-util/e-html-utils.c 18 Dec 2003 20:39:07 -0000 @@ -17,12 +17,16 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ - +#include <config.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <glib.h> +#ifdef ENABLE_IDN +#include "e-url.h" +#endif + #include "e-html-utils.h" static char * @@ -70,7 +74,7 @@ url_extract (const unsigned char **text, gboolean full_url) { const unsigned char *end = *text, *p; - char *out; + char *out, *t; while (*end && is_url_char (*end)) end++; @@ -80,8 +84,32 @@ end--; if (full_url) { +#ifdef ENABLE_IDN + EUri *uri; + + uri = e_uri_new (*text); + p = memchr (*text, ':', end - *text); + if (uri->host && (strcmp (uri->host, "") != 0)) { + /* if hostname OK */ + if (p) { + while ((end=++p) && *end=='/'); + + if (*end) + end = (t = strchr (end,'/')) ? t : end + strlen (end); + + while (*end && is_url_char (*end)) + end++; + + /* Back up if we probably went too far. */ + while (end > *text && (special_chars [*(end - 1)] & 2)) + end--; + } + } + e_uri_free (uri); +#else /* Make sure this really looks like a URL. */ p = memchr (*text, ':', end - *text); +#endif if (!p || end - p < 4) return NULL; } else { Index: e-util/e-url.c =================================================================== RCS file: /cvs/gnome/evolution/e-util/e-url.c,v retrieving revision 1.11 diff -u -r1.11 e-url.c --- e-util/e-url.c 8 May 2003 14:18:45 -0000 1.11 +++ e-util/e-url.c 18 Dec 2003 20:39:07 -0000 @@ -29,8 +29,18 @@ #include <ctype.h> #include <stdlib.h> #include <string.h> + +#ifdef ENABLE_IDN +#include <idn/api.h> +#include <errno.h> +#include <libgnome/gnome-url.h> +#include <glib.h> +#include <gal/widgets/e-unicode.h> +#endif + #include "e-url.h" + char * e_url_shroud (const char *url) { @@ -112,8 +122,9 @@ e_uri_new (const char *uri_string) { EUri *uri; - const char *end, *hash, *colon, *semi, *at, *slash, *question; - const char *p; + const char *end, *hash, *colon, *semi, *at, *slash, *quest, *path; + const char *p, *uri_start = uri_string; + const char *host_end; if (!uri_string) return NULL; @@ -146,65 +157,76 @@ return uri; /* check for authority */ - if (strncmp (uri_string, "//", 2) == 0) { + if (strncmp (uri_string, "//", 2) == 0) uri_string += 2; - slash = uri_string + strcspn (uri_string, "/#"); - at = strchr (uri_string, '@'); - if (at && at < slash) { - colon = strchr (uri_string, ':'); - if (colon && colon < at) { - uri->passwd = g_strndup (colon + 1, at - colon - 1); - uri_decode (uri->passwd); - } - else { - uri->passwd = NULL; - colon = at; - } - - semi = strchr (uri_string, ';'); - if (semi && semi < colon && - !strncasecmp (semi, ";auth=", 6)) { - uri->authmech = g_strndup (semi + 6, colon - semi - 6); - uri_decode (uri->authmech); - } - else { - uri->authmech = NULL; - semi = colon; - } - - uri->user = g_strndup (uri_string, semi - uri_string); - uri_decode (uri->user); - uri_string = at + 1; + slash = uri_string + strcspn (uri_string, "/#"); + at = strchr (uri_string, '@'); + if (at && at < slash) { + colon = strchr (uri_string, ':'); + if (colon && colon < at) { + uri->passwd = g_strndup (colon + 1, at - colon - 1); + uri_decode (uri->passwd); + } + else { + uri->passwd = NULL; + colon = at; } - else - uri->user = uri->passwd = uri->authmech = NULL; - /* find host and port */ - colon = strchr (uri_string, ':'); - if (colon && colon < slash) { - uri->host = g_strndup (uri_string, colon - uri_string); - uri->port = strtoul (colon + 1, NULL, 10); + semi = strchr (uri_string, ';'); + if (semi && semi < colon && + !strncasecmp (semi, ";auth=", 6)) { + uri->authmech = g_strndup (semi + 6, colon - semi - 6); + uri_decode (uri->authmech); } else { - uri->host = g_strndup (uri_string, slash - uri_string); - uri_decode (uri->host); - uri->port = 0; + uri->authmech = NULL; + semi = colon; } - uri_string = slash; + uri->user = g_strndup (uri_string, semi - uri_string); + uri_decode (uri->user); + uri_string = at + 1; } + else + uri->user = uri->passwd = uri->authmech = NULL; - /* find query */ - question = memchr (uri_string, '?', end - uri_string); - if (question) { - if (question[1]) { - uri->query = g_strndup (question + 1, end - (question + 1)); - uri_decode (uri->query); - } - end = question; + /* find host and port */ + colon = strchr (uri_string, ':'); + path = uri_string + strcspn (uri_string, "/"); + quest = uri_string + strcspn (uri_string, "?"); + host_end = path<quest ? path : quest; + + if (colon && colon < slash) { + uri->host = g_strndup (uri_string, colon - uri_string); + uri->host_offset = uri_string - uri_start; +#ifndef ENABLE_IDN + uri_decode (uri->host); +#endif + uri->port = strtoul (colon + 1, (char **)&uri_string, 10); + } + else { + uri->host = g_strndup (uri_string, host_end - uri_string); + uri->host_offset = uri_string - uri_start; +#ifndef ENABLE_IDN + uri_decode (uri->host); +#endif + uri_string = host_end; + uri->port = 0; } + if (path < quest && path != end && path[0] == '/' && path[1]) { + uri->path = g_strndup (path + 1, quest - (path + 1)); + uri_decode (uri->path); + uri_string = end; + } + + if (quest != end && quest[0] == '?' && quest[1]) { + uri->query = g_strndup (quest + 1, end - (quest + 1)); + uri_decode (uri->query); + uri_string = end; + } + /* find parameters */ semi = memchr (uri_string, ';', end - uri_string); if (semi) { @@ -266,6 +288,7 @@ return g_datalist_get_data (&uri->params, name); } + static void copy_param_cb (GQuark key_id, gpointer data, gpointer user_data) { @@ -274,6 +297,201 @@ g_datalist_id_set_data_full (¶ms, key_id, g_strdup (data), g_free); } +#ifdef ENABLE_IDN + +static char * +replace_str(char *str, int oldstr_offset, char *oldstr, char *newstr) { + int oldlen, newlen; + char *p, *q; + + if (!oldstr || !newstr) { + return NULL; + } + + oldlen = strlen (oldstr); + newlen = strlen (newstr); + + if (newlen > oldlen) + str = (char *)realloc (str, strlen (str) + newlen - oldlen + 1); + + p = str + oldstr_offset; + + memmove (q = p + newlen, p + oldlen, strlen (p + oldlen) + 1); + memcpy (p, newstr, newlen); + return str; +} + +static char * +cache_coded_host (char *ace_name, char *utf8_name) { + static char *stored_ace = NULL; + static char *stored_utf8 = NULL; + G_LOCK_DEFINE_STATIC (cache_lock); + + G_LOCK (cache_lock); + if (ace_name && utf8_name) { + if (stored_ace) g_free (stored_ace); + if (stored_utf8) g_free (stored_utf8); + + stored_ace = g_strdup (ace_name); + stored_utf8 = g_strdup (utf8_name); + G_UNLOCK (cache_lock); + return NULL; + } + + if (ace_name && !utf8_name) { + if (stored_utf8 && !strcmp (ace_name, stored_ace)) { + char *t = g_strdup (stored_utf8); + G_UNLOCK (cache_lock); + return t; + } + } + + if (!ace_name && utf8_name) { + if (stored_ace && !strcmp (utf8_name, stored_utf8)) { + char *t = g_strdup (stored_ace); + G_UNLOCK (cache_lock); + return t; + } + } + + G_UNLOCK (cache_lock); + return NULL; +} + +char * +e_uri_decode_host (char *ace_name) +{ + idn_result_t r; + char utf8_name[256]; + char *t = NULL, *d = NULL; + + + if (!ace_name || !strcmp (ace_name,"")) { + return NULL; + } + + t = strdup (ace_name); + + uri_decode (t); + + /* make sure it is ACE */ + if (!e_utf8_is_ascii(t)) { + char *tmp = e_uri_encode_host (t); + g_free (t); + t = tmp; + } + + if (!t && !t[0]) { + return NULL; + } + + if ((d = cache_coded_host (t, NULL)) != NULL) { + g_free (t); + return d; + } + + r = idn_decodename ( IDN_DELIMMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK, t, utf8_name, sizeof (utf8_name)); + + if (r == idn_success) { + if (strcmp (t, utf8_name)) + cache_coded_host (t, utf8_name); + d = strdup(utf8_name); + } + + g_free (t); + + return d; +} + +char * +e_uri_encode_host (char *utf8_name) +{ + idn_result_t r; + char ace_name[256]; + char *t = NULL, *d = NULL; + + + if (!utf8_name || !strcmp (utf8_name,"")) { + return NULL; + } + + t = strdup (utf8_name); + + uri_decode (t); + + if (!t && !t[0]) { + return NULL; + } + + if ((d = cache_coded_host (NULL, t)) != NULL) { + g_free (t); + return d; + } + + r = idn_encodename ( IDN_DELIMMAP | IDN_LOCALMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_LENCHECK | IDN_ASCCHECK, t, ace_name, sizeof (ace_name)); + + + if (r == idn_success) { + if (strcmp (ace_name, t)) + cache_coded_host (ace_name, t); + d = strdup(ace_name); + } + + g_free (t); + + return d; +} + +void +e_uri_gnome_show_idn_url (const char *uri_string, GError **err) { + char *t = strdup (uri_string); + + e_uri_replace_with_encd_host (&t); + gnome_url_show (t, err); + g_free (t); +} + +void +e_uri_replace_with_encd_host (char **uri_string) +{ + EUri *uri; + char *idnh; + + + if (!*uri_string) return; + + + uri = e_uri_new (*uri_string); + if (uri->host && (strcmp (uri->host, "") != 0)) { + idnh = e_uri_encode_host (uri->host); + if (idnh) { + *uri_string = replace_str (*uri_string, uri->host_offset, uri->host, idnh); + g_free (idnh); + } + } + e_uri_free (uri); +} + +void +e_uri_replace_with_decd_host (char **uri_string) +{ + EUri *uri; + char *idnh; + + if (!*uri_string) return; + + uri = e_uri_new (*uri_string); + if (uri->host && (strcmp (uri->host, "") != 0)) { + idnh = e_uri_decode_host (uri->host); + if (idnh) { + *uri_string = replace_str (*uri_string, uri->host_offset, uri->host, idnh); + g_free (idnh); + } + } + e_uri_free (uri); +} +#endif + EUri * e_uri_copy (EUri *uri) { @@ -291,6 +509,7 @@ uri_copy->path = g_strdup (uri->path); uri_copy->query = g_strdup (uri->query); uri_copy->fragment = g_strdup (uri->fragment); + uri_copy->host_offset = uri->host_offset; /* copy uri->params */ g_datalist_foreach (&uri->params, @@ -309,7 +528,7 @@ if (uri->port != 0) str_uri = g_strdup_printf ( - "%s://%s%s%s%s%s%s%s:%d%s%s%s", + "%s://%s%s%s%s%s%s%s:%d%s%s%s%s", uri->protocol, uri->user ? uri->user : "", uri->authmech ? ";auth=" : "", @@ -319,12 +538,13 @@ uri->user ? "@" : "", uri->host ? uri->host : "", uri->port, + uri->path ? "/" : "", uri->path ? uri->path : "", uri->query ? "?" : "", uri->query ? uri->query : ""); else str_uri = g_strdup_printf( - "%s://%s%s%s%s%s%s%s%s%s%s", + "%s://%s%s%s%s%s%s%s%s%s%s%s", uri->protocol, uri->user ? uri->user : "", uri->authmech ? ";auth=" : "", @@ -333,6 +553,7 @@ uri->passwd && show_password ? uri->passwd : "", uri->user ? "@" : "", uri->host ? uri->host : "", + uri->path ? "/" : "", uri->path ? uri->path : "", uri->query ? "?" : "", uri->query ? uri->query : ""); Index: e-util/e-url.h =================================================================== RCS file: /cvs/gnome/evolution/e-util/e-url.h,v retrieving revision 1.5 diff -u -r1.5 e-url.h --- e-util/e-url.h 27 Oct 2001 16:59:34 -0000 1.5 +++ e-util/e-url.h 18 Dec 2003 20:39:07 -0000 @@ -44,6 +44,7 @@ GData *params; char *query; char *fragment; + int host_offset; } EUri; EUri *e_uri_new (const char *uri_string); @@ -52,5 +53,13 @@ EUri *e_uri_copy (EUri *uri); char *e_uri_to_string (EUri *uri, gboolean show_password); +#ifdef ENABLE_IDN +char *e_uri_encode_host (char *utf8_name); +char *e_uri_decode_host (char *ace_name); +void e_uri_replace_with_decd_host (char **uri_string); +void e_uri_replace_with_encd_host (char **uri_string); +void e_uri_gnome_show_idn_url (const char *uri_string, GError **err); +#endif + #endif /* __E_URL_H__ */ Index: mail/ChangeLog =================================================================== RCS file: /cvs/gnome/evolution/mail/ChangeLog,v retrieving revision 1.2960 diff -u -r1.2960 ChangeLog --- mail/ChangeLog 12 Dec 2003 00:05:00 -0000 1.2960 +++ mail/ChangeLog 18 Dec 2003 20:39:07 -0000 @@ -1,3 +1,21 @@ +2003-12-15 Suresh Chandrasekharan <suresh chandrasekharan sun com> + + * em-folder-view.c: (emfv_format_link_clicked): When a multibyte + hostname is appearing on a URL, convert it into suitable ASCII + encoding before passing over to gnome_url_show. + + * mail-account-gui.c: (setup_service) Display the mail server name + in UTF-8 in account set up windows. + + * mail-ops.c: (get_folder_desc) Change the output hostname to UTF-8. + + * mail-send-recv.c: (format_url) hostname in message when the + Send/receive button is clicked changed to utf8. + + * mail-vfolder.c: (vfolder_adduri_desc) Display utf8 host name in + 'Updating vfolders for uri' message + + 2003-12-12 Not Zed <NotZed Ximian com> * mail-config.c (config_write_style): put the style in .evolution. Index: mail/em-folder-view.c =================================================================== RCS file: /cvs/gnome/evolution/mail/em-folder-view.c,v retrieving revision 1.19 diff -u -r1.19 em-folder-view.c --- mail/em-folder-view.c 11 Dec 2003 04:56:12 -0000 1.19 +++ mail/em-folder-view.c 18 Dec 2003 20:39:07 -0000 @@ -56,6 +56,10 @@ #include "widgets/misc/e-charset-picker.h" +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include <e-util/e-dialog-utils.h> #include "em-format-html-display.h" @@ -1793,8 +1797,11 @@ /* ignore */ } else { GError *err = NULL; - +#ifdef ENABLE_IDN + e_uri_gnome_show_idn_url (uri, &err); +#else gnome_url_show (uri, &err); +#endif if (err) { g_warning ("gnome_url_show: %s", err->message); Index: mail/mail-account-gui.c =================================================================== RCS file: /cvs/gnome/evolution/mail/mail-account-gui.c,v retrieving revision 1.142 diff -u -r1.142 mail-account-gui.c --- mail/mail-account-gui.c 13 Nov 2003 22:33:02 -0000 1.142 +++ mail/mail-account-gui.c 18 Dec 2003 20:39:07 -0000 @@ -36,6 +36,10 @@ #include <e-util/e-account-list.h> #include <e-util/e-dialog-utils.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "em-folder-selection-button.h" #include "mail-account-gui.h" #include "mail-session.h" @@ -1114,10 +1118,21 @@ if (url->host && CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_HOST)) { char *hostname; - if (url->port) + if (url->port) { +#ifdef ENABLE_IDN + char *h = e_uri_decode_host (url->host); + hostname = g_strdup_printf ("%s:%d", h, url->port); + g_free(h); +#else hostname = g_strdup_printf ("%s:%d", url->host, url->port); - else +#endif + } else { +#ifdef ENABLE_IDN + hostname = e_uri_decode_host (url->host); +#else hostname = g_strdup (url->host); +#endif + } gtk_entry_set_text (gsvc->hostname, hostname); g_free (hostname); Index: mail/mail-send-recv.c =================================================================== RCS file: /cvs/gnome/evolution/mail/mail-send-recv.c,v retrieving revision 1.79 diff -u -r1.79 mail-send-recv.c --- mail/mail-send-recv.c 17 Nov 2003 03:32:41 -0000 1.79 +++ mail/mail-send-recv.c 18 Dec 2003 20:39:07 -0000 @@ -34,6 +34,10 @@ #include <gtk/gtkstock.h> #include <libgnomeui/gnome-window-icon.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "e-util/e-gtk-utils.h" #include "widgets/misc/e-clipped-label.h" @@ -250,7 +254,13 @@ url = camel_url_new(internal_url, NULL); if (url->host) - pretty_url = g_strdup_printf(_("Server: %s, Type: %s"), url->host, url->protocol); + pretty_url = g_strdup_printf(_("Server: %s, Type: %s"), +#ifdef ENABLE_IDN + url->utf8_host ? url->utf8_host : url->host, +#else + url->host, +#endif + url->protocol); else if (url->path) pretty_url = g_strdup_printf(_("Path: %s, Type: %s"), url->path, url->protocol); else Index: mail/mail-vfolder.c =================================================================== RCS file: /cvs/gnome/evolution/mail/mail-vfolder.c,v retrieving revision 1.107 diff -u -r1.107 mail-vfolder.c --- mail/mail-vfolder.c 3 Dec 2003 15:37:54 -0000 1.107 +++ mail/mail-vfolder.c 18 Dec 2003 20:39:07 -0000 @@ -28,6 +28,10 @@ #include <string.h> #include <libgnome/gnome-i18n.h> +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif + #include "Evolution.h" #include "mail-component.h" @@ -201,8 +205,16 @@ vfolder_adduri_desc(struct _mail_msg *mm, int done) { struct _adduri_msg *m = (struct _adduri_msg *)mm; - +#ifdef ENABLE_IDN + char *dup_str; + char *decd_uri = g_strdup (m->uri); + e_uri_replace_with_decd_host (&decd_uri); + dup_str = g_strdup_printf(_("Updating vfolders for uri: %s"), decd_uri); + g_free (decd_uri); + return dup_str; +#else return g_strdup_printf(_("Updating vfolders for uri: %s"), m->uri); +#endif } static void Index: widgets/ChangeLog =================================================================== RCS file: /cvs/gnome/evolution/widgets/ChangeLog,v retrieving revision 1.112 diff -u -r1.112 ChangeLog --- widgets/ChangeLog 10 Dec 2003 01:12:42 -0000 1.112 +++ widgets/ChangeLog 18 Dec 2003 20:39:08 -0000 @@ -1,3 +1,9 @@ +2003-12-15 Suresh Chandrasekharan <suresh chandrasekharan sun com> + + * misc/e-url-entry.c: (button_clicked_cb) When clicking on + the 'connect' button for EUrlEntry widget, change the hostname + to ACE before passing to gnome_url_show. + 2003-12-10 Not Zed <NotZed Ximian com> * menus/gal-view-menus.c (remove_instance): NULL out Index: widgets/misc/e-url-entry.c =================================================================== RCS file: /cvs/gnome/evolution/widgets/misc/e-url-entry.c,v retrieving revision 1.8 diff -u -r1.8 e-url-entry.c --- widgets/misc/e-url-entry.c 13 Jul 2003 19:29:03 -0000 1.8 +++ widgets/misc/e-url-entry.c 18 Dec 2003 20:39:08 -0000 @@ -28,6 +28,9 @@ #include <gtk/gtk.h> #include <libgnome/gnome-url.h> #include "e-url-entry.h" +#ifdef ENABLE_IDN +#include <e-util/e-url.h> +#endif struct _EUrlEntryPrivate { GtkWidget *entry; @@ -171,6 +174,11 @@ priv = url_entry->priv; url = gtk_editable_get_chars (GTK_EDITABLE (priv->entry), 0, -1); + +#ifdef ENABLE_IDN + e_uri_gnome_show_idn_url (url, NULL); +#else gnome_url_show (url, NULL); +#endif g_free (url); }
International Domain Names Support in Evolution-1.5 --------------------------------------------------- Pre-requisite for getting IDN support in Evolution. --------------------------------------------------- Download build and install the idnkit library from http://www.nic.ad.jp/ja/idn/idnkit/download/. I have provided a rpm along with this to use, which's a slightly modified version of the download from above, plus a .pc file etc, which makes it possible for pkg-config to find out about it. Refer to libidnkit(3LIB) for documentation on supported functions. What's in and what's not in IDN support --------------------------------------- Plainly speaking it's support for Internationalized Host Names (non-ASCII) in domain name, hostname and URLs. Only host names in URLs come under the scope of IDN. The path names in a URL or host names in e-mail addresses does not come under this. Internal to Evolution only ASCII Compatible Encoded host name corresponding to the input UTF8 is used. So this means that we only need to convert to UTF-8 name when we need to actually display the name. Due to this same same configuration files can be used by a IDN'ized and a non-IDN Evolution, as they are compatible and no 8 bit characters are used. The following is information about IDN standards. The IETF IDN WG (Internationalized Domain Name Working Group) generated four Internet Drafts and they are now all published recently from the IESG as RFCs [1], [2], [3], and [4]. The published RFCs, as a set, defines the architecture and the IDN support scheme called IDNA (Internationalizing Domain Names in Applications) [1]. [1] RFC3490, Internationalizing Domain Names in Applications (IDNA), March 2003. ftp://ftp.ietf.org/rfc/rfc3490.txt [2] RFC3454, Preparation of Internationalized Strings ("stringprep"), December 2002. ftp://ftp.ietf.org/rfc/rfc3454.txt [3] RFC3491, Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN), March 2003. ftp://ftp.ietf.org/rfc/rfc3491.txt [4] RFC3492, Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA), March 2003. ftp://ftp.ietf.org/rfc/rfc3492.txt The Internationalizing Domain Names in Applications [IDNA] defines and suggests an implementation architecture for the IDN support in Internet applications. With the IDNA implemented, the Internet applications can support URIs, domain names, and host names in native language in various codesets. It is specified in the IDNA that the URIs, domain names, and host names in various codesets should be converted to ACE (ASCII Compatible Encoding) at the application before send down to resolvers and underlying transport layers/protocols. +------+ | User | +------+ ^ | Input and display: local interface methods | (pen, keyboard, glowing phosphorus, ...) +-------------------|-------------------------------+ | v | | +-----------------------------+ | | | Application | | | | (conversion between local | | | | character set and Unicode | | | | is done here) | | | | | | | | Locale's characters | | | | ^ | | | | | | | | | v | | | | Unicode | | | | ^ | | | | | | | | | v | | | | ACE | | | +-----------------------------+ | | ^ ^ | End system | | | | | Call to resolver: | | Application-specific | | ACE | | protocol: | | v | predefined by the | | +----------+ | protocol or defaults | | | Resolver | | to ACE | | +----------+ | | | ^ | | +-----------------|----------|----------------------+ DNS protocol: | | ACE | | v v +-------------+ +---------------------+ | DNS servers | | Application servers | +-------------+ +---------------------+ In Evolution since UTF-8 is used as the internal codeset the conversion step between current locale's codeset and UTF-8 avoided. IDN support currently not covers host name part of e-mail addresses as there are conflicting standards proposed, Internationalized Resource Identifiers is being standardized at W3C/IETF and the Internationalizing Mail Addresses in Applications is being std'zed at IETF, and there is an infra change proposal to support internationalized email address. The following are the links to the above three. http://www.ietf.org/internet-drafts/draft-hoffman-imaa-03.txt http://www.ietf.org/internet-drafts/draft-klensin-emailaddr-i18n-01.txt http://www.ietf.org/internet-drafts/draft-duerst-iri-05.txt seems like these conflicting proposed standards will take 1-2 years for reaching consensus, for the time being e-mail addresses are not covered under IDN. Whats IDN support in Evolution mean to the end user. --------------------------------------------------- With IDN supported evolution we can configure a non-ASCII host name as the name for the mail server or calendar sever or LDAP server in evolution. Also urls with non-ASCII host names can be clicked to reach the web pages. Also we can configure non-ASCII host names in the urls of the addressbook used by the contacts etc. Basically in all places a domain name, host name is used, it can be substituted by it's non-ASCII version. One thing to notice that, the path name part of the URL is still confined to ASCII characters. Only the host name part can be non-ASCII. The configuration files and data files produced by a IDN'ized version of evolution is fully readable by a version which's not IDN'ized. What this means is only for display purposes to the end user the non-ASCII names are used, internally evolution uses ASCII Compatible Encoded (ACE) host names for library/system calls interface. This makes sharing of the address book etc. possible by apps which is not IDN'ized with IDN supported evolution. How to create aliases for hostnames. ------------------------------------ If you do have a mail server/LDAP server/calendar server which you want to try this on, log in to a UTF-8 locale, compile the attached idn.c program like follows (after installing the idnkit library). cc -o idn idn.c -lidnkit Pick a UTF8 name you want to be the host name. ./idn <UTF8-hostname> It will output a ASCII name staring with 'xn--', like xn--48jm8lu34qkgo ask your sys admin to create an alias for your server with this, so that ypmatch <original hostname> hosts return the xn--48jm8lu34qkgo name too. After that xn--48jm8lu34qkgo that name in in the Evoution Settings. After you save it it will be displayed as the UTF8 name and in all messages password dialog etc. the UTF8 name will be used. Building Evolution ------------------- Use '--enable-idn' flag for enabling idn support when configuring evolution.
#include <stdio.h> #include <sys/types.h> #include <idn/api.h> int main(int argc, char *argv[]) { idn_result_t r; char ace_name[256]; char changed_name[256]; int i = 1; if ( argc<2 ) { printf ("Usage: %s \"UTF-8 hostname\"\n",argv[0]); exit (-1); } do { r = idn_encodename (IDN_DELIMMAP | IDN_LOCALMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_LENCHECK | IDN_ASCCHECK, argv[i], ace_name, sizeof (ace_name)); if (r != idn_success) { fprintf (stderr, "idn_encodename failed: \n"); continue; } r = idn_decodename(IDN_DELIMMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK, ace_name, changed_name, sizeof (changed_name)); if (r != idn_success) { fprintf (stderr, "idn_decodename failed: \n"); continue; } printf("%s----->%s\n", argv[i], ace_name); } while (++i < argc); return 0; }