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]

Reply via email to