# HG changeset patch # User Eric Warmenhoven # Date 990360366 0 # Node ID a49ed23b3c02496e5c8cd3d52c6195aab3a59b79 # Parent b508cbbe9c48e271031ba4ee0a621c8e5a501740 [gaim-migrate @ 1878] proxy stuff. committer: Tailor Script diff -r b508cbbe9c48 -r a49ed23b3c02 ChangeLog --- a/ChangeLog Sun May 20 10:39:10 2001 +0000 +++ b/ChangeLog Sun May 20 12:06:06 2001 +0000 @@ -13,7 +13,7 @@ * MSN can now change your 'friendly name' (Thanks for the packet logs, aechols) * More IRC improvements [colors, etc] (Thanks Sean Egan) - * Improved proxy options for TOC, IRC, MSN, Jabber + * Improved proxy options for TOC, IRC, MSN, Jabber, Oscar * Fixed a small issue with HTML not being stripped from log files properly (Thanks, faceprint) diff -r b508cbbe9c48 -r a49ed23b3c02 src/oscar.c --- a/src/oscar.c Sun May 20 10:39:10 2001 +0000 +++ b/src/oscar.c Sun May 20 12:06:06 2001 +0000 @@ -41,6 +41,7 @@ #include "prpl.h" #include "gaim.h" #include "aim.h" +#include "proxy.h" /*#include "pixmaps/cancel.xpm"*/ #include "pixmaps/admin_icon.xpm" @@ -52,12 +53,15 @@ /* constants to identify proto_opts */ #define USEROPT_AUTH 0 #define USEROPT_AUTHPORT 1 -#define USEROPT_SOCKSHOST 2 -#define USEROPT_SOCKSPORT 3 +#define USEROPT_PROXYHOST 2 +#define USEROPT_PROXYPORT 3 +#define USEROPT_PROXYTYPE 4 +#define USEROPT_USER 5 +#define USEROPT_PASS 6 #define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3" -int gaim_caps = AIM_CAPS_CHAT | AIM_CAPS_GETFILE | AIM_CAPS_IMIMAGE; +static int gaim_caps = AIM_CAPS_CHAT | AIM_CAPS_GETFILE | AIM_CAPS_IMIMAGE; static GtkWidget *join_chat_spin = NULL; static GtkWidget *join_chat_entry = NULL; @@ -91,6 +95,8 @@ struct aim_conn_t *conn; int inpa; int id; + struct gaim_connection *gc; /* i hate this. */ + gpointer priv; /* don't ask. */ }; struct direct_im { @@ -404,11 +410,34 @@ g_free(s); } -void oscar_login(struct aim_user *user) { +static void oscar_login_connect(gpointer data, gint source, GdkInputCondition cond) +{ + struct gaim_connection *gc = data; + struct oscar_data *odata = gc->proto_data; + struct aim_session_t *sess = odata->sess; + struct aim_conn_t *conn = aim_getconn_type(sess, AIM_CONN_TYPE_AUTH); + + if (source < 0) { + hide_login_progress(gc, _("Couldn't connect to host")); + signoff(gc); + return; + } + + if (conn->fd != source) + conn->fd = source; + + aim_request_login(sess, conn, gc->username); + + gc->inpa = gdk_input_add(conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, + oscar_callback, conn); + + debug_printf(_("Password sent, waiting for response\n")); +} + +static void oscar_login(struct aim_user *user) { struct aim_session_t *sess; struct aim_conn_t *conn; char buf[256]; - char *finalauth = NULL; struct gaim_connection *gc = new_gaim_conn(user); struct oscar_data *odata = gc->proto_data = g_new0(struct oscar_data, 1); odata->create_exchange = 0; @@ -420,68 +449,43 @@ aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0); aim_setdebuggingcb(sess, oscar_debug); - if (user->proto_opt[USEROPT_SOCKSHOST][0]) { - char *finalproxy; - if (user->proto_opt[USEROPT_SOCKSPORT][0]) - finalproxy = g_strconcat(user->proto_opt[USEROPT_SOCKSHOST], ":", - user->proto_opt[USEROPT_SOCKSPORT], NULL); - else - finalproxy = g_strdup(user->proto_opt[USEROPT_SOCKSHOST]); - aim_setupproxy(sess, finalproxy, NULL, NULL); - g_free(finalproxy); - } - - if (user->proto_opt[USEROPT_AUTH][0]) { - if (user->proto_opt[USEROPT_AUTHPORT][0]) - finalauth = g_strconcat(user->proto_opt[USEROPT_AUTH], ":", - user->proto_opt[USEROPT_AUTHPORT], NULL); - else - finalauth = g_strdup(user->proto_opt[USEROPT_AUTH]); - } - /* we need an immediate queue because we don't use a while-loop to * see if things need to be sent. */ aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL); odata->sess = sess; sess->aux_data = gc; - conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, finalauth ? finalauth : FAIM_LOGIN_SERVER); - - if (finalauth) - g_free(finalauth); - + conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); if (conn == NULL) { debug_printf(_("internal connection error\n")); hide_login_progress(gc, _("Unable to login to AIM")); signoff(gc); return; - } else if (conn->fd == -1) { - if (conn->status & AIM_CONN_STATUS_RESOLVERR) { - char *crh = _("couldn't resolve host"); - debug_printf("%s\n", crh); - hide_login_progress(gc, crh); - } else if (conn->status & AIM_CONN_STATUS_CONNERR) { - char *cch = _("couldn't connect to host"); - debug_printf("%s\n", cch); - hide_login_progress(gc, cch); - } - signoff(gc); - return; } + g_snprintf(buf, sizeof(buf), _("Signon: %s"), gc->username); set_login_progress(gc, 2, buf); aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); - aim_request_login(sess, conn, gc->username); - - gc->inpa = gdk_input_add(conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, conn); - - debug_printf(_("Password sent, waiting for response\n")); + + conn->fd = proxy_connect(user->proto_opt[USEROPT_AUTH][0] ? + user->proto_opt[USEROPT_AUTH] : FAIM_LOGIN_SERVER, + user->proto_opt[USEROPT_AUTHPORT][0] ? + atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT, + user->proto_opt[USEROPT_PROXYHOST], + atoi(user->proto_opt[USEROPT_PROXYPORT]), + atoi(user->proto_opt[USEROPT_PROXYTYPE]), + user->proto_opt[USEROPT_USER], user->proto_opt[USEROPT_PASS], + oscar_login_connect, gc); + if (!user->gc || (conn->fd < 0)) { + hide_login_progress(gc, _("Couldn't connect to host")); + signoff(gc); + return; + } } -void oscar_close(struct gaim_connection *gc) { +static void oscar_close(struct gaim_connection *gc) { struct oscar_data *odata = (struct oscar_data *)gc->proto_data; GSList *c = odata->oscar_chats; struct chat_connection *n; @@ -510,6 +514,32 @@ debug_printf(_("Signed off.\n")); } +static void oscar_bos_connect(gpointer data, gint source, GdkInputCondition cond) { + struct gaim_connection *gc = data; + struct oscar_data *odata = gc->proto_data; + struct aim_session_t *sess = odata->sess; + struct aim_conn_t *bosconn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); + + if (source < 0) { + if (bosconn->priv) + g_free(bosconn->priv); + bosconn->priv = NULL; + hide_login_progress(gc, _("Could Not Connect")); + signoff(gc); + return; + } + + if (bosconn->fd != source) + bosconn->fd = source; + + aim_auth_sendcookie(sess, bosconn, bosconn->priv); + g_free(bosconn->priv); + bosconn->priv = NULL; + gc->inpa = gdk_input_add(bosconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, + oscar_callback, bosconn); + set_login_progress(gc, 4, _("Connection established, cookie sent")); +} + int gaim_parse_auth_resp(struct aim_session_t *sess, struct command_rx_struct *command, ...) { va_list ap; @@ -521,8 +551,11 @@ char *latestrelease = NULL, *latestbeta = NULL; char *latestreleaseurl = NULL, *latestbetaurl = NULL; char *latestreleaseinfo = NULL, *latestbetainfo = NULL; + int i; char *host; int port = FAIM_LOGIN_PORT; + struct aim_user *user; struct gaim_connection *gc = sess->aux_data; + user = gc->user; va_start(ap, command); sn = va_arg(ap, char *); @@ -593,15 +626,11 @@ gdk_input_remove(gc->inpa); aim_conn_kill(sess, &command->conn); - bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip); + bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL); if (bosconn == NULL) { hide_login_progress(gc, _("Internal Error")); signoff(gc); return -1; - } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) { - hide_login_progress(gc, _("Could Not Connect")); - signoff(gc); - return -1; } aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0); @@ -630,11 +659,30 @@ aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, gaim_parse_genericerr, 0); aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, gaim_memrequest, 0); - aim_auth_sendcookie(sess, bosconn, cookie); ((struct oscar_data *)gc->proto_data)->conn = bosconn; - gc->inpa = gdk_input_add(bosconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, bosconn); - set_login_progress(gc, 4, _("Connection established, cookie sent")); + for (i = 0; i < (int)strlen(bosip); i++) { + if (bosip[i] == ':') { + port = atoi(&(bosip[i+1])); + break; + } + } + host = g_strndup(bosip, i); + bosconn->priv = g_memdup(cookie, AIM_COOKIELEN); + bosconn->fd = proxy_connect(host, port, + gc->user->proto_opt[USEROPT_PROXYHOST], + atoi(gc->user->proto_opt[USEROPT_PROXYPORT]), + atoi(gc->user->proto_opt[USEROPT_PROXYTYPE]), + gc->user->proto_opt[USEROPT_USER], gc->user->proto_opt[USEROPT_PASS], + oscar_bos_connect, gc); + g_free(host); + if (!user->gc || (bosconn->fd < 0)) { + if (bosconn->priv) + g_free(bosconn->priv); + bosconn->priv = NULL; + hide_login_progress(gc, _("Could Not Connect")); + signoff(gc); + return -1; + } return 1; } @@ -643,41 +691,20 @@ unsigned long offset; unsigned long len; char *modname; + int fd; struct aim_conn_t *conn; - struct aim_conn_t *mainconn; unsigned int inpa; }; -void damn_you(gpointer data, gint source, GdkInputCondition c) +static void damn_you(gpointer data, gint source, GdkInputCondition c) { struct pieceofcrap *pos = data; struct oscar_data *od = pos->gc->proto_data; char in = '\0'; int x = 0; char m[17]; - if (c == GDK_INPUT_WRITE) { - char buf[BUF_LONG]; - if (aim_conn_completeconnect(od->sess, pos->conn) < 0) { - do_error_dialog("Gaim was unable to get a valid hash for logging into AIM." - " You may be disconnected shortly.", "Login Error"); - gdk_input_remove(pos->inpa); - close(pos->conn->fd); - aim_conn_kill(od->sess, &pos->conn); - g_free(pos); - return; - } - g_snprintf(buf, sizeof(buf), "GET " AIMHASHDATA - "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n", - pos->offset, pos->len, pos->modname ? pos->modname : ""); - write(pos->conn->fd, buf, strlen(buf)); - if (pos->modname) - g_free(pos->modname); - gdk_input_remove(pos->inpa); - pos->inpa = gdk_input_add(pos->conn->fd, GDK_INPUT_READ, damn_you, pos); - return; - } - - while (read(pos->conn->fd, &in, 1) == 1) { + + while (read(pos->fd, &in, 1) == 1) { if (in == '\n') x++; else if (in != '\r') @@ -690,33 +717,59 @@ do_error_dialog("Gaim was unable to get a valid hash for logging into AIM." " You may be disconnected shortly.", "Login Error"); gdk_input_remove(pos->inpa); - close(pos->conn->fd); - aim_conn_kill(od->sess, &pos->conn); + close(pos->fd); g_free(pos); return; } - read(pos->conn->fd, m, 16); + read(pos->fd, m, 16); m[16] = '\0'; debug_printf("Sending hash: "); for (x = 0; x < 16; x++) debug_printf("%02x ", (unsigned char)m[x]); debug_printf("\n"); gdk_input_remove(pos->inpa); - close(pos->conn->fd); - aim_conn_kill(od->sess, &pos->conn); - aim_sendmemblock(od->sess, pos->mainconn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); + close(pos->fd); + aim_sendmemblock(od->sess, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); g_free(pos); } +static void straight_to_hell(gpointer data, gint source, GdkInputCondition cond) { + struct pieceofcrap *pos = data; + char buf[BUF_LONG]; + + if (source < 0) { + do_error_dialog("Gaim was unable to get a valid hash for logging into AIM." + " You may be disconnected shortly.", "Login Error"); + if (pos->modname) + g_free(pos->modname); + g_free(pos); + return; + } + + if (pos->fd != source) + pos->fd = source; + + g_snprintf(buf, sizeof(buf), "GET " AIMHASHDATA + "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n", + pos->offset, pos->len, pos->modname ? pos->modname : ""); + write(pos->fd, buf, strlen(buf)); + if (pos->modname) + g_free(pos->modname); + pos->inpa = gdk_input_add(pos->fd, GDK_INPUT_READ, damn_you, pos); + return; +} + /* size of icbmui.ocm, the largest module in AIM 3.5 */ #define AIM_MAX_FILE_SIZE 98304 int gaim_memrequest(struct aim_session_t *sess, struct command_rx_struct *command, ...) { + struct gaim_connection *gc = sess->aux_data; va_list ap; struct pieceofcrap *pos; unsigned long offset, len; char *modname; + int fd; va_start(ap, command); offset = va_arg(ap, unsigned long); @@ -724,6 +777,7 @@ modname = va_arg(ap, char *); va_end(ap); + debug_printf("offset: %d, len: %d, file: %s\n", offset, len, modname ? modname : "aim.exe"); if (len == 0) { debug_printf("len is 0, hashing NULL\n"); aim_sendmemblock(sess, command->conn, offset, len, NULL, @@ -759,14 +813,26 @@ pos = g_new0(struct pieceofcrap, 1); pos->gc = sess->aux_data; - pos->mainconn = command->conn; + pos->conn = command->conn; pos->offset = offset; pos->len = len; pos->modname = modname ? g_strdup(modname) : NULL; - pos->conn = aim_newconn(sess, 0, "gaim.sourceforge.net:80"); - pos->inpa = gdk_input_add(pos->conn->fd, GDK_INPUT_WRITE, damn_you, pos); + fd = proxy_connect("gaim.sourceforge.net", 80, + gc->user->proto_opt[USEROPT_PROXYHOST], + atoi(gc->user->proto_opt[USEROPT_PROXYPORT]), + atoi(gc->user->proto_opt[USEROPT_PROXYTYPE]), + gc->user->proto_opt[USEROPT_USER], gc->user->proto_opt[USEROPT_PASS], + straight_to_hell, pos); + if (fd < 0) { + if (pos->modname) + g_free(pos->modname); + g_free(pos); + do_error_dialog("Gaim was unable to get a valid hash for logging into AIM." + " You may be disconnected shortly.", "Login Error"); + } + pos->fd = fd; return 1; } @@ -864,6 +930,85 @@ return 1; } +static void oscar_chatnav_connect(gpointer data, gint source, GdkInputCondition cond) +{ + struct gaim_connection *gc = data; + struct oscar_data *odata = gc->proto_data; + struct aim_session_t *sess = odata->sess; + struct aim_conn_t *tstconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV); + + if (source < 0) { + if (tstconn->priv) + g_free(tstconn->priv); + tstconn->priv = NULL; + aim_conn_kill(sess, &tstconn); + debug_printf("unable to connect to chatnav server\n"); + return; + } + + if (tstconn->fd != source) + tstconn->fd = source; + + aim_auth_sendcookie(sess, tstconn, tstconn->priv); + g_free(tstconn->priv); + odata->cnpa = gdk_input_add(tstconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, + oscar_callback, tstconn); + debug_printf("chatnav: connected\n"); +} + +static void oscar_auth_connect(gpointer data, gint source, GdkInputCondition cond) +{ + struct gaim_connection *gc = data; + struct oscar_data *odata = gc->proto_data; + struct aim_session_t *sess = odata->sess; + struct aim_conn_t *tstconn = aim_getconn_type(sess, AIM_CONN_TYPE_AUTH); + + if (source < 0) { + if (tstconn->priv) + g_free(tstconn->priv); + tstconn->priv = NULL; + aim_conn_kill(sess, &tstconn); + debug_printf("unable to connect to authorizer\n"); + return; + } + + if (tstconn->fd != source) + tstconn->fd = source; + + aim_auth_sendcookie(sess, tstconn, tstconn->priv); + g_free(tstconn->priv); + odata->cnpa = gdk_input_add(tstconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, + oscar_callback, tstconn); + debug_printf("chatnav: connected\n"); +} + +static void oscar_chat_connect(gpointer data, gint source, GdkInputCondition cond) +{ + struct chat_connection *ccon = data; + struct gaim_connection *gc = ccon->gc; + struct oscar_data *odata = gc->proto_data; + struct aim_session_t *sess = odata->sess; + struct aim_conn_t *tstconn = ccon->conn; + + if (source < 0) { + aim_conn_kill(sess, &tstconn); + g_free(ccon->priv); + g_free(ccon->show); + g_free(ccon->name); + g_free(ccon); + } + + if (ccon->fd != source) + ccon->fd = tstconn->fd = source; + + ccon->inpa = gdk_input_add(tstconn->fd, + GDK_INPUT_READ | GDK_INPUT_EXCEPTION, + oscar_callback, tstconn); + odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon); + aim_chat_attachname(tstconn, ccon->name); + aim_auth_sendcookie(sess, tstconn, ccon->priv); + g_free(ccon->priv); +} int gaim_handle_redirect(struct aim_session_t *sess, struct command_rx_struct *command, ...) { va_list ap; @@ -871,75 +1016,119 @@ char *ip; unsigned char *cookie; struct gaim_connection *gc = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + struct aim_user *user = gc->user; + struct aim_conn_t *tstconn; + int i; + char *host; int port = FAIM_LOGIN_PORT, fd; va_start(ap, command); serviceid = va_arg(ap, int); ip = va_arg(ap, char *); cookie = va_arg(ap, unsigned char *); + for (i = 0; i < (int)strlen(ip); i++) { + if (ip[i] == ':') { + port = atoi(&(ip[i+1])); + break; + } + } + host = g_strndup(ip, i); + switch(serviceid) { case 0x7: /* Authorizer */ debug_printf("Reconnecting with authorizor...\n"); - { - struct aim_conn_t *tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip); - if (tstconn == NULL || tstconn->status & AIM_CONN_STATUS_RESOLVERR) + tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); + if (tstconn == NULL) { debug_printf("unable to reconnect with authorizer\n"); - else { - aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); - aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, gaim_rateresp, 0); - aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, gaim_info_change, 0); - aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, gaim_info_change, 0); - aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0); - odata->paspa = gdk_input_add(tstconn->fd, - GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, tstconn); - aim_auth_sendcookie(sess, tstconn, cookie); - } - } - break; - case 0xd: /* ChatNav */ - { - struct aim_conn_t *tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip); - if (tstconn == NULL || tstconn->status & AIM_CONN_STATUS_RESOLVERR) { - debug_printf("unable to connect to chatnav server\n"); + g_free(host); return 1; } aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); - aim_auth_sendcookie(sess, tstconn, cookie); - odata->cnpa = gdk_input_add(tstconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, tstconn); + aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, gaim_rateresp, 0); + aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, gaim_info_change, 0); + aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, gaim_info_change, 0); + aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0); + + tstconn->priv = g_memdup(cookie, AIM_COOKIELEN); + fd = proxy_connect(host, port, user->proto_opt[USEROPT_PROXYHOST], + atoi(user->proto_opt[USEROPT_PROXYPORT]), + atoi(user->proto_opt[USEROPT_PROXYTYPE]), + user->proto_opt[USEROPT_USER], user->proto_opt[USEROPT_PASS], + oscar_auth_connect, gc); + if (fd < 0) { + if (tstconn->priv) + g_free(tstconn->priv); + aim_conn_kill(sess, &tstconn); + debug_printf("unable to reconnect with authorizer\n"); + g_free(host); + return 1; } - debug_printf("chatnav: connected\n"); + tstconn->fd = fd; + break; + case 0xd: /* ChatNav */ + tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, NULL); + if (tstconn == NULL) { + debug_printf("unable to connect to chatnav server\n"); + g_free(host); + return 1; + } + aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); + + tstconn->priv = g_memdup(cookie, AIM_COOKIELEN); + fd = proxy_connect(host, port, user->proto_opt[USEROPT_PROXYHOST], + atoi(user->proto_opt[USEROPT_PROXYPORT]), + atoi(user->proto_opt[USEROPT_PROXYTYPE]), + user->proto_opt[USEROPT_USER], user->proto_opt[USEROPT_PASS], + oscar_chatnav_connect, gc); + if (fd < 0) { + if (tstconn->priv) + g_free(tstconn->priv); + aim_conn_kill(sess, &tstconn); + debug_printf("unable to connect to chatnav server\n"); + g_free(host); + return 1; + } + tstconn->fd = fd; break; case 0xe: /* Chat */ { - struct aim_conn_t *tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip); char *roomname = va_arg(ap, char *); int exchange = va_arg(ap, int); struct chat_connection *ccon; - if (tstconn == NULL || tstconn->status & AIM_CONN_STATUS_RESOLVERR) { + tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, NULL); + if (tstconn == NULL) { debug_printf("unable to connect to chat server\n"); + g_free(host); return 1; } - debug_printf("Connected to chat room %s exchange %d\n", roomname, exchange); - + + aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); ccon = g_new0(struct chat_connection, 1); ccon->conn = tstconn; - ccon->fd = tstconn->fd; + ccon->gc = gc; + ccon->fd = -1; ccon->name = g_strdup(roomname); ccon->exchange = exchange; ccon->show = extract_name(roomname); - ccon->inpa = gdk_input_add(tstconn->fd, - GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, tstconn); - - odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon); - - aim_chat_attachname(tstconn, roomname); - aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); - aim_auth_sendcookie(sess, tstconn, cookie); + ccon->priv = g_memdup(cookie, AIM_COOKIELEN); + fd = proxy_connect(host, port, user->proto_opt[USEROPT_PROXYHOST], + atoi(user->proto_opt[USEROPT_PROXYPORT]), + atoi(user->proto_opt[USEROPT_PROXYTYPE]), + user->proto_opt[USEROPT_USER], user->proto_opt[USEROPT_PASS], + oscar_chat_connect, ccon); + if (fd < 0) { + aim_conn_kill(sess, &tstconn); + debug_printf("unable to connect to chat server\n"); + g_free(host); + g_free(ccon->priv); + g_free(ccon->show); + g_free(ccon->name); + g_free(ccon); + return 1; + } + ccon->fd = tstconn->fd = fd; + debug_printf("Connected to chat room %s exchange %d\n", roomname, exchange); } break; default: /* huh? */ @@ -949,6 +1138,7 @@ va_end(ap); + g_free(host); return 1; } @@ -1024,6 +1214,15 @@ struct oscar_data *od = gc->proto_data; char buf[256]; + if (source < 0) { + od->direct_ims = g_slist_remove(od->direct_ims, dim); + g_free(dim); + return; + } + + if (dim->conn->fd != source) + dim->conn->fd = source; + if (!(dim->cnv = find_conversation(dim->name))) dim->cnv = new_conversation(dim->name); g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name); write_to_conv(dim->cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); @@ -1031,14 +1230,6 @@ gtk_signal_connect(GTK_OBJECT(dim->cnv->window), "destroy", GTK_SIGNAL_FUNC(delete_direct_im), dim); - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, - gaim_directim_incoming, 0); - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, - gaim_directim_disconnect, 0); - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, - gaim_directim_typing, 0); - - gdk_input_remove(dim->watcher); dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, oscar_callback, dim->conn); } @@ -1047,6 +1238,8 @@ struct gaim_connection *gc = d->gc; struct oscar_data *od = (struct oscar_data *)gc->proto_data; struct direct_im *dim; + char *host; int port = FAIM_LOGIN_PORT; + int i; debug_printf("Accepted DirectIM.\n"); @@ -1059,8 +1252,37 @@ dim->gc = d->gc; g_snprintf(dim->name, sizeof dim->name, "%s", d->sn); - if ((dim->conn = aim_directim_connect(od->sess, od->conn, d->priv)) == NULL) { - od->sess->flags ^= AIM_SESS_FLAGS_NONBLOCKCONNECT; + if ((dim->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL)) == NULL) { + g_free(dim); + cancel_direct_im(w, d); + return TRUE; + } + dim->conn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; + dim->conn->priv = d->priv; + aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, + gaim_directim_incoming, 0); + aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, + gaim_directim_disconnect, 0); + aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, + gaim_directim_typing, 0); + + for (i = 0; i < (int)strlen(d->priv->ip); i++) { + if (d->priv->ip[i] == ':') { + port = atoi(&(d->priv->ip[i+1])); + break; + } + } + host = g_strndup(d->priv->ip, i); + dim->conn->fd = proxy_connect(host, port, + gc->user->proto_opt[USEROPT_PROXYHOST], + atoi(gc->user->proto_opt[USEROPT_PROXYPORT]), + atoi(gc->user->proto_opt[USEROPT_PROXYTYPE]), + gc->user->proto_opt[USEROPT_USER], + gc->user->proto_opt[USEROPT_PASS], + oscar_directim_callback, dim); + g_free(host); + if (dim->conn->fd < 0) { + aim_conn_kill(od->sess, &dim->conn); g_free(dim); cancel_direct_im(w, d); return TRUE; @@ -1068,8 +1290,6 @@ od->direct_ims = g_slist_append(od->direct_ims, dim); - dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_WRITE, oscar_directim_callback, dim); - cancel_direct_im(w, d); return TRUE; @@ -2538,56 +2758,69 @@ /* weeee */ -static void oscar_print_option(GtkEntry *entry, struct aim_user *user) { - int entrynum; - - entrynum = (int) gtk_object_get_user_data(GTK_OBJECT(entry)); - +static void oscar_print_option(GtkEntry *entry, struct aim_user *user) +{ + int entrynum; + + entrynum = (int)gtk_object_get_user_data(GTK_OBJECT(entry)); + if (entrynum == USEROPT_AUTH) { g_snprintf(user->proto_opt[USEROPT_AUTH], - sizeof(user->proto_opt[USEROPT_AUTH]), - "%s", gtk_entry_get_text(entry)); + sizeof(user->proto_opt[USEROPT_AUTH]), "%s", gtk_entry_get_text(entry)); } else if (entrynum == USEROPT_AUTHPORT) { - g_snprintf(user->proto_opt[USEROPT_AUTHPORT], - sizeof(user->proto_opt[USEROPT_AUTHPORT]), - "%s", gtk_entry_get_text(entry)); - } else if (entrynum == USEROPT_SOCKSHOST) { - g_snprintf(user->proto_opt[USEROPT_SOCKSHOST], - sizeof(user->proto_opt[USEROPT_SOCKSHOST]), - "%s", gtk_entry_get_text(entry)); - } else if (entrynum == USEROPT_SOCKSPORT) { - g_snprintf(user->proto_opt[USEROPT_SOCKSPORT], - sizeof(user->proto_opt[USEROPT_SOCKSPORT]), - "%s", gtk_entry_get_text(entry)); - } + g_snprintf(user->proto_opt[USEROPT_AUTHPORT], + sizeof(user->proto_opt[USEROPT_AUTHPORT]), "%s", gtk_entry_get_text(entry)); + } else if (entrynum == USEROPT_PROXYHOST) { + g_snprintf(user->proto_opt[USEROPT_PROXYHOST], + sizeof(user->proto_opt[USEROPT_PROXYHOST]), "%s", gtk_entry_get_text(entry)); + } else if (entrynum == USEROPT_PROXYPORT) { + g_snprintf(user->proto_opt[USEROPT_PROXYPORT], + sizeof(user->proto_opt[USEROPT_PROXYPORT]), "%s", gtk_entry_get_text(entry)); + } else if (entrynum == USEROPT_USER) { + g_snprintf(user->proto_opt[USEROPT_USER], + sizeof(user->proto_opt[USEROPT_USER]), "%s", gtk_entry_get_text(entry)); + } else if (entrynum == USEROPT_PASS) { + g_snprintf(user->proto_opt[USEROPT_PASS], + sizeof(user->proto_opt[USEROPT_PASS]), "%s", gtk_entry_get_text(entry)); + } } -static void oscar_user_opts(GtkWidget *book, struct aim_user *user) { +static void oscar_print_optionrad(GtkRadioButton * entry, struct aim_user *user) +{ + int entrynum; + + entrynum = (int)gtk_object_get_user_data(GTK_OBJECT(entry)); + + g_snprintf(user->proto_opt[USEROPT_PROXYTYPE], + sizeof(user->proto_opt[USEROPT_PROXYTYPE]), "%d", entrynum); +} + +static void oscar_user_opts(GtkWidget *book, struct aim_user *user) +{ /* so here, we create the new notebook page */ GtkWidget *vbox; GtkWidget *hbox; GtkWidget *label; GtkWidget *entry; + GtkWidget *first, *opt; vbox = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_notebook_append_page(GTK_NOTEBOOK(book), vbox, - gtk_label_new("OSCAR Options")); + gtk_notebook_append_page(GTK_NOTEBOOK(book), vbox, gtk_label_new("Oscar Options")); gtk_widget_show(vbox); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); - label = gtk_label_new("Authorizer:"); + label = gtk_label_new("Auth Host:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_AUTH); - gtk_signal_connect(GTK_OBJECT(entry), "changed", - GTK_SIGNAL_FUNC(oscar_print_option), user); + gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user); if (user->proto_opt[USEROPT_AUTH][0]) { debug_printf("setting text %s\n", user->proto_opt[USEROPT_AUTH]); gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_AUTH]); @@ -2595,42 +2828,119 @@ gtk_entry_set_text(GTK_ENTRY(entry), "login.oscar.aol.com"); gtk_widget_show(entry); - hbox = gtk_hbox_new(FALSE, 5); + hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); - label = gtk_label_new("Authorizer Port:"); + label = gtk_label_new("Auth Port:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); - gtk_object_set_user_data(GTK_OBJECT(entry), (void *)1); - gtk_signal_connect(GTK_OBJECT(entry), "changed", - GTK_SIGNAL_FUNC(oscar_print_option), user); + gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_AUTHPORT); + gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user); if (user->proto_opt[USEROPT_AUTHPORT][0]) { debug_printf("setting text %s\n", user->proto_opt[USEROPT_AUTHPORT]); gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_AUTHPORT]); } else - gtk_entry_set_text(GTK_ENTRY(entry), "5190"); + gtk_entry_set_text(GTK_ENTRY(entry), "9898"); + gtk_widget_show(entry); - hbox = gtk_hbox_new(FALSE, 5); + hbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); - label = gtk_label_new("SOCKS5 Host:"); + first = gtk_radio_button_new_with_label(NULL, "No proxy"); + gtk_box_pack_start(GTK_BOX(hbox), first, FALSE, FALSE, 0); + gtk_object_set_user_data(GTK_OBJECT(first), (void *)PROXY_NONE); + gtk_signal_connect(GTK_OBJECT(first), "clicked", GTK_SIGNAL_FUNC(oscar_print_optionrad), user); + gtk_widget_show(first); + if (atoi(user->proto_opt[USEROPT_PROXYTYPE]) == PROXY_NONE) + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(first), TRUE); + + opt = + gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(first)), "SOCKS 4"); + gtk_box_pack_start(GTK_BOX(hbox), opt, FALSE, FALSE, 0); + gtk_object_set_user_data(GTK_OBJECT(opt), (void *)PROXY_SOCKS4); + gtk_signal_connect(GTK_OBJECT(opt), "clicked", GTK_SIGNAL_FUNC(oscar_print_optionrad), user); + gtk_widget_show(opt); + if (atoi(user->proto_opt[USEROPT_PROXYTYPE]) == PROXY_SOCKS4) + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(opt), TRUE); + + hbox = gtk_hbox_new(TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show(hbox); + + opt = + gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(first)), "SOCKS 5"); + gtk_box_pack_start(GTK_BOX(hbox), opt, FALSE, FALSE, 0); + gtk_object_set_user_data(GTK_OBJECT(opt), (void *)PROXY_SOCKS5); + gtk_signal_connect(GTK_OBJECT(opt), "clicked", GTK_SIGNAL_FUNC(oscar_print_optionrad), user); + gtk_widget_show(opt); + if (atoi(user->proto_opt[USEROPT_PROXYTYPE]) == PROXY_SOCKS5) + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(opt), TRUE); + + opt = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(first)), "HTTP"); + gtk_box_pack_start(GTK_BOX(hbox), opt, FALSE, FALSE, 0); + gtk_object_set_user_data(GTK_OBJECT(opt), (void *)PROXY_HTTP); + gtk_signal_connect(GTK_OBJECT(opt), "clicked", GTK_SIGNAL_FUNC(oscar_print_optionrad), user); + gtk_widget_show(opt); + if (atoi(user->proto_opt[USEROPT_PROXYTYPE]) == PROXY_HTTP) + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(opt), TRUE); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show(hbox); + + label = gtk_label_new("Proxy Host:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); - gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_SOCKSHOST); - gtk_signal_connect(GTK_OBJECT(entry), "changed", - GTK_SIGNAL_FUNC(oscar_print_option), user); - if (user->proto_opt[USEROPT_SOCKSHOST][0]) { - debug_printf("setting text %s\n", user->proto_opt[USEROPT_SOCKSHOST]); - gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_SOCKSHOST]); + gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_PROXYHOST); + gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user); + if (user->proto_opt[USEROPT_PROXYHOST][0]) { + debug_printf("setting text %s\n", user->proto_opt[USEROPT_PROXYHOST]); + gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_PROXYHOST]); + } + gtk_widget_show(entry); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show(hbox); + + label = gtk_label_new("Proxy Port:"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_widget_show(label); + + entry = gtk_entry_new(); + gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); + gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_PROXYPORT); + gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user); + if (user->proto_opt[USEROPT_PROXYPORT][0]) { + debug_printf("setting text %s\n", user->proto_opt[USEROPT_PROXYPORT]); + gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_PROXYPORT]); + } + gtk_widget_show(entry); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show(hbox); + + label = gtk_label_new("Proxy User:"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_widget_show(label); + + entry = gtk_entry_new(); + gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); + gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_USER); + gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user); + if (user->proto_opt[USEROPT_USER][0]) { + debug_printf("setting text %s\n", user->proto_opt[USEROPT_USER]); + gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_USER]); } gtk_widget_show(entry); @@ -2638,18 +2948,18 @@ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); - label = gtk_label_new("SOCKS5 Port:"); + label = gtk_label_new("Proxy Password:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); - gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_SOCKSPORT); - gtk_signal_connect(GTK_OBJECT(entry), "changed", - GTK_SIGNAL_FUNC(oscar_print_option), user); - if (user->proto_opt[USEROPT_SOCKSPORT][0]) { - debug_printf("setting text %s\n", user->proto_opt[USEROPT_SOCKSPORT]); - gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_SOCKSPORT]); + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_PASS); + gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user); + if (user->proto_opt[USEROPT_PASS][0]) { + debug_printf("setting text %s\n", user->proto_opt[USEROPT_PASS]); + gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_PASS]); } gtk_widget_show(entry); } diff -r b508cbbe9c48 -r a49ed23b3c02 src/proxy.c --- a/src/proxy.c Sun May 20 10:39:10 2001 +0000 +++ b/src/proxy.c Sun May 20 12:06:06 2001 +0000 @@ -69,6 +69,17 @@ g_free(phb); } +static gboolean clean_connect(gpointer data) +{ + struct PHB *phb = data; + + phb->func(phb->data, phb->port, GDK_INPUT_READ); + g_free(phb); + + return FALSE; +} + + static int proxy_connect_none(char *host, unsigned short port, struct PHB *phb) { struct sockaddr_in sin; @@ -112,8 +123,10 @@ return -1; } fcntl(fd, F_SETFL, 0); - phb->func(phb->data, fd, GDK_INPUT_READ); - g_free(phb); + phb->port = fd; /* bleh */ + gtk_timeout_add(50, clean_connect, phb); /* we do this because we never + want to call our callback + before we return. */ } return fd;