Package: gaim Version: 1:1.5.0+1.5.1cvs20051015-1 Severity: wishlist Please consider applying this patch from upstream CVS to add SSL support for IRC in gaim. Thanks.
-- James --- gaim-1.5.0/src/protocols/irc/irc.c.orig 2005-07-24 20:27:36.000000000 +0100 +++ gaim-1.5.0/src/protocols/irc/irc.c 2005-12-15 23:51:13.000000000 +0000 @@ -45,13 +45,16 @@ static GList *irc_actions(GaimPlugin *plugin, gpointer context); /* static GList *irc_chat_info(GaimConnection *gc); */ static void irc_login(GaimAccount *account); +static void irc_login_cb_ssl(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond); static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond); +static void irc_ssl_connect_failure(GaimSslConnection *gsc, GaimSslErrorType error, gpointer data); static void irc_close(GaimConnection *gc); static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimConvImFlags flags); static int irc_chat_send(GaimConnection *gc, int id, const char *what); static void irc_ping_server(GaimConnection *gc); static void irc_chat_join (GaimConnection *gc, GHashTable *data); static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond); +static void irc_input_cb_ssl(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond); static guint irc_nick_hash(const char *nick); static gboolean irc_nick_equal(const char *nick1, const char *nick2); @@ -85,13 +88,20 @@ { int ret; - if (irc->fd < 0) - return -1; + if (irc->gsc) { + ret = gaim_ssl_write(irc->gsc, buf, strlen(buf)); + } else { + if (irc->fd < 0) + return -1; + ret = write(irc->fd, buf, strlen(buf)); + } - /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent: %s", buf); */ - if ((ret = write(irc->fd, buf, strlen(buf))) < 0) + /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent%s: %s", + irc->gsc ? " (ssl)" : "", buf); */ + if (ret < 0) { gaim_connection_error(gaim_account_get_connection(irc->account), _("Server has disconnected")); + } return ret; } @@ -237,43 +247,41 @@ gaim_connection_update_progress(gc, _("Connecting"), 1, 2); - err = gaim_proxy_connect(account, irc->server, + if (gaim_account_get_bool(account, "ssl", FALSE)) { + if (gaim_ssl_is_supported()) { + irc->gsc = gaim_ssl_connect(account, irc->server, + gaim_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT), + irc_login_cb_ssl, irc_ssl_connect_failure, gc); + } else { + gaim_connection_error(gc, _("SSL support unavailable")); + } + } + + if (!irc->gsc) { + + err = gaim_proxy_connect(account, irc->server, gaim_account_get_int(account, "port", IRC_DEFAULT_PORT), irc_login_cb, gc); - if (err || !account->gc) { - gaim_connection_error(gc, _("Couldn't create socket")); - return; + if (err || !account->gc) { + gaim_connection_error(gc, _("Couldn't create socket")); + return; + } } } -static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond) -{ - GaimConnection *gc = data; - struct irc_conn *irc = gc->proto_data; - char hostname[256]; +static gboolean do_login(GaimConnection *gc) { char *buf; + char hostname[256]; const char *username, *realname; - GList *connections = gaim_connections_get_all(); - - if (source < 0) { - gaim_connection_error(gc, _("Couldn't connect to host")); - return; - } - - if (!g_list_find(connections, gc)) { - close(source); - return; - } - - irc->fd = source; + struct irc_conn *irc = gc->proto_data; if (gc->account->password && *gc->account->password) { buf = irc_format(irc, "vv", "PASS", gc->account->password); if (irc_send(irc, buf) < 0) { gaim_connection_error(gc, "Error sending password"); g_free(buf); - return; + return FALSE; } g_free(buf); } @@ -287,18 +295,78 @@ if (irc_send(irc, buf) < 0) { gaim_connection_error(gc, "Error registering with server"); g_free(buf); - return; + return FALSE; } g_free(buf); buf = irc_format(irc, "vn", "NICK", gaim_connection_get_display_name(gc)); if (irc_send(irc, buf) < 0) { gaim_connection_error(gc, "Error sending nickname"); g_free(buf); - return; + return FALSE; } g_free(buf); - gc->inpa = gaim_input_add(irc->fd, GAIM_INPUT_READ, irc_input_cb, gc); + return TRUE; +} + +static void irc_login_cb_ssl(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + GaimConnection *gc = data; + struct irc_conn *irc = gc->proto_data; + + if(!g_list_find(gaim_connections_get_all(), gc)) { + gaim_ssl_close(gsc); + return; + } + + irc->gsc = gsc; + + if (do_login(gc)) { + gaim_ssl_input_add(gsc, irc_input_cb_ssl, gc); + } +} + +static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond) +{ + GaimConnection *gc = data; + struct irc_conn *irc = gc->proto_data; + GList *connections = gaim_connections_get_all(); + + if (source < 0) { + gaim_connection_error(gc, _("Couldn't connect to host")); + return; + } + + if (!g_list_find(connections, gc)) { + close(source); + return; + } + + irc->fd = source; + + if (do_login(gc)) { + gc->inpa = gaim_input_add(irc->fd, GAIM_INPUT_READ, irc_input_cb, gc); + } +} + +static void +irc_ssl_connect_failure(GaimSslConnection *gsc, GaimSslErrorType error, + gpointer data) +{ + GaimConnection *gc = data; + struct irc_conn *irc = gc->proto_data; + + switch(error) { + case GAIM_SSL_CONNECT_FAILED: + gaim_connection_error(gc, _("Connection Failed")); + break; + case GAIM_SSL_HANDSHAKE_FAILED: + gaim_connection_error(gc, _("SSL Handshake Failed")); + break; + } + + irc->gsc = NULL; } static void irc_close(GaimConnection *gc) @@ -314,7 +382,11 @@ gaim_input_remove(gc->inpa); g_free(irc->inbuf); - close(irc->fd); + if (irc->gsc) { + gaim_ssl_close(irc->gsc); + } else if (irc->fd > 0) { + close(irc->fd); + } if (irc->timer) gaim_timeout_remove(irc->timer); g_hash_table_destroy(irc->cmds); @@ -387,25 +459,9 @@ g_hash_table_remove(irc->buddies, buddy->name); } -static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond) +static void read_input(struct irc_conn *irc, int len) { - GaimConnection *gc = data; - struct irc_conn *irc = gc->proto_data; char *cur, *end; - int len; - - if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { - irc->inbuflen += IRC_INITIAL_BUFSIZE; - irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); - } - - if ((len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { - gaim_connection_error(gc, _("Read error")); - return; - } else if (len == 0) { - gaim_connection_error(gc, _("Server has disconnected")); - return; - } irc->inbufused += len; irc->inbuf[irc->inbufused] = '\0'; @@ -426,6 +482,57 @@ } } +static void irc_input_cb_ssl(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + + GaimConnection *gc = data; + struct irc_conn *irc = gc->proto_data; + int len; + + if(!g_list_find(gaim_connections_get_all(), gc)) { + gaim_ssl_close(gsc); + return; + } + + if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { + irc->inbuflen += IRC_INITIAL_BUFSIZE; + irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); + } + + if ((len = gaim_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { + gaim_connection_error(gc, _("Read error")); + return; + } else if (len == 0) { + gaim_connection_error(gc, _("Server has disconnected")); + return; + } + + read_input(irc, len); +} + +static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond) +{ + GaimConnection *gc = data; + struct irc_conn *irc = gc->proto_data; + int len; + + if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { + irc->inbuflen += IRC_INITIAL_BUFSIZE; + irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); + } + + if ((len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { + gaim_connection_error(gc, _("Read error")); + return; + } else if (len == 0) { + gaim_connection_error(gc, _("Server has disconnected")); + return; + } + + read_input(irc, len); +} + static void irc_chat_join (GaimConnection *gc, GHashTable *data) { struct irc_conn *irc = gc->proto_data; @@ -731,6 +838,9 @@ option = gaim_account_option_string_new(_("Real name"), "realname", ""); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + option = gaim_account_option_bool_new(_("Use SSL"), "ssl", FALSE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + _irc_plugin = plugin; gaim_prefs_add_none("/plugins/prpl/irc"); --- gaim-1.5.0/src/protocols/irc/irc.h.orig 2005-07-09 20:19:22.000000000 +0100 +++ gaim-1.5.0/src/protocols/irc/irc.h 2005-12-15 23:51:01.000000000 +0000 @@ -26,9 +26,11 @@ #include <glib.h> #include "roomlist.h" +#include "sslconn.h" #define IRC_DEFAULT_SERVER "irc.freenode.net" #define IRC_DEFAULT_PORT 6667 +#define IRC_DEFAULT_SSL_PORT 994 #define IRC_DEFAULT_CHARSET "UTF-8" #define IRC_DEFAULT_ALIAS "gaim" @@ -71,6 +73,7 @@ time_t signon; } whois; GaimRoomlist *roomlist; + GaimSslConnection *gsc; gboolean quitting; }; -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]