Mercurial > pidgin
changeset 2088:68d316573162
[gaim-migrate @ 2098]
forgot to do this earlier.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Tue, 31 Jul 2001 18:01:55 +0000 |
parents | cf68ddc50ba2 |
children | bb1ddaaf0d26 |
files | src/oscar.c src/toc.c |
diffstat | 2 files changed, 0 insertions(+), 5143 deletions(-) [+] |
line wrap: on
line diff
--- a/src/oscar.c Tue Jul 31 01:58:50 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3302 +0,0 @@ -/* - * gaim - * - * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net> - * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include "../config.h" -#endif - - -#include <netdb.h> -#include <gtk/gtk.h> -#include <unistd.h> -#include <errno.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <time.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include "multi.h" -#include "prpl.h" -#include "gaim.h" -#include "aim.h" -#include "proxy.h" - -#if USE_PIXBUF -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gdk-pixbuf/gdk-pixbuf-loader.h> -#endif - -/*#include "pixmaps/cancel.xpm"*/ -#include "pixmaps/admin_icon.xpm" -#include "pixmaps/aol_icon.xpm" -#include "pixmaps/away_icon.xpm" -#include "pixmaps/dt_icon.xpm" -#include "pixmaps/free_icon.xpm" - -/* constants to identify proto_opts */ -#define USEROPT_AUTH 0 -#define USEROPT_AUTHPORT 1 - -#define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3" - -static int gaim_caps = AIM_CAPS_CHAT | -#if USE_PIXBUF - AIM_CAPS_BUDDYICON | -#endif - AIM_CAPS_GETFILE | - AIM_CAPS_IMIMAGE; - -static GtkWidget *join_chat_spin = NULL; -static GtkWidget *join_chat_entry = NULL; - -struct oscar_data { - struct aim_session_t *sess; - struct aim_conn_t *conn; - - guint cnpa; - guint paspa; - - int create_exchange; - char *create_name; - - gboolean conf; - gboolean reqemail; - gboolean chpass; - char *oldp; - char *newp; - - GSList *oscar_chats; - GSList *direct_ims; - GSList *getfiles; - GSList *hasicons; - - gboolean killme; -}; - -struct chat_connection { - char *name; - char *show; /* AOL did something funny to us */ - int exchange; - int fd; /* this is redundant since we have the conn below */ - struct aim_conn_t *conn; - int inpa; - int id; - struct gaim_connection *gc; /* i hate this. */ - struct conversation *cnv; /* bah. */ -}; - -struct direct_im { - struct gaim_connection *gc; - char name[80]; - struct conversation *cnv; - int watcher; - struct aim_conn_t *conn; -}; - -struct ask_direct { - struct gaim_connection *gc; - char *sn; - struct aim_directim_priv *priv; -}; - -struct ask_getfile { - struct gaim_connection *gc; - char *sn; - char *cookie; - char *ip; -}; - -struct getfile_transfer { - struct gaim_connection *gc; - char *receiver; - char *filename; - struct aim_conn_t *conn; - struct aim_fileheader_t *fh; - int gip; - int gop; - FILE *listing; - FILE *file; - GtkWidget *window; - GtkWidget *meter; - GtkWidget *label; - long pos; - long size; -}; - -#if USE_PIXBUF -struct icon_req { - char *user; - time_t timestamp; - unsigned long length; - gpointer data; - gboolean request; - GdkPixbufAnimation *anim; - GdkPixbuf *unanim; - struct conversation *cnv; - GtkWidget *pix; - int curframe; - int timer; -}; -#endif - -static struct direct_im *find_direct_im(struct oscar_data *od, char *who) { - GSList *d = od->direct_ims; - char *n = g_strdup(normalize(who)); - struct direct_im *m = NULL; - - while (d) { - m = (struct direct_im *)d->data; - if (!strcmp(n, normalize(m->name))) - break; - m = NULL; - d = d->next; - } - - g_free(n); - return m; -} - -/* -static struct getfile_transfer *find_getfile_transfer(struct oscar_data *od, struct aim_conn_t *conn) { - GSList *g = od->getfiles; - struct getfile_transfer *n = NULL; - - while (g) { - n = (struct getfile_transfer *)g->data; - if (n->conn == conn) - return n; - n = NULL; - g = g->next; - } - - return n; -} -*/ - -static char *extract_name(char *name) { - char *tmp; - int i, j; - char *x = strchr(name, '-'); - if (!x) return NULL; - x = strchr(++x, '-'); - if (!x) return NULL; - tmp = g_strdup(++x); - - for (i = 0, j = 0; x[i]; i++) { - if (x[i] != '%') - tmp[j++] = x[i]; - else { - char hex[3]; - hex[0] = x[++i]; - hex[1] = x[++i]; - hex[2] = 0; - sscanf(hex, "%x", (int *)&tmp[j++]); - } - } - - tmp[j] = 0; - return tmp; -} - -static struct chat_connection *find_oscar_chat(struct gaim_connection *gc, int id) { - GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; - struct chat_connection *c = NULL; - if (gc->protocol != PROTO_OSCAR) return NULL; - - while (g) { - c = (struct chat_connection *)g->data; - if (c->id == id) - break; - g = g->next; - c = NULL; - } - - return c; -} - -static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc, - struct aim_conn_t *conn) { - GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; - struct chat_connection *c = NULL; - - while (g) { - c = (struct chat_connection *)g->data; - if (c->conn == conn) - break; - g = g->next; - c = NULL; - } - - return c; -} - -static int gaim_parse_auth_resp (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_login (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_server_ready (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_handle_redirect (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_info_change (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_account_confirm (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_oncoming (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_offgoing (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_misses (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_user_info (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_motd (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_chatnav_info (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_chat_join (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_chat_leave (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_chat_info_update (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_chat_incoming_msg(struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_msgack (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_ratechange (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_evilnotify (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_searcherror(struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_searchreply(struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_bosrights (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_rateresp (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_reportinterval (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_msgerr (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_buddyrights(struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_locerr (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_parse_genericerr (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_memrequest (struct aim_session_t *, struct command_rx_struct *, ...); - -static int gaim_directim_initiate (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_directim_incoming (struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_directim_disconnect(struct aim_session_t *, struct command_rx_struct *, ...); -static int gaim_directim_typing (struct aim_session_t *, struct command_rx_struct *, ...); - -static char *msgerrreason[] = { - "Invalid error", - "Invalid SNAC", - "Rate to host", - "Rate to client", - "Not logged in", - "Service unavailable", - "Service not defined", - "Obsolete SNAC", - "Not supported by host", - "Not supported by client", - "Refused by client", - "Reply too big", - "Responses lost", - "Request denied", - "Busted SNAC payload", - "Insufficient rights", - "In local permit/deny", - "Too evil (sender)", - "Too evil (receiver)", - "User temporarily unavailable", - "No match", - "List overflow", - "Request ambiguous", - "Queue full", - "Not while on AOL" -}; -static int msgerrreasonlen = 25; - -static void oscar_callback(gpointer data, gint source, - GdkInputCondition condition) { - struct aim_conn_t *conn = (struct aim_conn_t *)data; - struct aim_session_t *sess = aim_conn_getsess(conn); - struct gaim_connection *gc = sess ? sess->aux_data : NULL; - struct oscar_data *odata; - - if (!gc) { - /* gc is null. we return, else we seg SIGSEG on next line. */ - debug_printf("oscar callback for closed connection (1).\n"); - return; - } - - odata = (struct oscar_data *)gc->proto_data; - - if (!g_slist_find(connections, gc)) { - /* oh boy. this is probably bad. i guess the only thing we - * can really do is return? */ - debug_printf("oscar callback for closed connection (2).\n"); - return; - } - - if (condition & GDK_INPUT_EXCEPTION) { - hide_login_progress(gc, _("Disconnected.")); - signoff(gc); - return; - } - if (condition & GDK_INPUT_READ) { - if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) { - debug_printf("got information on rendezvous\n"); - if (aim_handlerendconnect(odata->sess, conn) < 0) { - debug_printf(_("connection error (rend)\n")); - } - } else { - if (aim_get_command(odata->sess, conn) >= 0) { - aim_rxdispatch(odata->sess); - if (odata->killme) - signoff(gc); - } else { - if ((conn->type == AIM_CONN_TYPE_BOS) || - !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) { - debug_printf(_("major connection error\n")); - hide_login_progress(gc, _("Disconnected.")); - signoff(gc); - } else if (conn->type == AIM_CONN_TYPE_CHAT) { - struct chat_connection *c = find_oscar_chat_by_conn(gc, conn); - char buf[BUF_LONG]; - debug_printf("disconnected from chat room %s\n", c->name); - c->conn = NULL; - if (c->inpa > 0) - gdk_input_remove(c->inpa); - c->inpa = 0; - c->fd = -1; - aim_conn_kill(odata->sess, &conn); - sprintf(buf, _("You have been disconnected from chat room %s."), c->name); - do_error_dialog(buf, _("Chat Error!")); - } else if (conn->type == AIM_CONN_TYPE_CHATNAV) { - if (odata->cnpa > 0) - gdk_input_remove(odata->cnpa); - odata->cnpa = 0; - debug_printf("removing chatnav input watcher\n"); - if (odata->create_exchange) { - odata->create_exchange = 0; - g_free(odata->create_name); - odata->create_name = NULL; - do_error_dialog(_("Chat is currently unavailable"), - _("Gaim - Chat")); - } - aim_conn_kill(odata->sess, &conn); - } else if (conn->type == AIM_CONN_TYPE_AUTH) { - if (odata->paspa > 0) - gdk_input_remove(odata->paspa); - odata->paspa = 0; - debug_printf("removing authconn input watcher\n"); - aim_conn_kill(odata->sess, &conn); - } else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) { - debug_printf("No handler for rendezvous disconnect (%d).\n", - source); - aim_conn_kill(odata->sess, &conn); - } else { - debug_printf("holy crap! generic connection error! %d\n", - conn->type); - aim_conn_kill(odata->sess, &conn); - } - } - } - } -} - -static void oscar_debug(struct aim_session_t *sess, int level, const char *format, va_list va) { - char *s = g_strdup_vprintf(format, va); - char buf[256]; - char *t; - struct gaim_connection *gc = sess->aux_data; - - g_snprintf(buf, sizeof(buf), "%s %d: ", gc->username, level); - t = g_strconcat(buf, s, NULL); - debug_printf(t); - if (t[strlen(t)-1] != '\n') - debug_printf("\n"); - g_free(t); - g_free(s); -} - -static void oscar_login_connect(gpointer data, gint source, GdkInputCondition cond) -{ - struct gaim_connection *gc = data; - struct oscar_data *odata; - struct aim_session_t *sess; - struct aim_conn_t *conn; - - if (!g_slist_find(connections, gc)) { - close(source); - return; - } - - odata = gc->proto_data; - sess = odata->sess; - conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); - - if (source < 0) { - hide_login_progress(gc, _("Couldn't connect to host")); - signoff(gc); - return; - } - - aim_conn_completeconnect(sess, conn); - 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]; - 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; - - debug_printf(_("Logging in %s\n"), user->username); - - sess = g_new0(struct aim_session_t, 1); - - aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0); - aim_setdebuggingcb(sess, oscar_debug); - - /* 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, NULL); - if (conn == NULL) { - debug_printf(_("internal connection error\n")); - hide_login_progress(gc, _("Unable to login to AIM")); - 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); - - conn->status |= AIM_CONN_STATUS_INPROGRESS; - 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, - oscar_login_connect, gc); - if (conn->fd < 0) { - hide_login_progress(gc, _("Couldn't connect to host")); - signoff(gc); - return; - } - aim_request_login(sess, conn, gc->username); -} - -static void oscar_close(struct gaim_connection *gc) { - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; - if (gc->protocol != PROTO_OSCAR) return; - - while (odata->oscar_chats) { - struct chat_connection *n = odata->oscar_chats->data; - if (n->inpa > 0) - gdk_input_remove(n->inpa); - g_free(n->name); - g_free(n->show); - odata->oscar_chats = g_slist_remove(odata->oscar_chats, n); - g_free(n); - } - while (odata->direct_ims) { - struct direct_im *n = odata->direct_ims->data; - if (n->watcher > 0) - gdk_input_remove(n->watcher); - odata->direct_ims = g_slist_remove(odata->direct_ims, n); - g_free(n); - } -#if USE_PIXBUF - while (odata->hasicons) { - struct icon_req *n = odata->hasicons->data; - if (n->anim) - gdk_pixbuf_animation_unref(n->anim); - if (n->unanim) - gdk_pixbuf_unref(n->unanim); - if (n->timer) - gtk_timeout_remove(n->timer); - if (n->cnv && n->pix) - gtk_container_remove(GTK_CONTAINER(n->cnv->bbox), n->pix); - g_free(n->user); - if (n->data) - g_free(n->data); - odata->hasicons = g_slist_remove(odata->hasicons, n); - g_free(n); - } -#endif - if (gc->inpa > 0) - gdk_input_remove(gc->inpa); - if (odata->cnpa > 0) - gdk_input_remove(odata->cnpa); - if (odata->paspa > 0) - gdk_input_remove(odata->paspa); - aim_session_kill(odata->sess); - g_free(odata->sess); - odata->sess = NULL; - g_free(gc->proto_data); - gc->proto_data = NULL; - 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; - struct aim_session_t *sess; - struct aim_conn_t *bosconn; - - if (!g_slist_find(connections, gc)) { - close(source); - return; - } - - odata = gc->proto_data; - sess = odata->sess; - bosconn = odata->conn; - - if (source < 0) { - hide_login_progress(gc, _("Could Not Connect")); - signoff(gc); - return; - } - - aim_conn_completeconnect(sess, 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")); -} - -int gaim_parse_auth_resp(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - struct aim_conn_t *bosconn = NULL; - char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL; - unsigned char *cookie = NULL; - int errorcode = 0, regstatus = 0; - int latestbuild = 0, latestbetabuild = 0; - char *latestrelease = NULL, *latestbeta = NULL; - char *latestreleaseurl = NULL, *latestbetaurl = NULL; - char *latestreleaseinfo = NULL, *latestbetainfo = NULL; - int i; char *host; int port; - struct aim_user *user; - - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = gc->proto_data; - user = gc->user; - port = user->proto_opt[USEROPT_AUTHPORT][0] ? - atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT, - - va_start(ap, command); - sn = va_arg(ap, char *); - errorcode = va_arg(ap, int); - errurl = va_arg(ap, char *); - regstatus = va_arg(ap, int); - email = va_arg(ap, char *); - bosip = va_arg(ap, char *); - cookie = va_arg(ap, unsigned char *); - - latestrelease = va_arg(ap, char *); - latestbuild = va_arg(ap, int); - latestreleaseurl = va_arg(ap, char *); - latestreleaseinfo = va_arg(ap, char *); - - latestbeta = va_arg(ap, char *); - latestbetabuild = va_arg(ap, int); - latestbetaurl = va_arg(ap, char *); - latestbetainfo = va_arg(ap, char *); - - va_end(ap); - - debug_printf("inside auth_resp (Screen name: %s)\n", sn); - - if (errorcode || !bosip || !cookie) { - switch (errorcode) { - case 0x05: - /* Incorrect nick/password */ - hide_login_progress(gc, _("Incorrect nickname or password.")); - plugin_event(event_error, (void *)980, 0, 0, 0); - break; - case 0x11: - /* Suspended account */ - hide_login_progress(gc, _("Your account is currently suspended.")); - break; - case 0x18: - /* connecting too frequently */ - hide_login_progress(gc, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); - plugin_event(event_error, (void *)983, 0, 0, 0); - break; - case 0x1c: - /* client too old */ - hide_login_progress(gc, _("The client version you are using is too old. Please upgrade at " WEBSITE)); - plugin_event(event_error, (void *)989, 0, 0, 0); - break; - default: - hide_login_progress(gc, _("Authentication Failed")); - break; - } - debug_printf("Login Error Code 0x%04x\n", errorcode); - debug_printf("Error URL: %s\n", errurl); - od->killme = TRUE; - return 1; - } - - - debug_printf("Reg status: %2d\n", regstatus); - if (email) { - debug_printf("Email: %s\n", email); - } else { - debug_printf("Email is NULL\n"); - } - debug_printf("BOSIP: %s\n", bosip); - if (latestbeta) - debug_printf("Latest WinAIM beta version %s, build %d, at %s (%s)\n", - latestbeta, latestbetabuild, latestbetaurl, latestbetainfo); - if (latestrelease) - debug_printf("Latest WinAIM released version %s, build %d, at %s (%s)\n", - latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo); - debug_printf("Closing auth connection...\n"); - aim_conn_kill(sess, &command->conn); - - bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL); - if (bosconn == NULL) { - hide_login_progress(gc, _("Internal Error")); - od->killme = TRUE; - return 0; - } - - aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0); - aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, gaim_rateresp, 0); /* rate info */ - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, gaim_server_ready, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, gaim_reportinterval, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, gaim_parse_misses, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, gaim_parse_ratechange, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, gaim_parse_evilnotify, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, gaim_parse_searcherror, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, gaim_parse_searchreply, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_user_info, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, gaim_parse_msgack, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0); - aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, gaim_memrequest, 0); - - ((struct oscar_data *)gc->proto_data)->conn = bosconn; - for (i = 0; i < (int)strlen(bosip); i++) { - if (bosip[i] == ':') { - port = atoi(&(bosip[i+1])); - break; - } - } - host = g_strndup(bosip, i); - bosconn->status |= AIM_CONN_STATUS_INPROGRESS; - bosconn->fd = proxy_connect(host, port, oscar_bos_connect, gc); - g_free(host); - if (bosconn->fd < 0) { - hide_login_progress(gc, _("Could Not Connect")); - od->killme = TRUE; - return 0; - } - aim_auth_sendcookie(sess, bosconn, cookie); - gdk_input_remove(gc->inpa); - return 1; -} - -struct pieceofcrap { - struct gaim_connection *gc; - unsigned long offset; - unsigned long len; - char *modname; - int fd; - struct aim_conn_t *conn; - unsigned int inpa; -}; - -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; - unsigned char m[17]; - - while (read(pos->fd, &in, 1) == 1) { - if (in == '\n') - x++; - else if (in != '\r') - x = 0; - if (x == 2) - break; - in = '\0'; - } - if (in != '\n') { - 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->fd); - g_free(pos); - return; - } - 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->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; - } - - 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, ...) { - va_list ap; - struct pieceofcrap *pos; - unsigned long offset, len; - char *modname; - int fd; - - va_start(ap, command); - offset = va_arg(ap, unsigned long); - len = va_arg(ap, unsigned long); - 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, - AIM_SENDMEMBLOCK_FLAG_ISREQUEST); - return 1; - } - /* uncomment this when you're convinced it's right. remember, it's been wrong before. - if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) { - char *buf; - int i = 8; - if (modname) - i += strlen(modname); - buf = g_malloc(i); - i = 0; - if (modname) { - memcpy(buf, modname, strlen(modname)); - i += strlen(modname); - } - buf[i++] = offset & 0xff; - buf[i++] = (offset >> 8) & 0xff; - buf[i++] = (offset >> 16) & 0xff; - buf[i++] = (offset >> 24) & 0xff; - buf[i++] = len & 0xff; - buf[i++] = (len >> 8) & 0xff; - buf[i++] = (len >> 16) & 0xff; - buf[i++] = (len >> 24) & 0xff; - debug_printf("len + offset is invalid, hashing request\n"); - aim_sendmemblock(sess, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); - g_free(buf); - return 1; - } - */ - - pos = g_new0(struct pieceofcrap, 1); - pos->gc = sess->aux_data; - pos->conn = command->conn; - - pos->offset = offset; - pos->len = len; - pos->modname = modname ? g_strdup(modname) : NULL; - - fd = proxy_connect("gaim.sourceforge.net", 80, 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; -} - -void some_name(char *buf) -{ - int x[4]; - x[0] = htonl(0x45576172); - x[1] = htonl(0x6d656e68); - x[2] = htonl(0x6f76656e); - x[3] = 0; - g_snprintf(buf, 16, "%s", (char *)x); -} - -int gaim_parse_login(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { -#if 0 - struct client_info_s info = {"gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b}; -#else - struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD; -#endif - char *key; - va_list ap; - struct gaim_connection *gc = sess->aux_data; - - va_start(ap, command); - key = va_arg(ap, char *); - va_end(ap); - - aim_send_login(sess, command->conn, gc->username, gc->password, &info, key); - return 1; -} - -int gaim_server_ready(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - static int id = 1; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = gc->proto_data; - struct chat_connection *chatcon; - switch (command->conn->type) { - case AIM_CONN_TYPE_AUTH: - aim_auth_setversions(sess, command->conn); - aim_bos_reqrate(sess, command->conn); - debug_printf("done with AUTH ServerReady\n"); - if (od->chpass) { - debug_printf("changing password\n"); - aim_auth_changepasswd(sess, command->conn, od->newp, od->oldp); - g_free(od->oldp); - g_free(od->newp); - od->chpass = FALSE; - } - if (od->conf) { - debug_printf("confirming account\n"); - aim_auth_reqconfirm(sess, command->conn); - od->conf = FALSE; - } - if (od->reqemail) { - debug_printf("requesting email\n"); - aim_auth_getinfo(sess, command->conn, 0x0011); - od->reqemail = FALSE; - } - break; - case AIM_CONN_TYPE_BOS: - aim_setversions(sess, command->conn); - aim_bos_reqrate(sess, command->conn); /* request rate info */ - debug_printf("done with BOS ServerReady\n"); - break; - case AIM_CONN_TYPE_CHATNAV: - debug_printf("chatnav: got server ready\n"); - aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0); - aim_bos_reqrate(sess, command->conn); - aim_bos_ackrateresp(sess, command->conn); - aim_chatnav_clientready(sess, command->conn); - aim_chatnav_reqrights(sess, command->conn); - break; - case AIM_CONN_TYPE_CHAT: - debug_printf("chat: got server ready\n"); - aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0); - aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0); - aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0); - aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0); - aim_bos_reqrate(sess, command->conn); - aim_bos_ackrateresp(sess, command->conn); - aim_chat_clientready(sess, command->conn); - chatcon = find_oscar_chat_by_conn(gc, command->conn); - chatcon->id = id; - chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show); - break; - case AIM_CONN_TYPE_RENDEZVOUS: - break; - default: /* huh? */ - debug_printf("server ready: got unexpected connection type %04x\n", command->conn->type); - break; - } - return 1; -} - -static void oscar_chatnav_connect(gpointer data, gint source, GdkInputCondition cond) -{ - struct gaim_connection *gc = data; - struct oscar_data *odata; - struct aim_session_t *sess; - struct aim_conn_t *tstconn; - - if (!g_slist_find(connections, gc)) { - close(source); - return; - } - - odata = gc->proto_data; - sess = odata->sess; - tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_CHATNAV); - - if (source < 0) { - aim_conn_kill(sess, &tstconn); - debug_printf("unable to connect to chatnav server\n"); - return; - } - - aim_conn_completeconnect(sess, tstconn); - 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; - struct aim_session_t *sess; - struct aim_conn_t *tstconn; - - if (!g_slist_find(connections, gc)) { - close(source); - return; - } - - odata = gc->proto_data; - sess = odata->sess; - tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); - - if (source < 0) { - aim_conn_kill(sess, &tstconn); - debug_printf("unable to connect to authorizer\n"); - return; - } - - aim_conn_completeconnect(sess, tstconn); - odata->paspa = 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; - struct aim_session_t *sess; - struct aim_conn_t *tstconn; - - if (!g_slist_find(connections, gc)) { - close(source); - g_free(ccon->show); - g_free(ccon->name); - g_free(ccon); - return; - } - - odata = gc->proto_data; - sess = odata->sess; - tstconn = ccon->conn; - - if (source < 0) { - aim_conn_kill(sess, &tstconn); - g_free(ccon->show); - g_free(ccon->name); - g_free(ccon); - return; - } - - aim_conn_completeconnect(sess, ccon->conn); - 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); -} - -int gaim_handle_redirect(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - int serviceid; - char *ip; - unsigned char *cookie; - struct gaim_connection *gc = sess->aux_data; - struct aim_user *user = gc->user; - struct aim_conn_t *tstconn; - int i; - char *host; - int port; - - port = user->proto_opt[USEROPT_AUTHPORT][0] ? - atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT, - - 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"); - tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); - if (tstconn == NULL) { - debug_printf("unable to reconnect with authorizer\n"); - g_free(host); - return 1; - } - 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); - - tstconn->status |= AIM_CONN_STATUS_INPROGRESS; - tstconn->fd = proxy_connect(host, port, oscar_auth_connect, gc); - if (tstconn->fd < 0) { - aim_conn_kill(sess, &tstconn); - debug_printf("unable to reconnect with authorizer\n"); - g_free(host); - return 1; - } - aim_auth_sendcookie(sess, tstconn, cookie); - 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->status |= AIM_CONN_STATUS_INPROGRESS; - tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, gc); - if (tstconn->fd < 0) { - aim_conn_kill(sess, &tstconn); - debug_printf("unable to connect to chatnav server\n"); - g_free(host); - return 1; - } - aim_auth_sendcookie(sess, tstconn, cookie); - break; - case 0xe: /* Chat */ - { - char *roomname = va_arg(ap, char *); - int exchange = va_arg(ap, int); - struct chat_connection *ccon; - 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; - } - - aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); - ccon = g_new0(struct chat_connection, 1); - ccon->conn = tstconn; - ccon->gc = gc; - ccon->fd = -1; - ccon->name = g_strdup(roomname); - ccon->exchange = exchange; - ccon->show = extract_name(roomname); - - ccon->conn->status |= AIM_CONN_STATUS_INPROGRESS; - ccon->conn->fd = proxy_connect(host, port, oscar_chat_connect, ccon); - if (ccon->conn->fd < 0) { - aim_conn_kill(sess, &tstconn); - debug_printf("unable to connect to chat server\n"); - g_free(host); - g_free(ccon->show); - g_free(ccon->name); - g_free(ccon); - return 1; - } - aim_auth_sendcookie(sess, tstconn, cookie); - debug_printf("Connected to chat room %s exchange %d\n", roomname, exchange); - } - break; - default: /* huh? */ - debug_printf("got redirect for unknown service 0x%04x\n", serviceid); - break; - } - - va_end(ap); - - g_free(host); - return 1; -} - -int gaim_parse_oncoming(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - struct aim_userinfo_s *info; - time_t time_idle; - int type = 0; - struct gaim_connection *gc = sess->aux_data; - - va_list ap; - va_start(ap, command); - info = va_arg(ap, struct aim_userinfo_s *); - va_end(ap); - - if (info->flags & AIM_FLAG_UNCONFIRMED) - type |= UC_UNCONFIRMED; - else if (info->flags & AIM_FLAG_ADMINISTRATOR) - type |= UC_ADMIN; - else if (info->flags & AIM_FLAG_AOL) - type |= UC_AOL; - else if (info->flags & AIM_FLAG_FREE) - type |= UC_NORMAL; - if (info->flags & AIM_FLAG_AWAY) - type |= UC_UNAVAILABLE; - - if (info->idletime) { - time(&time_idle); - time_idle -= info->idletime*60; - } else - time_idle = 0; - - serv_got_update(gc, info->sn, 1, info->warnlevel/10, info->onlinesince, - time_idle, type, info->capabilities); - - return 1; -} - -int gaim_parse_offgoing(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - struct aim_userinfo_s *info; - va_list ap; - struct gaim_connection *gc = sess->aux_data; - - va_start(ap, command); - info = va_arg(ap, struct aim_userinfo_s *); - va_end(ap); - - serv_got_update(gc, info->sn, 0, 0, 0, 0, 0, 0); - - return 1; -} - -static void cancel_direct_im(gpointer w, struct ask_direct *d) { - debug_printf("Freeing DirectIM prompts.\n"); - - g_free(d->sn); - g_free(d); -} - -static void delete_direct_im(gpointer w, struct direct_im *d) { - struct oscar_data *od = (struct oscar_data *)d->gc->proto_data; - - od->direct_ims = g_slist_remove(od->direct_ims, d); - gdk_input_remove(d->watcher); - aim_conn_kill(od->sess, &d->conn); - g_free(d); -} - -static void oscar_directim_callback(gpointer data, gint source, GdkInputCondition condition) { - struct direct_im *dim = data; - struct gaim_connection *gc = dim->gc; - struct oscar_data *od = gc->proto_data; - char buf[256]; - - if (!g_slist_find(connections, gc)) { - g_free(dim); - return; - } - - if (source < 0) { - g_free(dim); - return; - } - - aim_conn_completeconnect(od->sess, dim->conn); - 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)); - - od->direct_ims = g_slist_append(od->direct_ims, dim); - - gtk_signal_connect(GTK_OBJECT(dim->cnv->window), "destroy", - GTK_SIGNAL_FUNC(delete_direct_im), dim); - - dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, dim->conn); -} - -static int accept_direct_im(gpointer w, struct ask_direct *d) { - 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"); - - dim = find_direct_im(od, d->sn); - if (dim) { - cancel_direct_im(w, d); /* 40 */ - return TRUE; - } - dim = g_new0(struct direct_im, 1); - dim->gc = d->gc; - g_snprintf(dim->name, sizeof dim->name, "%s", d->sn); - - 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->status |= AIM_CONN_STATUS_INPROGRESS; - dim->conn->fd = proxy_connect(host, port, 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; - } - - cancel_direct_im(w, d); - - return TRUE; -} - -/* -static void cancel_getfile(gpointer w, struct ask_getfile *g) { - g_free(g->ip); - g_free(g->cookie); - g_free(g->sn); - g_free(g); -} - -static void cancel_getfile_file(GtkObject *obj, struct ask_getfile *g) { - GtkWidget *w = gtk_object_get_user_data(obj); - gtk_widget_destroy(w); - cancel_getfile(w, g); -} - -static void cancel_getfile_cancel(GtkObject *obj, struct ask_getfile *g) { - GtkWidget *w = gtk_object_get_user_data(obj); - gtk_widget_destroy(w); -} - -static void interrupt_getfile(GtkObject *obj, struct getfile_transfer *gt) { - struct gaim_connection *gc = gt->gc; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - - gtk_widget_destroy(gt->window); - gdk_input_remove(gt->gip); - if (gt->gop > 0) - gdk_input_remove(gt->gop); - aim_conn_kill(od->sess, >->conn); - od->getfiles = g_slist_remove(od->getfiles, gt); - g_free(gt->receiver); - g_free(gt->filename); - fclose(gt->listing); - g_free(gt); -} - -static int gaim_getfile_filereq(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct getfile_transfer *gt; - char buf[2048]; - GtkWidget *label; - GtkWidget *button; - - va_list ap; - struct aim_conn_t *oftconn; - struct aim_fileheader_t *fh; - char *cookie; - - va_start(ap, command); - oftconn = va_arg(ap, struct aim_conn_t *); - fh = va_arg(ap, struct aim_fileheader_t *); - cookie = va_arg(ap, char *); - va_end(ap); - - gt = find_getfile_transfer(od, oftconn); - - if (gt->window) - return 1; - - gt->window = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(gt->window), _("Gaim - File Transfer")); - gtk_widget_realize(gt->window); - aol_icon(gt->window->window); - - g_snprintf(buf, sizeof buf, _("Sending %s to %s"), fh->name, gt->receiver); - label = gtk_label_new(buf); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->vbox), label, FALSE, FALSE, 5); - gtk_widget_show(label); - - gt->meter = gtk_progress_bar_new(); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->action_area), gt->meter, FALSE, FALSE, 5); - gtk_widget_show(gt->meter); - - gt->label = gtk_label_new("0 %"); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->action_area), gt->label, FALSE, FALSE, 5); - gtk_widget_show(gt->label); - - button = picture_button(gt->window, _("Cancel"), cancel_xpm); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->action_area), button, FALSE, FALSE, 5); - gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(interrupt_getfile), gt); - - gtk_widget_show(gt->window); - - return 1; -} - -static void getfile_send_callback(gpointer data, gint source, GdkInputCondition condition) { - struct getfile_transfer *gt = (struct getfile_transfer *)data; - int result; - - result = aim_getfile_send_chunk(gt->conn, gt->file, gt->fh, -1, 1024); - gt->pos += result; - if (result == 0) { - gdk_input_remove(gt->gop); gt->gop = 0; - } else if (result == -1) { - do_error_dialog(_("Error in transfer"), "Gaim"); - gdk_input_remove(gt->gop); gt->gop = 0; - interrupt_getfile(NULL, gt); - } -} - -static int gaim_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct getfile_transfer *gt; - - va_list ap; - struct aim_conn_t *oftconn; - struct aim_fileheader_t *fh; - char *cookie; - - va_start(ap, command); - oftconn = va_arg(ap, struct aim_conn_t *); - fh = va_arg(ap, struct aim_fileheader_t *); - cookie = va_arg(ap, char *); - va_end(ap); - - gt = find_getfile_transfer(od, oftconn); - - if (gt->gop > 0) { - debug_printf("already have output watcher?\n"); - return 1; - } - - if ((gt->file = fopen(gt->filename, "r")) == NULL) { - interrupt_getfile(NULL, gt); - return 1; - } - gt->pos = 0; - gt->fh = g_memdup(fh, sizeof(struct aim_fileheader_t)); - fseek(gt->file, 0, SEEK_SET); - - gt->gop = gdk_input_add(gt->conn->fd, GDK_INPUT_WRITE, getfile_send_callback, gt); - - return 1; -} - -static int gaim_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct getfile_transfer *gt; - - va_list ap; - struct aim_conn_t *conn; - struct aim_fileheader_t *fh; - - va_start(ap, command); - conn = va_arg(ap, struct aim_conn_t *); - fh = va_arg(ap, struct aim_fileheader_t *); - va_end(ap); - - gt = find_getfile_transfer(od, conn); - - gtk_widget_destroy(gt->window); - gt->window = NULL; - do_error_dialog(_("Transfer complete."), "Gaim"); - - return 1; -} - -static int gaim_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct getfile_transfer *gt; - - va_list ap; - struct aim_conn_t *conn; - char *sn; - - va_start(ap, command); - conn = va_arg(ap, struct aim_conn_t *); - sn = va_arg(ap, char *); - va_end(ap); - - gt = find_getfile_transfer(od, conn); - od->getfiles = g_slist_remove(od->getfiles, gt); - gdk_input_remove(gt->gip); - if (gt->gop > 0) - gdk_input_remove(gt->gop); - g_free(gt->receiver); - g_free(gt->filename); - aim_conn_kill(sess, &conn); - fclose(gt->listing); - g_free(gt); - - debug_printf("getfile disconnect\n"); - - return 1; -} - -static void oscar_getfile_callback(gpointer data, gint source, GdkInputCondition condition) { - struct getfile_transfer *gf = data; - struct gaim_connection *gc = gf->gc; - struct oscar_data *od = gc->proto_data; - - gdk_input_remove(gf->gip); - gf->gip = gdk_input_add(source, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, oscar_callback, gf->conn); - - aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, gaim_getfile_filereq, 0); - aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, gaim_getfile_filesend, 0); - aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, gaim_getfile_complete, 0); - aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, gaim_getfile_disconnect, 0); -} - -static void do_getfile(GtkObject *obj, struct ask_getfile *g) { - GtkWidget *w = gtk_object_get_user_data(obj); - char *filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(w)); - struct gaim_connection *gc = g->gc; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct getfile_transfer *gf; - struct stat st; - struct tm *ft; - char tmppath[256]; - FILE *file; - static int current = 0; - struct aim_conn_t *newconn; - - if (file_is_dir(filename, w)) - return; - - if (stat(filename, &st) != 0) { - gtk_widget_destroy(w); - do_error_dialog(_("Error examining file"), _("GetFile Error")); - cancel_getfile(w, g); - return; - } - - g_snprintf(tmppath, sizeof tmppath, "/%s/gaim%d%d", g_get_tmp_dir(), getpid(), current++); - if ((file = fopen(tmppath, "w+")) == NULL) { - gtk_widget_destroy(w); - do_error_dialog(_("Could not open temporary file, aborting"), _("GetFile Error")); - cancel_getfile(w, g); - return; - } - - gf = g_new0(struct getfile_transfer, 1); - gf->gc = gc; - gf->filename = g_strdup(filename); - gf->listing = file; - gf->receiver = g_strdup(g->sn); - gf->size = st.st_size; - - ft = localtime(&st.st_ctime); - fprintf(file, "%2d/%2d/%4d %2d:%2d %8ld ", - ft->tm_mon + 1, ft->tm_mday, ft->tm_year + 1900, - ft->tm_hour + 1, ft->tm_min + 1, (long)st.st_size); - fprintf(file, "%s\r\n", g_basename(filename)); - rewind(file); - - aim_oft_registerlisting(od->sess, file, ""); - if ((newconn = aim_accepttransfer(od->sess, od->conn, g->sn, g->cookie, g->ip, file, AIM_CAPS_GETFILE)) == NULL) { - od->sess->flags ^= AIM_SESS_FLAGS_NONBLOCKCONNECT; - do_error_dialog(_("Error connecting for transfer"), _("GetFile Error")); - g_free(gf->filename); - fclose(file); - g_free(gf); - gtk_widget_destroy(w); - return; - } - - gtk_widget_destroy(w); - - od->getfiles = g_slist_append(od->getfiles, gf); - gf->conn = newconn; - gf->gip = gdk_input_add(newconn->fd, GDK_INPUT_WRITE, oscar_getfile_callback, gf); -} - -static int accept_getfile(gpointer w, struct ask_getfile *g) { - GtkWidget *window; - window = gtk_file_selection_new(_("Gaim - Send File...")); - gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(window)); - gtk_object_set_user_data(GTK_OBJECT(window), window); - gtk_signal_connect(GTK_OBJECT(window), "destroy", - GTK_SIGNAL_FUNC(cancel_getfile_file), g); - gtk_object_set_user_data(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), window); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", - GTK_SIGNAL_FUNC(do_getfile), g); - gtk_object_set_user_data(GTK_OBJECT(GTK_FILE_SELECTION(window)->cancel_button), window); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->cancel_button), "clicked", - GTK_SIGNAL_FUNC(cancel_getfile_cancel), g); - gtk_widget_show(window); - - return TRUE; -} -*/ - -#if USE_PIXBUF -static gboolean redraw_anim(gpointer data) -{ - int delay; - struct icon_req *ir = data; - GList *frames; - GdkPixbufFrame *frame; - GdkPixbuf *buf; - GdkPixmap *pm; GdkBitmap *bm; - GdkPixmap *src; - GdkGC *gc; - - if (!ir->cnv || !g_list_find(conversations, ir->cnv)) { - debug_printf("I think this is a bug.\n"); - return FALSE; - } - - frames = gdk_pixbuf_animation_get_frames(ir->anim); - frame = g_list_nth_data(frames, ir->curframe); - buf = gdk_pixbuf_frame_get_pixbuf(frame); - switch (gdk_pixbuf_frame_get_action(frame)) { - case GDK_PIXBUF_FRAME_RETAIN: - gdk_pixbuf_render_pixmap_and_mask(buf, &src, NULL, 0); - gtk_pixmap_get(GTK_PIXMAP(ir->pix), &pm, &bm); - gc = gdk_gc_new(pm); - gdk_draw_pixmap(pm, gc, src, 0, 0, - gdk_pixbuf_frame_get_x_offset(frame), - gdk_pixbuf_frame_get_y_offset(frame), - -1, -1); - gdk_pixmap_unref(src); - gtk_widget_queue_draw(ir->pix); - gdk_gc_unref(gc); - break; - case GDK_PIXBUF_FRAME_DISPOSE: - gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0); - gtk_pixmap_set(GTK_PIXMAP(ir->pix), pm, bm); - gdk_pixmap_unref(pm); - if (bm) - gdk_bitmap_unref(bm); - break; - case GDK_PIXBUF_FRAME_REVERT: - frame = frames->data; - buf = gdk_pixbuf_frame_get_pixbuf(frame); - gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0); - gtk_pixmap_set(GTK_PIXMAP(ir->pix), pm, bm); - gdk_pixmap_unref(pm); - if (bm) - gdk_bitmap_unref(bm); - break; - } - ir->curframe = (ir->curframe + 1) % g_list_length(frames); - delay = MAX(gdk_pixbuf_frame_get_delay_time(frame), 13); - ir->timer = gtk_timeout_add(delay * 10, redraw_anim, ir); - return FALSE; -} -#endif - -int gaim_parse_incoming_im(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - int channel; - struct aim_userinfo_s *userinfo; - va_list ap; - struct gaim_connection *gc = sess->aux_data; - - va_start(ap, command); - channel = va_arg(ap, int); - userinfo = va_arg(ap, struct aim_userinfo_s *); - - /* channel 1: standard message */ - if (channel == 1) { - char *tmp = g_malloc(BUF_LONG); - struct aim_incomingim_ch1_args *args; - - args = va_arg(ap, struct aim_incomingim_ch1_args *); - va_end(ap); - -#if USE_PIXBUF - if (args->icbmflags & AIM_IMFLAGS_HASICON) { - struct oscar_data *od = gc->proto_data; - struct icon_req *ir; - GSList *h = od->hasicons; - char *who = normalize(userinfo->sn); - debug_printf("%s has an icon\n", userinfo->sn); - while (h) { - ir = h->data; - if (!strcmp(ir->user, who)) - break; - h = h->next; - } - if (!h) { - ir = g_new0(struct icon_req, 1); - ir->user = g_strdup(who); - od->hasicons = g_slist_append(od->hasicons, ir); - } - if (args->iconstamp > ir->timestamp) - ir->request = TRUE; - ir->timestamp = args->iconstamp; - } -#endif - - /* - * Quickly convert it to eight bit format, replacing - * non-ASCII UNICODE characters with their equivelent - * HTML entity. - */ - if (args->icbmflags & AIM_IMFLAGS_UNICODE) { - int i; - - for (i = 0, tmp[0] = '\0'; i < args->msglen; i += 2) { - unsigned short uni; - - uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff); - - if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */ - - g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "%c", uni); - - } else { /* something else, do UNICODE entity */ - g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "&#%04x;", uni); - } - } - } else - g_snprintf(tmp, BUF_LONG, "%s", args->msg); - - serv_got_im(gc, userinfo->sn, tmp, args->icbmflags & AIM_IMFLAGS_AWAY, time(NULL)); - g_free(tmp); - } else if (channel == 2) { - struct aim_incomingim_ch2_args *args; - args = va_arg(ap, struct aim_incomingim_ch2_args *); - va_end(ap); - if (args->reqclass & AIM_CAPS_CHAT) { - char *name = extract_name(args->info.chat.roominfo.name); - serv_got_chat_invite(gc, - name ? name : args->info.chat.roominfo.name, - args->info.chat.roominfo.exchange, - userinfo->sn, - args->info.chat.msg); - if (name) - g_free(name); - } else if (args->reqclass & AIM_CAPS_SENDFILE) { - } else if (args->reqclass & AIM_CAPS_GETFILE) { - /* - char *ip, *cookie; - struct ask_getfile *g = g_new0(struct ask_getfile, 1); - char buf[256]; - - userinfo = va_arg(ap, struct aim_userinfo_s *); - ip = va_arg(ap, char *); - cookie = va_arg(ap, char *); - va_end(ap); - - debug_printf("%s received getfile request from %s (%s), cookie = %s\n", - gc->username, userinfo->sn, ip, cookie); - - g->gc = gc; - g->sn = g_strdup(userinfo->sn); - g->cookie = g_strdup(cookie); - g->ip = g_strdup(ip); - g_snprintf(buf, sizeof buf, "%s has just asked to get a file from %s.", - userinfo->sn, gc->username); - do_ask_dialog(buf, g, accept_getfile, cancel_getfile); - */ - } else if (args->reqclass & AIM_CAPS_VOICE) { - } else if (args->reqclass & AIM_CAPS_BUDDYICON) { -#if USE_PIXBUF - struct oscar_data *od = gc->proto_data; - GSList *h = od->hasicons; - struct icon_req *ir = NULL; - char *who; - struct conversation *c; - - GdkPixbufLoader *load; - GList *frames; - GdkPixbuf *buf; - GdkPixmap *pm; - GdkBitmap *bm; - - who = normalize(userinfo->sn); - - while (h) { - ir = h->data; - if (!strcmp(who, ir->user)) - break; - h = h->next; - - } - - if (!h || ((c = find_conversation(userinfo->sn)) == NULL) || (c->gc != gc)) { - debug_printf("got buddy icon for %s but didn't want it\n", userinfo->sn); - return 1; - } - - if (ir->pix && ir->cnv) - gtk_container_remove(GTK_CONTAINER(ir->cnv->bbox), ir->pix); - ir->pix = NULL; - ir->cnv = NULL; - if (ir->data) - g_free(ir->data); - if (ir->anim) - gdk_pixbuf_animation_unref(ir->anim); - ir->anim = NULL; - if (ir->unanim) - gdk_pixbuf_unref(ir->unanim); - ir->unanim = NULL; - if (ir->timer) - gtk_timeout_remove(ir->timer); - ir->timer = 0; - - ir->length = args->info.icon.length; - - if (!ir->length) - return 1; - - ir->data = g_memdup(args->info.icon.icon, args->info.icon.length); - - load = gdk_pixbuf_loader_new(); - gdk_pixbuf_loader_write(load, ir->data, ir->length); - ir->anim = gdk_pixbuf_loader_get_animation(load); - - if (ir->anim) { - frames = gdk_pixbuf_animation_get_frames(ir->anim); - buf = gdk_pixbuf_frame_get_pixbuf(frames->data); - gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0); - - if (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1) { - int delay = - MAX(gdk_pixbuf_frame_get_delay_time(frames->data), 13); - ir->curframe = 1; - ir->timer = gtk_timeout_add(delay * 10, redraw_anim, ir); - } - } else { - ir->unanim = gdk_pixbuf_loader_get_pixbuf(load); - if (!ir->unanim) { - gdk_pixbuf_loader_close(load); - return 1; - } - gdk_pixbuf_render_pixmap_and_mask(ir->unanim, &pm, &bm, 0); - } - - ir->cnv = c; - ir->pix = gtk_pixmap_new(pm, bm); - gtk_box_pack_start(GTK_BOX(c->bbox), ir->pix, FALSE, FALSE, 5); - if (ir->anim && (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1)) - gtk_widget_set_usize(ir->pix, gdk_pixbuf_animation_get_width(ir->anim), - gdk_pixbuf_animation_get_height(ir->anim)); - gtk_widget_show(ir->pix); - gdk_pixmap_unref(pm); - if (bm) - gdk_bitmap_unref(bm); - - gdk_pixbuf_loader_close(load); - -#endif - } else if (args->reqclass & AIM_CAPS_IMIMAGE) { - struct ask_direct *d = g_new0(struct ask_direct, 1); - char buf[256]; - - debug_printf("%s received direct im request from %s (%s)\n", - gc->username, userinfo->sn, args->info.directim->ip); - - d->gc = gc; - d->sn = g_strdup(userinfo->sn); - d->priv = args->info.directim; - g_snprintf(buf, sizeof buf, "%s has just asked to directly connect to %s.", - userinfo->sn, gc->username); - do_ask_dialog(buf, d, accept_direct_im, cancel_direct_im); - } else { - debug_printf("Unknown reqclass %d\n", args->reqclass); - } - } - - return 1; -} - -int gaim_parse_misses(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - unsigned short chan, nummissed, reason; - struct aim_userinfo_s *userinfo; - char buf[1024]; - - va_start(ap, command); - chan = (unsigned short)va_arg(ap, unsigned int); - userinfo = va_arg(ap, struct aim_userinfo_s *); - nummissed = (unsigned short)va_arg(ap, unsigned int); - reason = (unsigned short)va_arg(ap, unsigned int); - va_end(ap); - - switch(reason) { - case 1: - /* message too large */ - sprintf(buf, _("You missed a message from %s because it was too large."), userinfo->sn); - do_error_dialog(buf, _("Gaim - Error")); - plugin_event(event_error, (void *)961, 0, 0, 0); - break; - default: - sprintf(buf, _("You missed a message from %s for unknown reasons."), userinfo->sn); - do_error_dialog(buf, _("Gaim - Error")); - plugin_event(event_error, (void *)970, 0, 0, 0); - break; - } - - return 1; -} - -int gaim_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - unsigned short reason; - - va_start(ap, command); - reason = va_arg(ap, int); - va_end(ap); - - debug_printf("snac threw error (reason 0x%04x: %s\n", reason, - (reason < msgerrreasonlen) ? msgerrreason[reason] : "unknown"); - - return 1; -} - -int gaim_parse_msgerr(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - char *destn; - unsigned short reason; - char buf[1024]; - - va_start(ap, command); - reason = (unsigned short)va_arg(ap, unsigned int); - destn = va_arg(ap, char *); - va_end(ap); - - sprintf(buf, _("Your message to %s did not get sent: %s"), destn, - (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); - do_error_dialog(buf, _("Gaim - Error")); - - return 1; -} - -int gaim_parse_locerr(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - char *destn; - unsigned short reason; - char buf[1024]; - - va_start(ap, command); - reason = (unsigned short)va_arg(ap, unsigned int); - destn = va_arg(ap, char *); - va_end(ap); - - sprintf(buf, _("User information for %s unavailable: %s"), destn, - (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); - do_error_dialog(buf, _("Gaim - Error")); - - return 1; -} - -static char *images(int flags) { - static char buf[1024]; - g_snprintf(buf, sizeof(buf), "%s%s%s%s", - (flags & AIM_FLAG_UNCONFIRMED) ? "<IMG SRC=\"dt_icon.gif\">" : "", - (flags & AIM_FLAG_AOL) ? "<IMG SRC=\"aol_icon.gif\">" : "", - (flags & AIM_FLAG_ADMINISTRATOR) ? "<IMG SRC=\"admin_icon.gif\">" : "", - (flags & AIM_FLAG_FREE) ? "<IMG SRC=\"free_icon.gif\">" : ""); - return buf; -} - -int gaim_parse_user_info(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - struct aim_userinfo_s *info; - char *prof_enc = NULL, *prof = NULL; - unsigned short infotype; - char buf[BUF_LONG]; - struct gaim_connection *gc = sess->aux_data; - va_list ap; - char *asc; - - va_start(ap, command); - info = va_arg(ap, struct aim_userinfo_s *); - prof_enc = va_arg(ap, char *); - prof = va_arg(ap, char *); - infotype = (unsigned short)va_arg(ap, unsigned int); - va_end(ap); - - if (info->membersince) - asc = g_strdup_printf("Member Since : <B>%s</B><BR>\n", - asctime(localtime(&info->membersince))); - else - asc = g_strdup(""); - - g_snprintf(buf, sizeof buf, - _("Username : <B>%s</B> %s <BR>\n" - "%s" - "Warning Level : <B>%d %%</B><BR>\n" - "Online Since : <B>%s</B><BR>\n" - "Idle Minutes : <B>%d</B>\n<BR>\n<HR><BR>\n" - "%s" - "<br><BODY BGCOLOR=WHITE><hr><I>Legend:</I><br><br>" - "<IMG SRC=\"free_icon.gif\"> : Normal AIM User<br>" - "<IMG SRC=\"aol_icon.gif\"> : AOL User <br>" - "<IMG SRC=\"dt_icon.gif\"> : Trial AIM User <br>" - "<IMG SRC=\"admin_icon.gif\"> : Administrator"), - info->sn, images(info->flags), - asc, - info->warnlevel/10, - asctime(localtime(&info->onlinesince)), - info->idletime, - (prof && strlen(prof)) ? - (infotype == AIM_GETINFO_GENERALINFO ? - prof : - away_subs(prof, gc->username)) - : - (infotype == AIM_GETINFO_GENERALINFO ? - _("<i>No Information Provided</i>") : - _("<i>User has no away message</i>"))); - - g_show_info_text(away_subs(buf, gc->username)); - - g_free(asc); - - return 1; -} - -int gaim_parse_motd(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - char *msg; - unsigned short id; - va_list ap; - char buildbuf[150]; - - va_start(ap, command); - id = (unsigned short)va_arg(ap, unsigned int); - msg = va_arg(ap, char *); - va_end(ap); - - aim_getbuildstring(buildbuf, sizeof(buildbuf)); - - debug_printf("MOTD: %s (%d)\n", msg ? msg : "Unknown", id); - debug_printf("Gaim %s / Libfaim %s\n", VERSION, buildbuf); - if (id != 4) - do_error_dialog(_("Your connection may be lost."), - _("AOL error")); - - return 1; -} - -int gaim_chatnav_info(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - unsigned short type; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; - - va_start(ap, command); - type = (unsigned short)va_arg(ap, unsigned int); - - switch(type) { - case 0x0002: { - int maxrooms; - struct aim_chat_exchangeinfo *exchanges; - int exchangecount, i = 0; - - maxrooms = (unsigned char)va_arg(ap, unsigned int); - exchangecount = va_arg(ap, int); - exchanges = va_arg(ap, struct aim_chat_exchangeinfo *); - va_end(ap); - - debug_printf("chat info: Chat Rights:\n"); - debug_printf("chat info: \tMax Concurrent Rooms: %d\n", maxrooms); - debug_printf("chat info: \tExchange List: (%d total)\n", exchangecount); - while (i < exchangecount) - debug_printf("chat info: \t\t%d\n", exchanges[i++].number); - if (odata->create_exchange) { - debug_printf("creating room %s\n", odata->create_name); - aim_chatnav_createroom(sess, command->conn, odata->create_name, - odata->create_exchange); - odata->create_exchange = 0; - g_free(odata->create_name); - odata->create_name = NULL; - } - } - break; - case 0x0008: { - char *fqcn, *name, *ck; - unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange; - unsigned char createperms; - unsigned long createtime; - - fqcn = va_arg(ap, char *); - instance = (unsigned short)va_arg(ap, unsigned int); - exchange = (unsigned short)va_arg(ap, unsigned int); - flags = (unsigned short)va_arg(ap, unsigned int); - createtime = va_arg(ap, unsigned long); - maxmsglen = (unsigned short)va_arg(ap, unsigned int); - maxoccupancy = (unsigned short)va_arg(ap, unsigned int); - createperms = (unsigned char)va_arg(ap, int); - unknown = (unsigned short)va_arg(ap, unsigned int); - name = va_arg(ap, char *); - ck = va_arg(ap, char *); - va_end(ap); - - debug_printf("created room: %s %d %d %d %lu %d %d %d %d %s %s\n", - fqcn, - exchange, instance, flags, - createtime, - maxmsglen, maxoccupancy, createperms, unknown, - name, ck); - aim_chat_join(odata->sess, odata->conn, exchange, ck); - } - break; - default: - va_end(ap); - debug_printf("chatnav info: unknown type (%04x)\n", type); - break; - } - return 1; -} - -int gaim_chat_join(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - int count, i = 0; - struct aim_userinfo_s *info; - struct gaim_connection *g = sess->aux_data; - - struct chat_connection *c = NULL; - - va_start(ap, command); - count = va_arg(ap, int); - info = va_arg(ap, struct aim_userinfo_s *); - va_end(ap); - - c = find_oscar_chat_by_conn(g, command->conn); - if (!c) - return 1; - - while (i < count) - add_chat_buddy(c->cnv, info[i++].sn); - - return 1; -} - -int gaim_chat_leave(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - int count, i = 0; - struct aim_userinfo_s *info; - struct gaim_connection *g = sess->aux_data; - - struct chat_connection *c = NULL; - - va_start(ap, command); - count = va_arg(ap, int); - info = va_arg(ap, struct aim_userinfo_s *); - va_end(ap); - - c = find_oscar_chat_by_conn(g, command->conn); - if (!c) - return 1; - - while (i < count) - remove_chat_buddy(c->cnv, info[i++].sn); - - return 1; -} - -int gaim_chat_info_update(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - debug_printf("inside chat_info_update\n"); - return 1; -} - -int gaim_chat_incoming_msg(struct aim_session_t *sess, - struct command_rx_struct *command, ...) { - va_list ap; - struct aim_userinfo_s *info; - char *msg; - struct gaim_connection *gc = sess->aux_data; - struct chat_connection *ccon = find_oscar_chat_by_conn(gc, command->conn); - char *tmp; - - va_start(ap, command); - info = va_arg(ap, struct aim_userinfo_s *); - msg = va_arg(ap, char *); - - tmp = g_malloc(BUF_LONG); - g_snprintf(tmp, BUF_LONG, "%s", msg); - serv_got_chat_in(gc, ccon->id, info->sn, 0, tmp, time((time_t)NULL)); - g_free(tmp); - - return 1; -} - - /* - * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option. - */ -int gaim_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - unsigned short type; - char *sn = NULL; - - va_start(ap, command); - type = (unsigned short)va_arg(ap, unsigned int); - sn = va_arg(ap, char *); - va_end(ap); - - debug_printf("Sent message to %s.\n", sn); - - return 1; -} - -int gaim_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - static char *codes[5] = {"invalid", - "change", - "warning", - "limit", - "limit cleared"}; - va_list ap; - int code; - unsigned long rateclass, windowsize, clear, alert, limit, disconnect; - unsigned long currentavg, maxavg; - - va_start(ap, command); - code = va_arg(ap, int); - rateclass= va_arg(ap, int); - windowsize = va_arg(ap, unsigned long); - clear = va_arg(ap, unsigned long); - alert = va_arg(ap, unsigned long); - limit = va_arg(ap, unsigned long); - disconnect = va_arg(ap, unsigned long); - currentavg = va_arg(ap, unsigned long); - maxavg = va_arg(ap, unsigned long); - va_end(ap); - - debug_printf("rate %s (paramid 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, " - "clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n", - (code < 5) ? codes[code] : codes[0], - rateclass, - currentavg, maxavg, - alert, clear, - limit, disconnect, - windowsize); - - if (code == AIM_RATE_CODE_CHANGE) { - if (currentavg >= clear) - aim_conn_setlatency(command->conn, 0); - } else if (code == AIM_RATE_CODE_WARNING) { - aim_conn_setlatency(command->conn, windowsize/4); - } else if (code == AIM_RATE_CODE_LIMIT) { - aim_conn_setlatency(command->conn, windowsize/2); - } else if (code == AIM_RATE_CODE_CLEARLIMIT) { - aim_conn_setlatency(command->conn, 0); - } - - return 1; -} - -int gaim_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - int newevil; - struct aim_userinfo_s *userinfo; - struct gaim_connection *gc = sess->aux_data; - - va_start(ap, command); - newevil = va_arg(ap, int); - userinfo = va_arg(ap, struct aim_userinfo_s *); - va_end(ap); - - serv_got_eviled(gc, (userinfo && userinfo->sn[0]) ? userinfo->sn : NULL, newevil / 10); - - return 1; -} - -int gaim_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - struct gaim_connection *gc = sess->aux_data; - switch (command->conn->type) { - case AIM_CONN_TYPE_BOS: - aim_bos_ackrateresp(sess, command->conn); - aim_bos_reqpersonalinfo(sess, command->conn); - aim_bos_reqlocaterights(sess, command->conn); - aim_bos_setprofile(sess, command->conn, gc->user->user_info, NULL, gaim_caps); - aim_bos_reqbuddyrights(sess, command->conn); - - account_online(gc); - serv_finish_login(gc); - - if (bud_list_cache_exists(gc)) - do_import(NULL, gc); - - debug_printf("buddy list loaded\n"); - - aim_addicbmparam(sess, command->conn); - aim_bos_reqicbmparaminfo(sess, command->conn); - - aim_bos_reqrights(sess, command->conn); - aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS); - aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE | - AIM_PRIVFLAGS_ALLOWMEMBERSINCE); - - break; - case AIM_CONN_TYPE_AUTH: - aim_bos_ackrateresp(sess, command->conn); - aim_auth_clientready(sess, command->conn); - debug_printf("connected to auth (admin)\n"); - break; - default: - debug_printf("got rate response for unhandled connection type %04x\n", - command->conn->type); - break; - } - - return 1; -} - -int gaim_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - if (command->data) { - debug_printf("minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10)); - } else - debug_printf("NULL minimum report interval!\n"); - return 1; -} - -int gaim_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - unsigned short maxbuddies, maxwatchers; - - va_start(ap, command); - maxbuddies = (unsigned short)va_arg(ap, unsigned int); - maxwatchers = (unsigned short)va_arg(ap, unsigned int); - va_end(ap); - - debug_printf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers); - - return 1; -} - -int gaim_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - unsigned short maxpermits, maxdenies; - va_list ap; - - va_start(ap, command); - maxpermits = (unsigned short)va_arg(ap, unsigned int); - maxdenies = (unsigned short)va_arg(ap, unsigned int); - va_end(ap); - - debug_printf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies); - - aim_bos_clientready(sess, command->conn); - - aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); - - return 1; -} - -int gaim_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - char *address, *SNs; - int i, num; - char *buf; - int at = 0, len; - - va_start(ap, command); - address = va_arg(ap, char *); - num = va_arg(ap, int); - SNs = va_arg(ap, char *); - va_end(ap); - - len = num * (MAXSNLEN + 1) + 1024; - buf = g_malloc(len); - at += g_snprintf(buf + at, len - at, "<B>%s has the following screen names:</B><BR>", address); - for (i = 0; i < num; i++) - at += g_snprintf(buf + at, len - at, "%s<BR>", &SNs[i * (MAXSNLEN + 1)]); - g_show_info_text(buf); - g_free(buf); - - return 1; -} - -int gaim_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - char *address; - char buf[BUF_LONG]; - - va_start(ap, command); - address = va_arg(ap, char *); - va_end(ap); - - g_snprintf(buf, sizeof(buf), "No results found for email address %s", address); - do_error_dialog(buf, _("Error")); - - return 1; -} - -int gaim_account_confirm(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - int status; - va_list ap; - char msg[256]; - struct gaim_connection *gc = sess->aux_data; - - va_start(ap, command); - status = va_arg(ap, int); /* status code of confirmation request */ - va_end(ap); - - debug_printf("account confirmation returned status 0x%04x (%s)\n", status, - status ? "email sent" : "unknown"); - if (status) { - g_snprintf(msg, sizeof(msg), "You should receive an email asking to confirm %s.", - gc->username); - do_error_dialog(msg, "Confirm"); - } - - return 1; -} - -int gaim_info_change(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - unsigned short change = 0; - int perms, type, length, str; - char *val; - va_list ap; - char buf[BUF_LONG]; - struct gaim_connection *gc = sess->aux_data; - - va_start(ap, command); - perms = va_arg(ap, int); - type = va_arg(ap, int); - length = va_arg(ap, int); - val = va_arg(ap, char *); - str = va_arg(ap, int); - va_end(ap); - - if (aimutil_get16(command->data+2) == 0x0005) - change = 1; - - debug_printf("info%s: perms = %d, type = %x, length = %d, val = %s\n", - change ? " change" : "", perms, type, length, str ? val : "(not string)"); - - if ((type == 0x0011) && str) { - g_snprintf(buf, sizeof(buf), "The email address for %s is %s", gc->username, val); - do_error_dialog(buf, "Email"); - } - - return 1; -} - -static void oscar_keepalive(struct gaim_connection *gc) { - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; - aim_flap_nop(odata->sess, odata->conn); -} - -static char *oscar_name() { - return "Oscar"; -} - -static void oscar_send_im(struct gaim_connection *gc, char *name, char *message, int away) { - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; - struct direct_im *dim = find_direct_im(odata, name); - if (dim) { - aim_send_im_direct(odata->sess, dim->conn, message); - } else { - if (away) - aim_send_im(odata->sess, odata->conn, name, AIM_IMFLAGS_AWAY, message); - else { - int flags = AIM_IMFLAGS_ACK; -#if USE_PIXBUF - GSList *h = odata->hasicons; - struct icon_req *ir; - char *who = normalize(name); - while (h) { - ir = h->data; - if (ir->request && !strcmp(who, ir->user)) - break; - h = h->next; - } - if (h) { - ir->request = FALSE; - flags |= AIM_IMFLAGS_BUDDYREQ; - debug_printf("sending buddy icon request with message\n"); - } -#endif - aim_send_im(odata->sess, odata->conn, name, flags, message); - } - } -} - -static void oscar_get_info(struct gaim_connection *g, char *name) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_GENERALINFO); -} - -static void oscar_get_away_msg(struct gaim_connection *g, char *name) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_AWAYMESSAGE); -} - -static void oscar_set_dir(struct gaim_connection *g, char *first, char *middle, char *last, - char *maiden, char *city, char *state, char *country, int web) { - /* FIXME : some of these things are wrong, but i'm lazy */ - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - aim_setdirectoryinfo(odata->sess, odata->conn, first, middle, last, - maiden, NULL, NULL, city, state, NULL, 0, web); -} - - -static void oscar_set_idle(struct gaim_connection *g, int time) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - aim_bos_setidle(odata->sess, odata->conn, time); -} - -static void oscar_set_info(struct gaim_connection *g, char *info) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - char inforeal[1025], away[1025]; - g_snprintf(inforeal, sizeof(inforeal), "%s", info); - if (g->away) - g_snprintf(away, sizeof(away), "%s", g->away); - if (strlen(info) > 1024) - do_error_dialog("Maximum info length (1024) exceeded, truncating", "Info Too Long"); - aim_bos_setprofile(odata->sess, odata->conn, inforeal, g->away ? NULL : "", gaim_caps); -} - -static void oscar_set_away(struct gaim_connection *g, char *state, char *message) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - char info[1025], away[1025]; - g_snprintf(info, sizeof(info), "%s", g->user->user_info); - if (message) - g_snprintf(away, sizeof(away), "%s", message); - aim_bos_setprofile(odata->sess, odata->conn, NULL, message ? away : "", gaim_caps); - if (g->away) - g_free (g->away); - g->away = NULL; - if (message) { - if (strlen(message) > 1024) - do_error_dialog("Maximum away length (1024) exceeded, truncating", - "Info Too Long"); - g->away = g_strdup (message); - } -} - -static void oscar_warn(struct gaim_connection *g, char *name, int anon) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - aim_send_warning(odata->sess, odata->conn, name, anon); -} - -static void oscar_dir_search(struct gaim_connection *g, char *first, char *middle, char *last, - char *maiden, char *city, char *state, char *country, char *email) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - if (strlen(email)) - aim_usersearch_address(odata->sess, odata->conn, email); -} - -static void oscar_add_buddy(struct gaim_connection *g, char *name) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - aim_add_buddy(odata->sess, odata->conn, name); -} - -static void oscar_add_buddies(struct gaim_connection *g, GList *buddies) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - char buf[MSG_LEN]; - int n = 0; - while (buddies) { - if (n > MSG_LEN - 18) { - aim_bos_setbuddylist(odata->sess, odata->conn, buf); - n = 0; - } - n += g_snprintf(buf + n, sizeof(buf) - n, "%s&", (char *)buddies->data); - buddies = buddies->next; - } - aim_bos_setbuddylist(odata->sess, odata->conn, buf); -} - -static void oscar_remove_buddy(struct gaim_connection *g, char *name) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - aim_remove_buddy(odata->sess, odata->conn, name); -} - -static void oscar_join_chat(struct gaim_connection *g, int exchange, char *name) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - struct aim_conn_t *cur = NULL; - if (!name) { - if (!join_chat_entry || !join_chat_spin) - return; - name = gtk_entry_get_text(GTK_ENTRY(join_chat_entry)); - exchange = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(join_chat_spin)); - if (!name || !strlen(name)) - return; - } - debug_printf("Attempting to join chat room %s.\n", name); - if ((cur = aim_getconn_type(odata->sess, AIM_CONN_TYPE_CHATNAV))) { - debug_printf("chatnav exists, creating room\n"); - aim_chatnav_createroom(odata->sess, cur, name, exchange); - } else { - /* this gets tricky */ - debug_printf("chatnav does not exist, opening chatnav\n"); - odata->create_exchange = exchange; - odata->create_name = g_strdup(name); - aim_bos_reqservice(odata->sess, odata->conn, AIM_CONN_TYPE_CHATNAV); - } -} - -static void des_jc() -{ - join_chat_entry = NULL; - join_chat_spin = NULL; -} - -static void oscar_draw_join_chat(struct gaim_connection *gc, GtkWidget *fbox) { - GtkWidget *label; - GtkWidget *rowbox; - GtkObject *adjust; - - rowbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0); - gtk_widget_show(rowbox); - - label = gtk_label_new(_("Join what group:")); - gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); - gtk_signal_connect(GTK_OBJECT(label), "destroy", GTK_SIGNAL_FUNC(des_jc), NULL); - gtk_widget_show(label); - - join_chat_entry = gtk_entry_new(); - gtk_box_pack_start(GTK_BOX(rowbox), join_chat_entry, TRUE, TRUE, 0); - gtk_widget_grab_focus(join_chat_entry); - gtk_signal_connect(GTK_OBJECT(join_chat_entry), "activate", GTK_SIGNAL_FUNC(do_join_chat), NULL); - gtk_widget_show(join_chat_entry); - - rowbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0); - gtk_widget_show(rowbox); - - label = gtk_label_new(_("Exchange:")); - gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); - gtk_widget_show(label); - - adjust = gtk_adjustment_new(4, 4, 20, 1, 10, 10); - join_chat_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); - gtk_widget_set_usize(join_chat_spin, 50, -1); - gtk_box_pack_start(GTK_BOX(rowbox), join_chat_spin, FALSE, FALSE, 0); - gtk_widget_show(join_chat_spin); -} - -static void oscar_chat_invite(struct gaim_connection *g, int id, char *message, char *name) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - struct chat_connection *ccon = find_oscar_chat(g, id); - - if (!ccon) - return; - - aim_chat_invite(odata->sess, odata->conn, name, message ? message : "", - ccon->exchange, ccon->name, 0x0); -} - -static void oscar_chat_leave(struct gaim_connection *g, int id) { - struct oscar_data *odata = g ? (struct oscar_data *)g->proto_data : NULL; - GSList *bcs = g->buddy_chats; - struct conversation *b = NULL; - struct chat_connection *c = NULL; - int count = 0; - - while (bcs) { - count++; - b = (struct conversation *)bcs->data; - if (id == b->id) - break; - bcs = bcs->next; - b = NULL; - } - - if (!b) - return; - - debug_printf("Attempting to leave room %s (currently in %d rooms)\n", b->name, count); - - c = find_oscar_chat(g, b->id); - if (c != NULL) { - if (odata) - odata->oscar_chats = g_slist_remove(odata->oscar_chats, c); - if (c->inpa > 0) - gdk_input_remove(c->inpa); - if (g && odata->sess) - aim_conn_kill(odata->sess, &c->conn); - g_free(c->name); - g_free(c->show); - g_free(c); - } - /* we do this because with Oscar it doesn't tell us we left */ - serv_got_chat_left(g, b->id); -} - -static void oscar_chat_send(struct gaim_connection *g, int id, char *message) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - GSList *bcs = g->buddy_chats; - struct conversation *b = NULL; - struct chat_connection *c = NULL; - char *buf; - int i, j; - - while (bcs) { - b = (struct conversation *)bcs->data; - if (id == b->id) - break; - bcs = bcs->next; - b = NULL; - } - if (!b) - return; - - bcs = odata->oscar_chats; - while (bcs) { - c = (struct chat_connection *)bcs->data; - if (b == c->cnv) - break; - bcs = bcs->next; - c = NULL; - } - if (!c) - return; - - buf = g_malloc(strlen(message) * 4 + 1); - for (i = 0, j = 0; i < strlen(message); i++) { - if (message[i] == '\n') { - buf[j++] = '<'; - buf[j++] = 'B'; - buf[j++] = 'R'; - buf[j++] = '>'; - } else { - buf[j++] = message[i]; - } - } - buf[j] = '\0'; - aim_chat_send_im(odata->sess, c->conn, 0, buf, strlen(buf)); - g_free(buf); -} - -static char **oscar_list_icon(int uc) { - if (uc & UC_UNAVAILABLE) - return (char **)away_icon_xpm; - if (uc & UC_AOL) - return (char **)aol_icon_xpm; - if (uc & UC_NORMAL) - return (char **)free_icon_xpm; - if (uc & UC_ADMIN) - return (char **)admin_icon_xpm; - if (uc & UC_UNCONFIRMED) - return (char **)dt_icon_xpm; - return NULL; -} - -static void oscar_info(GtkObject *obj, char *who) { - struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(obj); - serv_get_info(gc, who); -} - -static void oscar_away_msg(GtkObject *obj, char *who) { - struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(obj); - serv_get_away_msg(gc, who); -} - -static int gaim_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct aim_directim_priv *priv; - struct aim_conn_t *newconn; - struct direct_im *dim; - char buf[256]; - - va_start(ap, command); - newconn = va_arg(ap, struct aim_conn_t *); - va_end(ap); - - priv = (struct aim_directim_priv *)newconn->priv; - - debug_printf("DirectIM: initiate success to %s\n", priv->sn); - dim = find_direct_im(od, priv->sn); - - dim->cnv = find_conversation(priv->sn); - if (!dim->cnv) dim->cnv = new_conversation(priv->sn); - gtk_signal_connect(GTK_OBJECT(dim->cnv->window), "destroy", - GTK_SIGNAL_FUNC(delete_direct_im), dim); - gdk_input_remove(dim->watcher); - dim->conn = newconn; - dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, dim->conn); - g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), priv->sn); - write_to_conv(dim->cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); - - aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, - gaim_directim_incoming, 0); - aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, - gaim_directim_disconnect, 0); - aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, - gaim_directim_typing, 0); - - return 1; -} - -static int gaim_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - char *msg = NULL; - struct aim_conn_t *conn; - struct aim_directim_priv *priv; - struct gaim_connection *gc = sess->aux_data; - - va_start(ap, command); - conn = va_arg(ap, struct aim_conn_t *); - msg = va_arg(ap, char *); - va_end(ap); - - if (!(priv = conn->priv)) { - return -1; - } - - debug_printf("Got DirectIM message from %s\n", priv->sn); - - serv_got_im(gc, priv->sn, msg, 0, time((time_t)NULL)); - - return 1; -} - -static int gaim_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - struct aim_conn_t *conn; - char *sn; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct direct_im *dim; - char buf[256]; - - va_start(ap, command); - conn = va_arg(ap, struct aim_conn_t *); - sn = va_arg(ap, char *); - va_end(ap); - - debug_printf("%s disconnected Direct IM.\n", sn); - - dim = find_direct_im(od, sn); - od->direct_ims = g_slist_remove(od->direct_ims, dim); - gdk_input_remove(dim->watcher); - gtk_signal_disconnect_by_data(GTK_OBJECT(dim->cnv->window), dim); - - g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), sn); - if (dim->cnv) - write_to_conv(dim->cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); - - aim_conn_kill(sess, &conn); - - return 1; -} - -static int gaim_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - va_list ap; - struct aim_conn_t *conn; - struct aim_directim_priv *priv; - - va_start(ap, command); - conn = va_arg(ap, struct aim_conn_t *); - va_end(ap); - - if (!(priv = conn->priv)) { - return -1; - } - - /* I had to leave this. It's just too funny. It reminds me of my sister. */ - debug_printf("ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn); - - return 1; -} - -struct ask_do_dir_im { - char *who; - struct gaim_connection *gc; -}; - -static void oscar_cancel_direct_im(GtkObject *obj, struct ask_do_dir_im *data) { - g_free(data); -} - -static void oscar_direct_im(GtkObject *obj, struct ask_do_dir_im *data) { - struct gaim_connection *gc = data->gc; - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - struct direct_im *dim; - - dim = find_direct_im(od, data->who); - if (dim) { - do_error_dialog("Direct IM request already pending.", "Unable"); - return; - } - dim = g_new0(struct direct_im, 1); - dim->gc = gc; - g_snprintf(dim->name, sizeof dim->name, "%s", data->who); - - dim->conn = aim_directim_initiate(od->sess, od->conn, NULL, data->who); - if (dim->conn != NULL) { - od->direct_ims = g_slist_append(od->direct_ims, dim); - dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - oscar_callback, dim->conn); - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, - gaim_directim_initiate, 0); - } else { - do_error_dialog(_("Unable to open Direct IM"), _("Error")); - g_free(dim); - } -} - -static void oscar_ask_direct_im(GtkObject *m, gchar *who) { - char buf[BUF_LONG]; - struct ask_do_dir_im *data = g_new0(struct ask_do_dir_im, 1); - data->who = who; - data->gc = gtk_object_get_user_data(m); - g_snprintf(buf, sizeof(buf), _("You have selected to open a Direct IM connection with %s." - " Doing this will let them see your IP address, and may be" - " a security risk. Do you wish to continue?"), who); - do_ask_dialog(buf, data, oscar_direct_im, oscar_cancel_direct_im); -} - -static void oscar_buddy_menu(GtkWidget *menu, struct gaim_connection *gc, char *who) { - GtkWidget *button; - char *n = g_strdup(normalize(gc->username)); - - button = gtk_menu_item_new_with_label(_("Get Info")); - gtk_signal_connect(GTK_OBJECT(button), "activate", - GTK_SIGNAL_FUNC(oscar_info), who); - gtk_object_set_user_data(GTK_OBJECT(button), gc); - gtk_menu_append(GTK_MENU(menu), button); - gtk_widget_show(button); - - button = gtk_menu_item_new_with_label(_("Get Away Msg")); - gtk_signal_connect(GTK_OBJECT(button), "activate", - GTK_SIGNAL_FUNC(oscar_away_msg), who); - gtk_object_set_user_data(GTK_OBJECT(button), gc); - gtk_menu_append(GTK_MENU(menu), button); - gtk_widget_show(button); - - if (strcmp(n, normalize(who))) { - button = gtk_menu_item_new_with_label(_("Direct IM")); - gtk_signal_connect(GTK_OBJECT(button), "activate", - GTK_SIGNAL_FUNC(oscar_ask_direct_im), who); - gtk_object_set_user_data(GTK_OBJECT(button), gc); - gtk_menu_append(GTK_MENU(menu), button); - gtk_widget_show(button); - } - g_free(n); -} - - -/* weeee */ -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)); - } else if (entrynum == USEROPT_AUTHPORT) { - g_snprintf(user->proto_opt[USEROPT_AUTHPORT], - sizeof(user->proto_opt[USEROPT_AUTHPORT]), "%s", gtk_entry_get_text(entry)); - } -} - -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; - - 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_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("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); - 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]); - } else - gtk_entry_set_text(GTK_ENTRY(entry), "login.oscar.aol.com"); - 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("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 *)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_widget_show(entry); -} - -static void oscar_set_permit_deny(struct gaim_connection *gc) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - GSList *list; - char buf[MAXMSGLEN]; - int at; - - switch(gc->permdeny) { - case 1: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, gc->username); - break; - case 2: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, gc->username); - break; - case 3: - list = gc->permit; - at = 0; - while (list) { - at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data); - list = list->next; - } - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, buf); - break; - case 4: - list = gc->deny; - at = 0; - while (list) { - at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data); - list = list->next; - } - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, buf); - break; - default: - break; - } -} - -static void oscar_add_permit(struct gaim_connection *gc, char *who) { - if (gc->permdeny != 3) return; - oscar_set_permit_deny(gc); -} - -static void oscar_add_deny(struct gaim_connection *gc, char *who) { - if (gc->permdeny != 4) return; - oscar_set_permit_deny(gc); -} - -static void oscar_rem_permit(struct gaim_connection *gc, char *who) { - if (gc->permdeny != 3) return; - oscar_set_permit_deny(gc); -} - -static void oscar_rem_deny(struct gaim_connection *gc, char *who) { - if (gc->permdeny != 4) return; - oscar_set_permit_deny(gc); -} - -static void oscar_draw_new_user(GtkWidget *box) -{ - GtkWidget *label; - - label = gtk_label_new(_("Unfortunately, currently Oscar only allows new user registration by " - "going to http://aim.aol.com/aimnew/Aim/register.adp?promo=106723&pageset=Aim&client=no" - ". Clicking the Register button will open the URL for you.")); - gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5); - gtk_widget_show(label); -} - -static void oscar_do_new_user() -{ - open_url(NULL, "http://aim.aol.com/aimnew/Aim/register.adp?promo=106723&pageset=Aim&client=no"); -} - -static GList *oscar_away_states() -{ - return g_list_append(NULL, GAIM_AWAY_CUSTOM); -} - -static void oscar_do_action(struct gaim_connection *gc, char *act) -{ - struct oscar_data *od = gc->proto_data; - struct aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH); - - if (!strcmp(act, "Set User Info")) { - show_set_info(gc); - } else if (!strcmp(act, "Change Password")) { - show_change_passwd(gc); - } else if (!strcmp(act, "Confirm Account")) { - if (!conn) { - od->conf = TRUE; - aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); - } else - aim_auth_reqconfirm(od->sess, conn); - } else if (!strcmp(act, "Change Email")) { - } else if (!strcmp(act, "Display Current Registered Address")) { - if (!conn) { - od->reqemail = TRUE; - aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); - } else - aim_auth_getinfo(od->sess, conn, 0x11); - } else if (!strcmp(act, "Search for Buddy by Email")) { - show_find_email(gc); - } -} - -static GList *oscar_actions() -{ - GList *m = NULL; - - m = g_list_append(m, "Set User Info"); - m = g_list_append(m, NULL); - m = g_list_append(m, "Change Password"); - m = g_list_append(m, "Confirm Account"); - /* - m = g_list_append(m, "Change Email"); - */ - m = g_list_append(m, "Display Current Registered Address"); - m = g_list_append(m, NULL); - m = g_list_append(m, "Search for Buddy by Email"); - - return m; -} - -static void oscar_change_passwd(struct gaim_connection *gc, char *old, char *new) -{ - struct oscar_data *od = gc->proto_data; - if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) { - od->chpass = TRUE; - od->oldp = g_strdup(old); - od->newp = g_strdup(new); - aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); - } else { - aim_auth_changepasswd(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH), - new, old); - } -} - -static void oscar_insert_convo(struct gaim_connection *gc, struct conversation *c) -{ -#if USE_PIXBUF - struct oscar_data *od = gc->proto_data; - GSList *h = od->hasicons; - struct icon_req *ir = NULL; - char *who = normalize(c->name); - - GdkPixbufLoader *load; - GList *frames; - GdkPixbuf *buf; - GdkPixmap *pm; - GdkBitmap *bm; - - while (h) { - ir = h->data; - if (!strcmp(who, ir->user)) - break; - h = h->next; - } - if (!h || !ir->data) - return; - - ir->cnv = c; - - load = gdk_pixbuf_loader_new(); - gdk_pixbuf_loader_write(load, ir->data, ir->length); - ir->anim = gdk_pixbuf_loader_get_animation(load); - - if (ir->anim) { - frames = gdk_pixbuf_animation_get_frames(ir->anim); - buf = gdk_pixbuf_frame_get_pixbuf(frames->data); - gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0); - - if (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1) { - int delay = MAX(gdk_pixbuf_frame_get_delay_time(frames->data), 13); - ir->curframe = 1; - ir->timer = gtk_timeout_add(delay * 10, redraw_anim, ir); - } - } else { - ir->unanim = gdk_pixbuf_loader_get_pixbuf(load); - if (!ir->unanim) { - gdk_pixbuf_loader_close(load); - return; - } - gdk_pixbuf_render_pixmap_and_mask(ir->unanim, &pm, &bm, 0); - } - - ir->pix = gtk_pixmap_new(pm, bm); - gtk_box_pack_start(GTK_BOX(c->bbox), ir->pix, FALSE, FALSE, 5); - if (ir->anim && (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1)) - gtk_widget_set_usize(ir->pix, gdk_pixbuf_animation_get_width(ir->anim), - gdk_pixbuf_animation_get_height(ir->anim)); - gtk_widget_show(ir->pix); - gdk_pixmap_unref(pm); - if (bm) - gdk_bitmap_unref(bm); - - gdk_pixbuf_loader_close(load); -#endif -} - -static void oscar_remove_convo(struct gaim_connection *gc, struct conversation *c) -{ -#if USE_PIXBUF - struct oscar_data *od = gc->proto_data; - GSList *h = od->hasicons; - struct icon_req *ir = NULL; - char *who = normalize(c->name); - - while (h) { - ir = h->data; - if (!strcmp(who, ir->user)) - break; - h = h->next; - } - if (!h || !ir->data) - return; - - if (ir->cnv && ir->pix) { - gtk_container_remove(GTK_CONTAINER(ir->cnv->bbox), ir->pix); - ir->pix = NULL; - ir->cnv = NULL; - } - - if (ir->anim) { - gdk_pixbuf_animation_unref(ir->anim); - ir->anim = NULL; - } else if (ir->unanim) { - gdk_pixbuf_unref(ir->unanim); - ir->unanim = NULL; - } - - ir->curframe = 0; - - if (ir->timer) - gtk_timeout_remove(ir->timer); - ir->timer = 0; -#endif -} - -void oscar_init(struct prpl *ret) { - ret->protocol = PROTO_OSCAR; - ret->options = OPT_PROTO_HTML | OPT_PROTO_CORRECT_TIME; - ret->name = oscar_name; - ret->list_icon = oscar_list_icon; - ret->away_states = oscar_away_states; - ret->actions = oscar_actions; - ret->do_action = oscar_do_action; - ret->buddy_menu = oscar_buddy_menu; - ret->user_opts = oscar_user_opts; - ret->draw_new_user = oscar_draw_new_user; - ret->do_new_user = oscar_do_new_user; - ret->insert_convo = oscar_insert_convo; - ret->remove_convo = oscar_remove_convo; - ret->login = oscar_login; - ret->close = oscar_close; - ret->send_im = oscar_send_im; - ret->set_info = oscar_set_info; - ret->get_info = oscar_get_info; - ret->set_away = oscar_set_away; - ret->get_away_msg = oscar_get_away_msg; - ret->set_dir = oscar_set_dir; - ret->get_dir = NULL; /* Oscar really doesn't have this */ - ret->dir_search = oscar_dir_search; - ret->set_idle = oscar_set_idle; - ret->change_passwd = oscar_change_passwd; - ret->add_buddy = oscar_add_buddy; - ret->add_buddies = oscar_add_buddies; - ret->remove_buddy = oscar_remove_buddy; - ret->add_permit = oscar_add_permit; - ret->add_deny = oscar_add_deny; - ret->rem_permit = oscar_rem_permit; - ret->rem_deny = oscar_rem_deny; - ret->set_permit_deny = oscar_set_permit_deny; - ret->warn = oscar_warn; - ret->accept_chat = NULL; /* oscar doesn't have accept, it just joins */ - ret->join_chat = oscar_join_chat; - ret->draw_join_chat = oscar_draw_join_chat; - ret->chat_invite = oscar_chat_invite; - ret->chat_leave = oscar_chat_leave; - ret->chat_whisper = NULL; - ret->chat_send = oscar_chat_send; - ret->keepalive = oscar_keepalive; -}
--- a/src/toc.c Tue Jul 31 01:58:50 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1841 +0,0 @@ -/* - * gaim - * - * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - - - -#ifdef HAVE_CONFIG_H -#include "../config.h" -#endif -#include <netdb.h> -#include <gtk/gtk.h> -#include <unistd.h> -#include <errno.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <time.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "prpl.h" -#include "multi.h" -#include "gaim.h" -#include "proxy.h" - -#include "pixmaps/admin_icon.xpm" -#include "pixmaps/aol_icon.xpm" -#include "pixmaps/away_icon.xpm" -#include "pixmaps/dt_icon.xpm" -#include "pixmaps/free_icon.xpm" - -#define REVISION "penguin" - -#define TYPE_SIGNON 1 -#define TYPE_DATA 2 -#define TYPE_ERROR 3 -#define TYPE_SIGNOFF 4 -#define TYPE_KEEPALIVE 5 - -#define FLAPON "FLAPON\r\n\r\n" -#define ROAST "Tic/Toc" - -#define TOC_HOST "toc.oscar.aol.com" -#define TOC_PORT 9898 -#define AUTH_HOST "login.oscar.aol.com" -#define AUTH_PORT 5190 -#define LANGUAGE "english" - -#define STATE_OFFLINE 0 -#define STATE_FLAPON 1 -#define STATE_SIGNON_REQUEST 2 -#define STATE_ONLINE 3 -#define STATE_PAUSE 4 - -#define VOICE_UID "09461341-4C7F-11D1-8222-444553540000" -#define FILE_SEND_UID "09461343-4C7F-11D1-8222-444553540000" -#define IMAGE_UID "09461345-4C7F-11D1-8222-444553540000" -#define B_ICON_UID "09461346-4C7F-11D1-8222-444553540000" -#define STOCKS_UID "09461347-4C7F-11D1-8222-444553540000" -#define FILE_GET_UID "09461348-4C7F-11D1-8222-444553540000" -#define GAMES_UID "0946134a-4C7F-11D1-8222-444553540000" - -struct ft_request { - struct gaim_connection *gc; - char *user; - char UID[2048]; - char *cookie; - char *ip; - int port; - char *message; - char *filename; - int files; - int size; -}; - -struct buddy_icon { - guint32 hash; - guint32 len; - time_t time; - void *data; -}; - -struct toc_data { - int toc_fd; - int seqno; - int state; -}; - -struct sflap_hdr { - unsigned char ast; - unsigned char type; - unsigned short seqno; - unsigned short len; -}; - -struct signon { - unsigned int ver; - unsigned short tag; - unsigned short namelen; - char username[80]; -}; - -/* constants to identify proto_opts */ -#define USEROPT_AUTH 0 -#define USEROPT_AUTHPORT 1 - -static GtkWidget *join_chat_spin = NULL; -static GtkWidget *join_chat_entry = NULL; - -static void toc_login_callback(gpointer, gint, GdkInputCondition); -static void toc_callback(gpointer, gint, GdkInputCondition); -static unsigned char *roast_password(char *); -static void accept_file_dialog(struct ft_request *); - -/* ok. this function used to take username/password, and return 0 on success. - * now, it takes username/password, and returns NULL on error or a new gaim_connection - * on success. */ -static void toc_login(struct aim_user *user) -{ - struct gaim_connection *gc; - struct toc_data *tdt; - char buf[80]; - - gc = new_gaim_conn(user); - gc->proto_data = tdt = g_new0(struct toc_data, 1); - - g_snprintf(buf, sizeof buf, "Looking up %s", - user->proto_opt[USEROPT_AUTH][0] ? user->proto_opt[USEROPT_AUTH] : TOC_HOST); - set_login_progress(gc, 1, buf); - - debug_printf("* Client connects to TOC\n"); - tdt->toc_fd = - proxy_connect(user->proto_opt[USEROPT_AUTH][0] ? user->proto_opt[USEROPT_AUTH] : TOC_HOST, - user->proto_opt[USEROPT_AUTHPORT][0] ? - atoi(user->proto_opt[USEROPT_AUTHPORT]) : TOC_PORT, - toc_login_callback, gc); - - if (!user->gc || (tdt->toc_fd < 0)) { - g_snprintf(buf, sizeof(buf), "Connect to %s failed", user->proto_opt[USEROPT_AUTH]); - hide_login_progress(gc, buf); - signoff(gc); - return; - } -} - -static void toc_login_callback(gpointer data, gint source, GdkInputCondition cond) -{ - struct gaim_connection *gc = data; - struct toc_data *tdt; - char buf[80]; - - if (!g_slist_find(connections, data)) { - close(source); - return; - } - - tdt = gc->proto_data; - - if (source == -1) { - /* we didn't successfully connect. tdt->toc_fd is valid here */ - hide_login_progress(gc, "Unable to connect."); - signoff(gc); - return; - } - - if (tdt->toc_fd == 0) - tdt->toc_fd = source; - - debug_printf("* Client sends \"FLAPON\\r\\n\\r\\n\"\n"); - if (write(tdt->toc_fd, FLAPON, strlen(FLAPON)) < 0) { - hide_login_progress(gc, "Disconnected."); - signoff(gc); - return; - } - tdt->state = STATE_FLAPON; - - /* i know a lot of people like to look at gaim to see how TOC works. so i'll comment - * on what this does. it's really simple. when there's data ready to be read from the - * toc_fd file descriptor, toc_callback is called, with gc passed as its data arg. */ - gc->inpa = gdk_input_add(tdt->toc_fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, toc_callback, gc); - - g_snprintf(buf, sizeof(buf), "Signon: %s", gc->username); - set_login_progress(gc, 2, buf); -} - -static void toc_close(struct gaim_connection *gc) -{ - if (gc->inpa > 0) - gdk_input_remove(gc->inpa); - gc->inpa = 0; - close(((struct toc_data *)gc->proto_data)->toc_fd); - g_free(gc->proto_data); -} - -static int sflap_send(struct gaim_connection *gc, char *buf, int olen, int type) -{ - int len; - int slen = 0; - struct sflap_hdr hdr; - char obuf[MSG_LEN]; - struct toc_data *tdt = (struct toc_data *)gc->proto_data; - - if (tdt->state == STATE_PAUSE) - /* TOC has given us the PAUSE message; sending could cause a disconnect - * so we just return here like everything went through fine */ - return 0; - - /* One _last_ 2048 check here! This shouldn't ever - * get hit though, hopefully. If it gets hit on an IM - * It'll lose the last " and the message won't go through, - * but this'll stop a segfault. */ - if (strlen(buf) > (MSG_LEN - sizeof(hdr))) { - debug_printf("message too long, truncating\n"); - buf[MSG_LEN - sizeof(hdr) - 3] = '"'; - buf[MSG_LEN - sizeof(hdr) - 2] = '\0'; - } - - if (olen < 0) - len = escape_message(buf); - else - len = olen; - hdr.ast = '*'; - hdr.type = type; - hdr.seqno = htons(tdt->seqno++ & 0xffff); - hdr.len = htons(len + (type == TYPE_SIGNON ? 0 : 1)); - - memcpy(obuf, &hdr, sizeof(hdr)); - slen += sizeof(hdr); - memcpy(&obuf[slen], buf, len); - slen += len; - if (type != TYPE_SIGNON) { - obuf[slen] = '\0'; - slen += 1; - } - - return write(tdt->toc_fd, obuf, slen); -} - -static int wait_reply(struct gaim_connection *gc, char *buffer, size_t buflen) -{ - struct toc_data *tdt = (struct toc_data *)gc->proto_data; - struct sflap_hdr *hdr; - int ret; - - if (read(tdt->toc_fd, buffer, sizeof(struct sflap_hdr)) < 0) { - debug_printf("error, couldn't read flap header\n"); - return -1; - } - - hdr = (struct sflap_hdr *)buffer; - - if (buflen < ntohs(hdr->len)) { - /* fake like there's a read error */ - debug_printf("buffer too small (have %d, need %d)\n", buflen, ntohs(hdr->len)); - return -1; - } - - if (ntohs(hdr->len) > 0) { - int count = 0; - ret = 0; - do { - count += ret; - ret = read(tdt->toc_fd, - buffer + sizeof(struct sflap_hdr) + count, ntohs(hdr->len) - count); - } while (count + ret < ntohs(hdr->len) && ret > 0); - buffer[sizeof(struct sflap_hdr) + count + ret] = '\0'; - return ret; - } else - return 0; -} - -static unsigned char *roast_password(char *pass) -{ - /* Trivial "encryption" */ - static unsigned char rp[256]; - static char *roast = ROAST; - int pos = 2; - int x; - strcpy(rp, "0x"); - for (x = 0; (x < 150) && pass[x]; x++) - pos += sprintf(&rp[pos], "%02x", pass[x] ^ roast[x % strlen(roast)]); - rp[pos] = '\0'; - return rp; -} - -static void toc_got_info(gpointer data, char *url_text) -{ - if (!url_text) - return; - - g_show_info_text(url_text); -} - -static void toc_callback(gpointer data, gint source, GdkInputCondition condition) -{ - struct gaim_connection *gc = (struct gaim_connection *)data; - struct toc_data *tdt = (struct toc_data *)gc->proto_data; - struct sflap_hdr *hdr; - struct signon so; - char buf[8 * 1024], *c; - char snd[BUF_LEN * 2]; - - if (condition & GDK_INPUT_EXCEPTION) { - debug_printf("gdk_input exception! check internet connection\n"); - hide_login_progress(gc, _("Connection Closed")); - signoff(gc); - return; - } - - /* there's data waiting to be read, so read it. */ - if (wait_reply(gc, buf, 8 * 1024) <= 0) { - hide_login_progress(gc, _("Connection Closed")); - signoff(gc); - return; - } - - if (tdt->state == STATE_FLAPON) { - hdr = (struct sflap_hdr *)buf; - if (hdr->type != TYPE_SIGNON) - debug_printf("problem, hdr->type != TYPE_SIGNON\n"); - else - debug_printf("* TOC sends Client FLAP SIGNON\n"); - tdt->seqno = ntohs(hdr->seqno); - tdt->state = STATE_SIGNON_REQUEST; - - debug_printf("* Client sends TOC FLAP SIGNON\n"); - g_snprintf(so.username, sizeof(so.username), "%s", gc->username); - so.ver = htonl(1); - so.tag = htons(1); - so.namelen = htons(strlen(so.username)); - if (sflap_send(gc, (char *)&so, ntohs(so.namelen) + 8, TYPE_SIGNON) < 0) { - hide_login_progress(gc, _("Disconnected.")); - signoff(gc); - return; - } - - debug_printf("* Client sends TOC \"toc_signon\" message\n"); - g_snprintf(snd, sizeof snd, "toc_signon %s %d %s %s %s \"%s\"", - AUTH_HOST, AUTH_PORT, normalize(gc->username), - roast_password(gc->password), LANGUAGE, REVISION); - if (sflap_send(gc, snd, -1, TYPE_DATA) < 0) { - hide_login_progress(gc, _("Disconnected.")); - signoff(gc); - return; - } - - set_login_progress(gc, 3, _("Waiting for reply...")); - return; - } - - if (tdt->state == STATE_SIGNON_REQUEST) { - debug_printf("* TOC sends client SIGN_ON reply\n"); - if (g_strncasecmp(buf + sizeof(struct sflap_hdr), "SIGN_ON", strlen("SIGN_ON"))) { - debug_printf("Didn't get SIGN_ON! buf was: %s\n", - buf + sizeof(struct sflap_hdr)); - hide_login_progress(gc, _("Authentication Failed")); - signoff(gc); - return; - } - /* we're supposed to check that it's really TOC v1 here but we know it is ;) */ - debug_printf("TOC version: %s\n", buf + sizeof(struct sflap_hdr) + 4); - - /* we used to check for the CONFIG here, but we'll wait until we've sent our - * version of the config and then the toc_init_done message. we'll come back to - * the callback in a better state if we get CONFIG anyway */ - - tdt->state = STATE_ONLINE; - - account_online(gc); - serv_finish_login(gc); - - do_import(0, gc); - - /* Client sends TOC toc_init_done message */ - debug_printf("* Client sends TOC toc_init_done message\n"); - g_snprintf(snd, sizeof snd, "toc_init_done"); - sflap_send(gc, snd, -1, TYPE_DATA); - - /* - g_snprintf(snd, sizeof snd, "toc_set_caps %s %s %s", - FILE_SEND_UID, FILE_GET_UID, B_ICON_UID); - */ - g_snprintf(snd, sizeof snd, "toc_set_caps %s %s", FILE_SEND_UID, FILE_GET_UID); - sflap_send(gc, snd, -1, TYPE_DATA); - - return; - } - - debug_printf("From TOC server: %s\n", buf + sizeof(struct sflap_hdr)); - - c = strtok(buf + sizeof(struct sflap_hdr), ":"); /* Ditch the first part */ - - if (!g_strcasecmp(c, "SIGN_ON")) { - /* we should only get here after a PAUSE */ - if (tdt->state != STATE_PAUSE) - debug_printf("got SIGN_ON but not PAUSE!\n"); - else { - tdt->state = STATE_ONLINE; - g_snprintf(snd, sizeof snd, "toc_signon %s %d %s %s %s \"%s\"", - AUTH_HOST, AUTH_PORT, normalize(gc->username), - roast_password(gc->password), LANGUAGE, REVISION); - if (sflap_send(gc, snd, -1, TYPE_DATA) < 0) { - hide_login_progress(gc, _("Disconnected.")); - signoff(gc); - return; - } - do_import(0, gc); - g_snprintf(snd, sizeof snd, "toc_init_done"); - sflap_send(gc, snd, -1, TYPE_DATA); - do_error_dialog(_("TOC has come back from its pause. You may now send" - " messages again."), _("TOC Resume")); - } - } else if (!strcasecmp(c, "CONFIG")) { - c = strtok(NULL, ":"); - parse_toc_buddy_list(gc, c, 0); - } else if (!strcasecmp(c, "NICK")) { - /* ignore NICK so that things get imported/exported properly - c = strtok(NULL, ":"); - g_snprintf(gc->username, sizeof(gc->username), "%s", c); - */ - } else if (!strcasecmp(c, "IM_IN")) { - char *away, *message; - int a = 0; - - c = strtok(NULL, ":"); - away = strtok(NULL, ":"); - - message = away; - while (*message && (*message != ':')) - message++; - message++; - - a = (away && (*away == 'T')) ? 1 : 0; - - serv_got_im(gc, c, message, a, time((time_t)NULL)); - } else if (!strcasecmp(c, "UPDATE_BUDDY")) { - char *l, *uc; - int logged, evil, idle, type = 0; - time_t signon, time_idle; - - c = strtok(NULL, ":"); /* name */ - l = strtok(NULL, ":"); /* online */ - sscanf(strtok(NULL, ":"), "%d", &evil); - sscanf(strtok(NULL, ":"), "%ld", &signon); - sscanf(strtok(NULL, ":"), "%d", &idle); - uc = strtok(NULL, ":"); - - logged = (l && (*l == 'T')) ? 1 : 0; - - if (uc[0] == 'A') - type |= UC_AOL; - switch (uc[1]) { - case 'A': - type |= UC_ADMIN; - break; - case 'U': - type |= UC_UNCONFIRMED; - break; - case 'O': - type |= UC_NORMAL; - break; - default: - break; - } - if (uc[2] == 'U') - type |= UC_UNAVAILABLE; - - if (idle) { - time(&time_idle); - time_idle -= idle * 60; - } else - time_idle = 0; - - serv_got_update(gc, c, logged, evil, signon, time_idle, type, 0); - } else if (!strcasecmp(c, "ERROR")) { - c = strtok(NULL, ":"); - show_error_dialog(c); - } else if (!strcasecmp(c, "EVILED")) { - int lev; - char *name; - - sscanf(strtok(NULL, ":"), "%d", &lev); - name = strtok(NULL, ":"); - - serv_got_eviled(gc, name, lev); - } else if (!strcasecmp(c, "CHAT_JOIN")) { - char *name; - int id; - - sscanf(strtok(NULL, ":"), "%d", &id); - name = strtok(NULL, ":"); - - serv_got_joined_chat(gc, id, name); - } else if (!strcasecmp(c, "CHAT_IN")) { - int id, w; - char *m, *who, *whisper; - - sscanf(strtok(NULL, ":"), "%d", &id); - who = strtok(NULL, ":"); - whisper = strtok(NULL, ":"); - m = whisper; - while (*m && (*m != ':')) - m++; - m++; - - w = (whisper && (*whisper == 'T')) ? 1 : 0; - - serv_got_chat_in(gc, id, who, w, m, time((time_t)NULL)); - } else if (!strcasecmp(c, "CHAT_UPDATE_BUDDY")) { - int id; - char *in, *buddy; - GSList *bcs = gc->buddy_chats; - struct conversation *b = NULL; - - sscanf(strtok(NULL, ":"), "%d", &id); - in = strtok(NULL, ":"); - - while (bcs) { - b = (struct conversation *)bcs->data; - if (id == b->id) - break; - bcs = bcs->next; - b = NULL; - } - - if (!b) - return; - - if (in && (*in == 'T')) - while ((buddy = strtok(NULL, ":")) != NULL) - add_chat_buddy(b, buddy); - else - while ((buddy = strtok(NULL, ":")) != NULL) - remove_chat_buddy(b, buddy); - } else if (!strcasecmp(c, "CHAT_INVITE")) { - char *name, *who, *message; - int id; - - name = strtok(NULL, ":"); - sscanf(strtok(NULL, ":"), "%d", &id); - who = strtok(NULL, ":"); - message = strtok(NULL, ":"); - - serv_got_chat_invite(gc, name, id, who, message); - } else if (!strcasecmp(c, "CHAT_LEFT")) { - GSList *bcs = gc->buddy_chats; - struct conversation *b = NULL; - int id; - - sscanf(strtok(NULL, ":"), "%d", &id); - - while (bcs) { - b = (struct conversation *)bcs->data; - if (id == b->id) - break; - b = NULL; - bcs = bcs->next; - } - - if (!b) - return; - - if (b->window) { - char error_buf[BUF_LONG]; - b->gc = NULL; - g_snprintf(error_buf, sizeof error_buf, _("You have been disconnected" - " from chat room %s."), b->name); - do_error_dialog(error_buf, _("Chat Error")); - } else - serv_got_chat_left(gc, id); - } else if (!strcasecmp(c, "GOTO_URL")) { - char *name, *url, tmp[256]; - - name = strtok(NULL, ":"); - url = strtok(NULL, ":"); - - g_snprintf(tmp, sizeof(tmp), "http://%s:%d/%s", - gc->user->proto_opt[USEROPT_AUTH][0] ? - gc->user->proto_opt[USEROPT_AUTH] : TOC_HOST, - gc->user->proto_opt[USEROPT_AUTHPORT][0] ? - atoi(gc->user->proto_opt[USEROPT_AUTHPORT]) : TOC_PORT, - url); - grab_url(tmp, toc_got_info, NULL); - } else if (!strcasecmp(c, "DIR_STATUS")) { - } else if (!strcasecmp(c, "ADMIN_NICK_STATUS")) { - } else if (!strcasecmp(c, "ADMIN_PASSWD_STATUS")) { - do_error_dialog(_("Password Change Successeful"), _("Gaim - Password Change")); - } else if (!strcasecmp(c, "PAUSE")) { - tdt->state = STATE_PAUSE; - do_error_dialog(_("TOC has sent a PAUSE command. When this happens, TOC ignores" - " any messages sent to it, and may kick you off if you send a" - " message. Gaim will prevent anything from going through. This" - " is only temporary, please be patient."), _("TOC Pause")); - } else if (!strcasecmp(c, "RVOUS_PROPOSE")) { - char *user, *uuid, *cookie; - int seq; - char *rip, *pip, *vip; - int port; - - user = strtok(NULL, ":"); - uuid = strtok(NULL, ":"); - cookie = strtok(NULL, ":"); - sscanf(strtok(NULL, ":"), "%d", &seq); - rip = strtok(NULL, ":"); - pip = strtok(NULL, ":"); - vip = strtok(NULL, ":"); - sscanf(strtok(NULL, ":"), "%d", &port); - - if (!strcmp(uuid, FILE_SEND_UID)) { - /* they want us to get a file */ - int unk[4], i; - char *messages[4], *tmp, *name; - int subtype, files, totalsize = 0; - struct ft_request *ft; - - for (i = 0; i < 4; i++) { - sscanf(strtok(NULL, ":"), "%d", &unk[i]); - if (unk[i] == 10001) - break; - frombase64(strtok(NULL, ":"), &messages[i], NULL); - } - frombase64(strtok(NULL, ":"), &tmp, NULL); - - subtype = tmp[1]; - files = tmp[3]; - - totalsize |= (tmp[4] << 24) & 0xff000000; - totalsize |= (tmp[5] << 16) & 0x00ff0000; - totalsize |= (tmp[6] << 8) & 0x0000ff00; - totalsize |= (tmp[7] << 0) & 0x000000ff; - - if (!totalsize) { - g_free(tmp); - for (i--; i >= 0; i--) - g_free(messages[i]); - return; - } - - name = tmp + 8; - - ft = g_new0(struct ft_request, 1); - ft->cookie = g_strdup(cookie); - ft->ip = g_strdup(pip); - ft->port = port; - if (i) - ft->message = g_strdup(messages[0]); - else - ft->message = NULL; - ft->filename = g_strdup(name); - ft->user = g_strdup(user); - ft->size = totalsize; - ft->files = files; - g_snprintf(ft->UID, sizeof(ft->UID), "%s", FILE_SEND_UID); - ft->gc = gc; - - g_free(tmp); - for (i--; i >= 0; i--) - g_free(messages[i]); - - debug_printf("English translation of RVOUS_PROPOSE: %s requests Send File (i.e." - " send a file to you); %s:%d (verified_ip:port), %d files at" - " total size of %ld bytes.\n", user, vip, port, files, totalsize); - accept_file_dialog(ft); - } else if (!strcmp(uuid, FILE_GET_UID)) { - /* they want us to send a file */ - int unk[4], i; - char *messages[4], *tmp; - struct ft_request *ft; - - for (i = 0; i < 4; i++) { - sscanf(strtok(NULL, ":"), "%d", unk + i); - if (unk[i] == 10001) - break; - frombase64(strtok(NULL, ":"), &messages[i], NULL); - } - frombase64(strtok(NULL, ":"), &tmp, NULL); - - ft = g_new0(struct ft_request, 1); - ft->cookie = g_strdup(cookie); - ft->ip = g_strdup(pip); - ft->port = port; - if (i) - ft->message = g_strdup(messages[0]); - else - ft->message = NULL; - ft->user = g_strdup(user); - g_snprintf(ft->UID, sizeof(ft->UID), "%s", FILE_GET_UID); - ft->gc = gc; - - g_free(tmp); - for (i--; i >= 0; i--) - g_free(messages[i]); - - accept_file_dialog(ft); - } else if (!strcmp(uuid, VOICE_UID)) { - /* oh goody. voice over ip. fun stuff. */ - } else if (!strcmp(uuid, B_ICON_UID)) { - /* - int unk[4], i; - char *messages[4]; - struct buddy_icon *icon; - - for (i = 0; i < 4; i++) { - sscanf(strtok(NULL, ":"), "%d", unk + i); - if (unk[i] == 10001) - break; - frombase64(strtok(NULL, ":"), &messages[i], NULL); - } - frombase64(strtok(NULL, ":"), (char **)&icon, NULL); - - debug_printf("received icon of length %d\n", icon->len); - g_free(icon); - for (i--; i >= 0; i--) - g_free(messages[i]); - */ - } else if (!strcmp(uuid, IMAGE_UID)) { - /* aka Direct IM */ - } else { - debug_printf("Don't know what to do with RVOUS UUID %s\n", uuid); - /* do we have to do anything here? i think it just times out */ - } - } else { - debug_printf("don't know what to do with %s\n", c); - } -} - -static char *toc_name() -{ - return "TOC"; -} - -static void toc_send_im(struct gaim_connection *gc, char *name, char *message, int away) -{ - char buf[BUF_LEN * 2]; - - escape_text(message); - g_snprintf(buf, MSG_LEN - 8, "toc_send_im %s \"%s\"%s", normalize(name), - message, ((away) ? " auto" : "")); - sflap_send(gc, buf, -1, TYPE_DATA); -} - -static void toc_set_config(struct gaim_connection *gc) -{ - char buf[MSG_LEN], snd[BUF_LEN * 2]; - toc_build_config(gc, buf, MSG_LEN, FALSE); - g_snprintf(snd, MSG_LEN, "toc_set_config {%s}", buf); - sflap_send(gc, snd, -1, TYPE_DATA); -} - -static void toc_get_info(struct gaim_connection *g, char *name) -{ - char buf[BUF_LEN * 2]; - g_snprintf(buf, MSG_LEN, "toc_get_info %s", normalize(name)); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_get_dir(struct gaim_connection *g, char *name) -{ - char buf[BUF_LEN * 2]; - g_snprintf(buf, MSG_LEN, "toc_get_dir %s", normalize(name)); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_set_dir(struct gaim_connection *g, char *first, char *middle, char *last, - char *maiden, char *city, char *state, char *country, int web) -{ - char buf2[BUF_LEN * 4], buf[BUF_LEN]; - g_snprintf(buf2, sizeof(buf2), "%s:%s:%s:%s:%s:%s:%s:%s", first, - middle, last, maiden, city, state, country, (web == 1) ? "Y" : ""); - escape_text(buf2); - g_snprintf(buf, sizeof(buf), "toc_set_dir %s", buf2); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_dir_search(struct gaim_connection *g, char *first, char *middle, char *last, - char *maiden, char *city, char *state, char *country, char *email) -{ - char buf[BUF_LONG]; - g_snprintf(buf, sizeof(buf) / 2, "toc_dir_search %s:%s:%s:%s:%s:%s:%s:%s", first, middle, - last, maiden, city, state, country, email); - debug_printf("Searching for: %s,%s,%s,%s,%s,%s,%s\n", first, middle, last, maiden, - city, state, country); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_set_away(struct gaim_connection *g, char *state, char *message) -{ - char buf[BUF_LEN * 2]; - if (g->away) - g_free (g->away); - g->away = NULL; - if (message) { - g->away = g_strdup (message); - escape_text(message); - g_snprintf(buf, MSG_LEN, "toc_set_away \"%s\"", message); - } else - g_snprintf(buf, MSG_LEN, "toc_set_away \"\""); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_set_info(struct gaim_connection *g, char *info) -{ - char buf[BUF_LEN * 2], buf2[BUF_LEN * 2]; - g_snprintf(buf2, sizeof buf2, "%s", info); - escape_text(buf2); - g_snprintf(buf, sizeof(buf), "toc_set_info \"%s\n\"", buf2); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_change_passwd(struct gaim_connection *g, char *orig, char *new) -{ - char buf[BUF_LEN * 2]; - g_snprintf(buf, BUF_LONG, "toc_change_passwd %s %s", orig, new); - sflap_send(g, buf, strlen(buf), TYPE_DATA); -} - -static void toc_add_buddy(struct gaim_connection *g, char *name) -{ - char buf[BUF_LEN * 2]; - g_snprintf(buf, sizeof(buf), "toc_add_buddy %s", normalize(name)); - sflap_send(g, buf, -1, TYPE_DATA); - toc_set_config(g); -} - -static void toc_add_buddies(struct gaim_connection *g, GList * buddies) -{ - char buf[BUF_LEN * 2]; - int n; - - n = g_snprintf(buf, sizeof(buf), "toc_add_buddy"); - while (buddies) { - if (strlen(normalize(buddies->data)) > MSG_LEN - n - 16) { - sflap_send(g, buf, -1, TYPE_DATA); - n = g_snprintf(buf, sizeof(buf), "toc_add_buddy"); - } - n += g_snprintf(buf + n, sizeof(buf) - n, " %s", normalize(buddies->data)); - buddies = buddies->next; - } - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_remove_buddy(struct gaim_connection *g, char *name) -{ - char buf[BUF_LEN * 2]; - g_snprintf(buf, sizeof(buf), "toc_remove_buddy %s", normalize(name)); - sflap_send(g, buf, -1, TYPE_DATA); - toc_set_config(g); -} - -static void toc_set_idle(struct gaim_connection *g, int time) -{ - char buf[BUF_LEN * 2]; - g_snprintf(buf, sizeof(buf), "toc_set_idle %d", time); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_warn(struct gaim_connection *g, char *name, int anon) -{ - char send[BUF_LEN * 2]; - g_snprintf(send, 255, "toc_evil %s %s", name, ((anon) ? "anon" : "norm")); - sflap_send(g, send, -1, TYPE_DATA); -} - -static void toc_accept_chat(struct gaim_connection *g, int i) -{ - char buf[BUF_LEN * 2]; - g_snprintf(buf, 255, "toc_chat_accept %d", i); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_join_chat(struct gaim_connection *g, int exchange, char *name) -{ - char buf[BUF_LONG]; - if (!name) { - const char *nm; - if (!join_chat_entry || !join_chat_spin) - return; - nm = gtk_entry_get_text(GTK_ENTRY(join_chat_entry)); - exchange = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(join_chat_spin)); - if (!name || !strlen(name)) - return; - g_snprintf(buf, sizeof(buf) / 2, "toc_chat_join %d \"%s\"", exchange, nm); - } else - g_snprintf(buf, sizeof(buf) / 2, "toc_chat_join %d \"%s\"", exchange, name); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_chat_invite(struct gaim_connection *g, int id, char *message, char *name) -{ - char buf[BUF_LONG]; - g_snprintf(buf, sizeof(buf) / 2, "toc_chat_invite %d \"%s\" %s", id, message, normalize(name)); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_chat_leave(struct gaim_connection *g, int id) -{ - GSList *bcs = g->buddy_chats; - struct conversation *b = NULL; - char buf[BUF_LEN * 2]; - - while (bcs) { - b = (struct conversation *)bcs->data; - if (id == b->id) - break; - b = NULL; - bcs = bcs->next; - } - - if (!b) - return; /* can this happen? */ - - if (!b->gc) /* TOC already kicked us out of this room */ - serv_got_chat_left(g, id); - else { - g_snprintf(buf, 255, "toc_chat_leave %d", id); - sflap_send(g, buf, -1, TYPE_DATA); - } -} - -static void toc_chat_whisper(struct gaim_connection *g, int id, char *who, char *message) -{ - char buf2[BUF_LEN * 2]; - g_snprintf(buf2, sizeof(buf2), "toc_chat_whisper %d %s \"%s\"", id, who, message); - sflap_send(g, buf2, -1, TYPE_DATA); -} - -static void toc_chat_send(struct gaim_connection *g, int id, char *message) -{ - char buf[BUF_LEN * 2]; - escape_text(message); - g_snprintf(buf, sizeof(buf), "toc_chat_send %d \"%s\"", id, message); - sflap_send(g, buf, -1, TYPE_DATA); -} - -static void toc_keepalive(struct gaim_connection *gc) -{ - sflap_send(gc, "", 0, TYPE_KEEPALIVE); -} - -static char **toc_list_icon(int uc) -{ - if (uc & UC_UNAVAILABLE) - return (char **)away_icon_xpm; - if (uc & UC_AOL) - return (char **)aol_icon_xpm; - if (uc & UC_NORMAL) - return (char **)free_icon_xpm; - if (uc & UC_ADMIN) - return (char **)admin_icon_xpm; - if (uc & UC_UNCONFIRMED) - return (char **)dt_icon_xpm; - return NULL; -} - -static void toc_info(GtkObject * obj, char *who) -{ - struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(obj); - serv_get_info(gc, who); -} - -static void toc_dir_info(GtkObject * obj, char *who) -{ - struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(obj); - serv_get_dir(gc, who); -} - -static void des_jc() -{ - join_chat_entry = NULL; - join_chat_spin = NULL; -} - -static void toc_draw_join_chat(struct gaim_connection *gc, GtkWidget *fbox) { - GtkWidget *label; - GtkWidget *rowbox; - GtkObject *adjust; - - rowbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0); - gtk_widget_show(rowbox); - - label = gtk_label_new(_("Join what group:")); - gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); - gtk_signal_connect(GTK_OBJECT(label), "destroy", GTK_SIGNAL_FUNC(des_jc), NULL); - gtk_widget_show(label); - - join_chat_entry = gtk_entry_new(); - gtk_box_pack_start(GTK_BOX(rowbox), join_chat_entry, TRUE, TRUE, 0); - gtk_widget_grab_focus(join_chat_entry); - gtk_signal_connect(GTK_OBJECT(join_chat_entry), "activate", GTK_SIGNAL_FUNC(do_join_chat), NULL); - gtk_widget_show(join_chat_entry); - - rowbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0); - gtk_widget_show(rowbox); - - label = gtk_label_new(_("Community:")); - gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); - gtk_widget_show(label); - - adjust = gtk_adjustment_new(4, 4, 20, 1, 10, 10); - join_chat_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); - gtk_widget_set_usize(join_chat_spin, 50, -1); - gtk_box_pack_start(GTK_BOX(rowbox), join_chat_spin, FALSE, FALSE, 0); - gtk_widget_show(join_chat_spin); -} - -static void toc_buddy_menu(GtkWidget *menu, struct gaim_connection *gc, char *who) -{ - GtkWidget *button; - - button = gtk_menu_item_new_with_label(_("Get Info")); - gtk_signal_connect(GTK_OBJECT(button), "activate", GTK_SIGNAL_FUNC(toc_info), who); - gtk_object_set_user_data(GTK_OBJECT(button), gc); - gtk_menu_append(GTK_MENU(menu), button); - gtk_widget_show(button); - - button = gtk_menu_item_new_with_label(_("Get Dir Info")); - gtk_signal_connect(GTK_OBJECT(button), "activate", GTK_SIGNAL_FUNC(toc_dir_info), who); - gtk_object_set_user_data(GTK_OBJECT(button), gc); - gtk_menu_append(GTK_MENU(menu), button); - gtk_widget_show(button); -} - -static void toc_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)); - } else if (entrynum == USEROPT_AUTHPORT) { - g_snprintf(user->proto_opt[USEROPT_AUTHPORT], - sizeof(user->proto_opt[USEROPT_AUTHPORT]), "%s", gtk_entry_get_text(entry)); - } -} - -static void toc_user_opts(GtkWidget *book, struct aim_user *user) -{ - /* so here, we create the new notebook page */ - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *entry; - - 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("TOC 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("TOC 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(toc_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]); - } else - gtk_entry_set_text(GTK_ENTRY(entry), "toc.oscar.aol.com"); - 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("TOC 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_AUTHPORT); - gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(toc_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), "9898"); - - gtk_widget_show(entry); -} - -static void toc_add_permit(struct gaim_connection *gc, char *who) -{ - char buf2[BUF_LEN * 2]; - if (gc->permdeny != 3) - return; - g_snprintf(buf2, sizeof(buf2), "toc_add_permit %s", normalize(who)); - sflap_send(gc, buf2, -1, TYPE_DATA); - toc_set_config(gc); -} - -static void toc_add_deny(struct gaim_connection *gc, char *who) -{ - char buf2[BUF_LEN * 2]; - if (gc->permdeny != 4) - return; - g_snprintf(buf2, sizeof(buf2), "toc_add_deny %s", normalize(who)); - sflap_send(gc, buf2, -1, TYPE_DATA); - toc_set_config(gc); -} - -static void toc_set_permit_deny(struct gaim_connection *gc) -{ - char buf2[BUF_LEN * 2]; - GSList *list; - int at; - - switch (gc->permdeny) { - case 1: - /* permit all, deny none. to get here reliably we need to have been in permit - * mode, and send an empty toc_add_deny message, which will switch us to deny none */ - g_snprintf(buf2, sizeof(buf2), "toc_add_permit "); - sflap_send(gc, buf2, -1, TYPE_DATA); - g_snprintf(buf2, sizeof(buf2), "toc_add_deny "); - sflap_send(gc, buf2, -1, TYPE_DATA); - break; - case 2: - /* deny all, permit none. to get here reliably we need to have been in deny - * mode, and send an empty toc_add_permit message, which will switch us to permit none */ - g_snprintf(buf2, sizeof(buf2), "toc_add_deny "); - sflap_send(gc, buf2, -1, TYPE_DATA); - g_snprintf(buf2, sizeof(buf2), "toc_add_permit "); - sflap_send(gc, buf2, -1, TYPE_DATA); - break; - case 3: - /* permit some. we want to switch to deny mode first, then send the toc_add_permit - * message, which will clear and set our permit list. toc sucks. */ - g_snprintf(buf2, sizeof(buf2), "toc_add_deny "); - sflap_send(gc, buf2, -1, TYPE_DATA); - - at = g_snprintf(buf2, sizeof(buf2), "toc_add_permit "); - list = gc->permit; - while (list) { - at += g_snprintf(buf2 + at, sizeof(buf2) - at, "%s ", normalize(list->data)); - if (at > MSG_LEN + 32) { /* from out my ass comes greatness */ - sflap_send(gc, buf2, -1, TYPE_DATA); - at = g_snprintf(buf2, sizeof(buf2), "toc_add_permit "); - } - list = list->next; - } - sflap_send(gc, buf2, -1, TYPE_DATA); - break; - case 4: - /* deny some. we want to switch to permit mode first, then send the toc_add_deny - * message, which will clear and set our deny list. toc sucks. */ - g_snprintf(buf2, sizeof(buf2), "toc_add_permit "); - sflap_send(gc, buf2, -1, TYPE_DATA); - - at = g_snprintf(buf2, sizeof(buf2), "toc_add_deny "); - list = gc->deny; - while (list) { - at += g_snprintf(buf2 + at, sizeof(buf2) - at, "%s ", normalize(list->data)); - if (at > MSG_LEN + 32) { /* from out my ass comes greatness */ - sflap_send(gc, buf2, -1, TYPE_DATA); - at = g_snprintf(buf2, sizeof(buf2), "toc_add_deny "); - } - list = list->next; - } - sflap_send(gc, buf2, -1, TYPE_DATA); - break; - default: - break; - } - toc_set_config(gc); -} - -static void toc_rem_permit(struct gaim_connection *gc, char *who) -{ - if (gc->permdeny != 3) - return; - toc_set_permit_deny(gc); -} - -static void toc_rem_deny(struct gaim_connection *gc, char *who) -{ - if (gc->permdeny != 4) - return; - toc_set_permit_deny(gc); -} - -static void toc_draw_new_user(GtkWidget *box) -{ - GtkWidget *label; - - label = gtk_label_new(_("Unfortunately, currently TOC only allows new user registration by " - "going to http://aim.aol.com/aimnew/Aim/register.adp?promo=106723&pageset=Aim&client=no" - ". Clicking the Register button will open the URL for you.")); - gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5); - gtk_widget_show(label); -} - -static void toc_do_new_user() -{ - open_url(NULL, "http://aim.aol.com/aimnew/Aim/register.adp?promo=106723&pageset=Aim&client=no"); -} - -static GList *toc_away_states() -{ - return g_list_append(NULL, GAIM_AWAY_CUSTOM); -} - -static void toc_do_action(struct gaim_connection *gc, char *act) -{ - if (!strcmp(act, "Set User Info")) { - show_set_info(gc); - } else if (!strcmp(act, "Set Dir Info")) { - show_set_dir(gc); - } else if (!strcmp(act, "Change Password")) { - show_change_passwd(gc); - } -} - -static GList *toc_actions() -{ - GList *m = NULL; - - m = g_list_append(m, "Set User Info"); - m = g_list_append(m, "Set Dir Info"); - m = g_list_append(m, "Change Password"); - - return m; -} - -void toc_init(struct prpl *ret) -{ - ret->protocol = PROTO_TOC; - ret->options = OPT_PROTO_HTML | OPT_PROTO_CORRECT_TIME; - ret->name = toc_name; - ret->list_icon = toc_list_icon; - ret->away_states = toc_away_states; - ret->actions = toc_actions; - ret->do_action = toc_do_action; - ret->buddy_menu = toc_buddy_menu; - ret->user_opts = toc_user_opts; - ret->draw_new_user = toc_draw_new_user; - ret->do_new_user = toc_do_new_user; - ret->login = toc_login; - ret->close = toc_close; - ret->send_im = toc_send_im; - ret->set_info = toc_set_info; - ret->get_info = toc_get_info; - ret->set_away = toc_set_away; - ret->get_away_msg = NULL; - ret->set_dir = toc_set_dir; - ret->get_dir = toc_get_dir; - ret->dir_search = toc_dir_search; - ret->set_idle = toc_set_idle; - ret->change_passwd = toc_change_passwd; - ret->add_buddy = toc_add_buddy; - ret->add_buddies = toc_add_buddies; - ret->remove_buddy = toc_remove_buddy; - ret->add_permit = toc_add_permit; - ret->add_deny = toc_add_deny; - ret->rem_permit = toc_rem_permit; - ret->rem_deny = toc_rem_deny; - ret->set_permit_deny = toc_set_permit_deny; - ret->warn = toc_warn; - ret->draw_join_chat = toc_draw_join_chat; - ret->accept_chat = toc_accept_chat; - ret->join_chat = toc_join_chat; - ret->chat_invite = toc_chat_invite; - ret->chat_leave = toc_chat_leave; - ret->chat_whisper = toc_chat_whisper; - ret->chat_send = toc_chat_send; - ret->keepalive = toc_keepalive; -} - -/********* - * RVOUS ACTIONS - ********/ - -struct file_header { - char magic[4]; /* 0 */ - short hdrlen; /* 4 */ - short hdrtype; /* 6 */ - char bcookie[8]; /* 8 */ - short encrypt; /* 16 */ - short compress; /* 18 */ - short totfiles; /* 20 */ - short filesleft; /* 22 */ - short totparts; /* 24 */ - short partsleft; /* 26 */ - long totsize; /* 28 */ - long size; /* 32 */ - long modtime; /* 36 */ - long checksum; /* 40 */ - long rfrcsum; /* 44 */ - long rfsize; /* 48 */ - long cretime; /* 52 */ - long rfcsum; /* 56 */ - long nrecvd; /* 60 */ - long recvcsum; /* 64 */ - char idstring[32]; /* 68 */ - char flags; /* 100 */ - char lnameoffset; /* 101 */ - char lsizeoffset; /* 102 */ - char dummy[69]; /* 103 */ - char macfileinfo[16]; /* 172 */ - short nencode; /* 188 */ - short nlanguage; /* 190 */ - char name[64]; /* 192 */ - /* 256 */ -}; - -struct file_transfer { - struct file_header hdr; - - struct gaim_connection *gc; - - char *user; - char *cookie; - char *ip; - int port; - long size; - struct stat st; - - GtkWidget *window; - int files; - char *filename; - FILE *file; - int recvsize; - - gint inpa; -}; - -static void debug_header(struct file_transfer *ft) { - struct file_header *f = (struct file_header *)ft; - debug_printf("TOC FT HEADER:\n" - "\t%s %d 0x%04x\n" - "\t%s %d %d\n" - "\t%d %d %d %d %ld %ld\n" - "\t%ld %ld %ld %ld %ld %ld %ld %ld\n" - "\t%s\n" - "\t0x%02x, 0x%02x, 0x%02x\n" - "\t%s %s\n" - "\t%d %d\n" - "\t%s\n", - f->magic, ntohs(f->hdrlen), f->hdrtype, - f->bcookie, ntohs(f->encrypt), ntohs(f->compress), - ntohs(f->totfiles), ntohs(f->filesleft), ntohs(f->totparts), - ntohs(f->partsleft), ntohl(f->totsize), ntohl(f->size), - ntohl(f->modtime), ntohl(f->checksum), ntohl(f->rfrcsum), ntohl(f->rfsize), - ntohl(f->cretime), ntohl(f->rfcsum), ntohl(f->nrecvd), - ntohl(f->recvcsum), - f->idstring, - f->flags, f->lnameoffset, f->lsizeoffset, - f->dummy, f->macfileinfo, - ntohs(f->nencode), ntohs(f->nlanguage), - f->name); -} - -static void toc_send_file_callback(gpointer data, gint source, GdkInputCondition cond) -{ - char buf[BUF_LONG]; - int rt, i; - - struct file_transfer *ft = data; - - if (cond & GDK_INPUT_EXCEPTION) { - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->filename); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - if (ft->file) - fclose(ft->file); - g_free(ft); - return; - } - - if (ft->hdr.hdrtype != 0x202) { - char *buf; - frombase64(ft->cookie, &buf, NULL); - - read(source, ft, 8); - read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); - debug_header(ft); - - ft->hdr.hdrtype = 0x202; - memcpy(ft->hdr.bcookie, buf, 8); - g_free(buf); - ft->hdr.encrypt = 0; ft->hdr.compress = 0; - debug_header(ft); - write(source, ft, 256); - - if (ft->files == 1) { - ft->file = fopen(ft->filename, "w"); - if (!ft->file) { - buf = g_strdup_printf("Could not open %s for writing!", ft->filename); - do_error_dialog(buf, _("Error")); - g_free(buf); - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->filename); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - g_free(ft); - } - } else { - buf = g_strdup_printf("%s/%s", ft->filename, ft->hdr.name); - ft->file = fopen(buf, "w"); - g_free(buf); - if (!ft->file) { - buf = g_strdup_printf("Could not open %s/%s for writing!", ft->filename, - ft->hdr.name); - do_error_dialog(buf, _("Error")); - g_free(buf); - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->filename); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - g_free(ft); - } - } - - return; - } - - rt = read(source, buf, MIN(ntohl(ft->hdr.size) - ft->recvsize, 1024)); - if (rt < 0) { - do_error_dialog("File transfer failed; other side probably canceled.", "Error"); - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - if (ft->file) - fclose(ft->file); - g_free(ft); - return; - } - ft->recvsize += rt; - for (i = 0; i < rt; i++) - fprintf(ft->file, "%c", buf[i]); - - if (ft->recvsize == ntohl(ft->hdr.size)) { - ft->hdr.hdrtype = htons(0x0204); - ft->hdr.filesleft = htons(ntohs(ft->hdr.filesleft) - 1); - ft->hdr.partsleft = htons(ntohs(ft->hdr.partsleft) - 1); - ft->hdr.recvcsum = ft->hdr.checksum; /* uh... */ - ft->hdr.nrecvd = htons(ntohs(ft->hdr.nrecvd) + 1); - ft->hdr.flags = 0; - write(source, ft, 256); - debug_header(ft); - ft->recvsize = 0; - fclose(ft->file); - if (ft->hdr.filesleft == 0) { - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->filename); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - g_free(ft); - } - } -} - -static void toc_send_file_connect(gpointer data, gint src, GdkInputCondition cond) -{ - struct file_transfer *ft = data; - - if (src == -1) { - do_error_dialog(_("Could not connect for transfer!"), _("Error")); - g_free(ft->filename); - g_free(ft->cookie); - g_free(ft->user); - g_free(ft->ip); - g_free(ft); - return; - } - - ft->inpa = gdk_input_add(src, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, toc_send_file_callback, ft); -} - -static void toc_send_file(gpointer a, struct file_transfer *old_ft) -{ - struct file_transfer *ft; - const char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window)); - int fd; - struct aim_user *user; - char buf[BUF_LEN * 2]; - - if (file_is_dir(dirname, old_ft->window)) - return; - ft = g_new0(struct file_transfer, 1); - if (old_ft->files == 1) - ft->filename = g_strdup(dirname); - else - ft->filename = g_dirname(dirname); - ft->cookie = g_strdup(old_ft->cookie); - ft->user = g_strdup(old_ft->user); - ft->ip = g_strdup(old_ft->ip); - ft->files = old_ft->files; - ft->port = old_ft->port; - ft->gc = old_ft->gc; - user = ft->gc->user; - gtk_widget_destroy(old_ft->window); - - g_snprintf(buf, sizeof(buf), "toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_SEND_UID); - sflap_send(ft->gc, buf, -1, TYPE_DATA); - - fd = - proxy_connect(ft->ip, ft->port, toc_send_file_connect, ft); - if (fd < 0) { - do_error_dialog(_("Could not connect for transfer!"), _("Error")); - g_free(ft->filename); - g_free(ft->cookie); - g_free(ft->user); - g_free(ft->ip); - g_free(ft); - return; - } -} - -static void toc_get_file_callback(gpointer data, gint source, GdkInputCondition cond) -{ - char buf[BUF_LONG]; - - struct file_transfer *ft = data; - - if (cond & GDK_INPUT_EXCEPTION) { - do_error_dialog("The file tranfer has been aborted; the other side most likely" - " cancelled.", "Error"); - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->filename); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - if (ft->file) - fclose(ft->file); - g_free(ft); - return; - } - - if (cond & GDK_INPUT_WRITE) { - int remain = MIN(ntohl(ft->hdr.totsize) - ft->recvsize, 1024); - int i; - for (i = 0; i < remain; i++) - fscanf(ft->file, "%c", &buf[i]); - write(source, buf, remain); - ft->recvsize += remain; - if (ft->recvsize == ntohl(ft->hdr.totsize)) { - gdk_input_remove(ft->inpa); - ft->inpa = gdk_input_add(source, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, - toc_get_file_callback, ft); - } - return; - } - - if (ft->hdr.hdrtype == htons(0x1108)) { - struct tm *fortime; - struct stat st; - - read(source, ft, 8); - read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); - debug_header(ft); - - stat(ft->filename, &st); - fortime = localtime(&st.st_mtime); - g_snprintf(buf, sizeof(buf), "%2d/%2d/%4d %2d:%2d %8ld %s\r\n", - fortime->tm_mon + 1, fortime->tm_mday, fortime->tm_year + 1900, - fortime->tm_hour + 1, fortime->tm_min + 1, (long)st.st_size, - g_basename(ft->filename)); - write(source, buf, ntohl(ft->hdr.size)); - return; - } - - if (ft->hdr.hdrtype == htons(0x1209)) { - read(source, ft, 8); - read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); - debug_header(ft); - return; - } - - if (ft->hdr.hdrtype == htons(0x120b)) { - read(source, ft, 8); - read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); - debug_header(ft); - - if (ft->hdr.hdrtype != htons(0x120c)) { - g_snprintf(buf, sizeof(buf), "%s decided to cancel the transfer", ft->user); - do_error_dialog(buf, "Error"); - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->filename); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - if (ft->file) - fclose(ft->file); - g_free(ft); - return; - } - - ft->hdr.hdrtype = 0x0101; - ft->hdr.totfiles = htons(1); ft->hdr.filesleft = htons(1); - ft->hdr.flags = 0x20; - write(source, ft, 256); - return; - } - - if (ft->hdr.hdrtype == 0x0101) { - read(source, ft, 8); - read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); - debug_header(ft); - - gdk_input_remove(ft->inpa); - ft->inpa = gdk_input_add(source, GDK_INPUT_WRITE | GDK_INPUT_EXCEPTION, - toc_get_file_callback, ft); - return; - } - - if (ft->hdr.hdrtype == 0x0202) { - read(source, ft, 8); - read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); - debug_header(ft); - - gdk_input_remove(ft->inpa); - close(source); - g_free(ft->filename); - g_free(ft->user); - g_free(ft->ip); - g_free(ft->cookie); - if (ft->file) - fclose(ft->file); - g_free(ft); - return; - } -} - -static void toc_get_file_connect(gpointer data, gint src, GdkInputCondition cond) -{ - struct file_transfer *ft = data; - struct file_header *hdr; - char *buf; - - if (src == -1) { - do_error_dialog(_("Could not connect for transfer!"), _("Error")); - fclose(ft->file); - g_free(ft->filename); - g_free(ft->cookie); - g_free(ft->user); - g_free(ft->ip); - g_free(ft); - return; - } - - hdr = (struct file_header *)ft; - hdr->magic[0] = 'O'; hdr->magic[1] = 'F'; hdr->magic[2] = 'T'; hdr->magic[3] = '2'; - hdr->hdrlen = htons(256); - hdr->hdrtype = htons(0x1108); - frombase64(ft->cookie, &buf, NULL); - g_snprintf(hdr->bcookie, 8, "%s", buf); - g_free(buf); - hdr->totfiles = htons(1); hdr->filesleft = htons(1); - hdr->totparts = htons(1); hdr->partsleft = htons(1); - hdr->totsize = htonl((long)ft->st.st_size); /* combined size of all files */ - /* size = strlen("mm/dd/yyyy hh:mm sizesize 'name'\r\n") */ - hdr->size = htonl(28 + strlen(g_basename(ft->filename))); /* size of listing.txt */ - hdr->modtime = htonl(ft->st.st_mtime); - hdr->checksum = htonl(0x89f70000); /* uh... */ - g_snprintf(hdr->idstring, 32, "OFT_Windows ICBMFT V1.1 32"); - hdr->flags = 0x02; - hdr->lnameoffset = 0x1A; - hdr->lsizeoffset = 0x10; - g_snprintf(hdr->name, 64, "listing.txt"); - if (write(src, hdr, 256) < 0) { - do_error_dialog(_("Could not write file header!"), _("Error")); - fclose(ft->file); - g_free(ft->filename); - g_free(ft->cookie); - g_free(ft->user); - g_free(ft->ip); - g_free(ft); - return; - } - - ft->inpa = gdk_input_add(src, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, toc_get_file_callback, ft); -} - -static void toc_get_file(gpointer a, struct file_transfer *old_ft) -{ - struct file_transfer *ft; - const char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window)); - int fd; - struct aim_user *user; - char *buf, buf2[BUF_LEN * 2]; - - if (file_is_dir(dirname, old_ft->window)) - return; - ft = g_new0(struct file_transfer, 1); - ft->filename = g_strdup(dirname); - ft->file = fopen(ft->filename, "r"); - if (!ft->file) { - buf = g_strdup_printf("Unable to open %s for transfer!", ft->filename); - do_error_dialog(buf, "Error"); - g_free(buf); - g_free(ft->filename); - g_free(ft); - return; - } - if (stat(dirname, &ft->st)) { - buf = g_strdup_printf("Unable to examine %s!", dirname); - do_error_dialog(buf, "Error"); - g_free(buf); - g_free(ft->filename); - g_free(ft); - return; - } - ft->cookie = g_strdup(old_ft->cookie); - ft->user = g_strdup(old_ft->user); - ft->ip = g_strdup(old_ft->ip); - ft->port = old_ft->port; - ft->gc = old_ft->gc; - user = ft->gc->user; - gtk_widget_destroy(old_ft->window); - - g_snprintf(buf2, sizeof(buf2), "toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_GET_UID); - sflap_send(ft->gc, buf2, -1, TYPE_DATA); - - fd = - proxy_connect(ft->ip, ft->port, toc_get_file_connect, ft); - if (fd < 0) { - do_error_dialog(_("Could not connect for transfer!"), _("Error")); - fclose(ft->file); - g_free(ft->filename); - g_free(ft->cookie); - g_free(ft->user); - g_free(ft->ip); - g_free(ft); - return; - } -} - -static void cancel_callback(gpointer a, struct file_transfer *ft) { - gtk_widget_destroy(ft->window); - if (a == ft->window) { - g_free(ft->cookie); - g_free(ft->user); - g_free(ft->ip); - g_free(ft); - } -} - -static void toc_accept_ft(gpointer a, struct ft_request *fr) { - GtkWidget *window; - char buf[BUF_LEN]; - - struct file_transfer *ft = g_new0(struct file_transfer, 1); - ft->gc = fr->gc; - ft->user = g_strdup(fr->user); - ft->cookie = g_strdup(fr->cookie); - ft->ip = g_strdup(fr->ip); - ft->port = fr->port; - ft->files = fr->files; - - ft->window = window = gtk_file_selection_new(_("Gaim - Save As...")); - g_snprintf(buf, sizeof(buf), "%s/%s", g_get_home_dir(), fr->filename ? fr->filename : ""); - gtk_file_selection_set_filename(GTK_FILE_SELECTION(window), buf); - gtk_signal_connect(GTK_OBJECT(window), "destroy", - GTK_SIGNAL_FUNC(cancel_callback), ft); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(ft->window)->cancel_button), "clicked", - GTK_SIGNAL_FUNC(cancel_callback), ft); - - if (!strcmp(fr->UID, FILE_SEND_UID)) - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", - GTK_SIGNAL_FUNC(toc_send_file), ft); - else - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", - GTK_SIGNAL_FUNC(toc_get_file), ft); - - gtk_widget_show(window); -} - -static void toc_reject_ft(gpointer a, struct ft_request *ft) { - g_free(ft->user); - g_free(ft->filename); - g_free(ft->ip); - g_free(ft->cookie); - if (ft->message) - g_free(ft->message); - g_free(ft); -} - -static void accept_file_dialog(struct ft_request *ft) { - char buf[BUF_LONG]; - if (!strcmp(ft->UID, FILE_SEND_UID)) { - /* holy crap. who the fuck would transfer gigabytes through AIM?! */ - static char *sizes[4] = { "bytes", "KB", "MB", "GB" }; - float size = ft->size; - int index = 0; - while ((index < 4) && (size > 1024)) { - size /= 1024; - index++; - } - g_snprintf(buf, sizeof(buf), _("%s requests %s to accept %d file%s: %s (%.2f %s)%s%s"), - ft->user, ft->gc->username, ft->files, (ft->files == 1) ? "" : "s", - ft->filename, size, sizes[index], (ft->message) ? "\n" : "", - (ft->message) ? ft->message : ""); - } else { - g_snprintf(buf, sizeof(buf), _("%s requests you to send them a file"), ft->user); - } - do_ask_dialog(buf, ft, toc_accept_ft, toc_reject_ft); -}