changeset 1457:c6f9d0cdaa00

[gaim-migrate @ 1467] all of toc in one file; rewritten file transfer. no get file yet; just send file. but why would you want to send files to people anyway? ;) committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Thu, 01 Feb 2001 11:29:15 +0000
parents 6650776468b3
children 6933fd960557
files src/Makefile.am src/gaim.h src/prpl.c src/rvous.c src/toc.c
diffstat 5 files changed, 316 insertions(+), 782 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile.am	Thu Feb 01 08:37:16 2001 +0000
+++ b/src/Makefile.am	Thu Feb 01 11:29:15 2001 +0000
@@ -22,7 +22,6 @@
 			prefs.c \
 			proxy.c \
 			prpl.c \
-			rvous.c \
 			server.c \
 			sound.c \
 			ticker.c \
@@ -54,7 +53,6 @@
 		prefs.c \
 		proxy.c \
 		prpl.c \
-		rvous.c \
 		server.c \
 		sound.c \
 		ticker.c \
--- a/src/gaim.h	Thu Feb 01 08:37:16 2001 +0000
+++ b/src/gaim.h	Thu Feb 01 11:29:15 2001 +0000
@@ -354,34 +354,9 @@
 	gboolean is_chat;
 };
 
-struct file_transfer {
-        GtkWidget *window;
-        char *cookie;
-        char *ip;
-        char *message;
-        int port;
-        int size;
-        int accepted;
-        char *filename;
-        char *lfilename;
-        char *user;
-        FILE *f;
-        int fd;
-	char UID[2048];
-	struct gaim_connection *gc;
-};
-
 #define CONVERSATION_TITLE "Gaim - %s"
 #define LOG_CONVERSATION_TITLE "Gaim - %s (logged)"
 
-#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"
-
 #define AOL_SRCHSTR "/community/aimcheck.adp/url="
 
 /* These should all be runtime selectable */
@@ -809,9 +784,6 @@
 extern void apply_font(GtkWidget *widget, GtkFontSelection *fontsel);
 extern void set_color_selection(GtkWidget *selection, GdkColor color);
 
-/* Functions in rvous.c */
-extern void accept_file_dialog(struct file_transfer *);
-
 /* Functions in browser.c */
 extern void open_url(GtkWidget *, char *);
 extern void open_url_nw(GtkWidget *, char *);
--- a/src/prpl.c	Thu Feb 01 08:37:16 2001 +0000
+++ b/src/prpl.c	Thu Feb 01 11:29:15 2001 +0000
@@ -138,7 +138,6 @@
 	gtk_container_add(GTK_CONTAINER(window), vbox);
 
 	label = gtk_label_new(text);
-	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
 
 	hbox = gtk_hbox_new(FALSE, 5);
--- a/src/rvous.c	Thu Feb 01 08:37:16 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,742 +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 <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h> 
-#include <unistd.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <gtk/gtk.h>
-#include "proxy.h"
-#include "gaim.h"
-
-#define TYPE_DATA 2 /* from toc.c */
-
-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 */
-};
-
-static void do_send_file(GtkWidget *, struct file_transfer *);
-static void do_get_file (GtkWidget *, struct file_transfer *);
-extern int sflap_send(struct gaim_connection *, char *, int, int);
-
-static int snpa = -1;
-
-static void toggle(GtkWidget *w, int *m)
-{
-	*m = !(*m);
-}
-
-static void free_ft(struct file_transfer *ft)
-{
-	if (ft->window) { gtk_widget_destroy(ft->window); ft->window = NULL; }
-	if (ft->filename) g_free(ft->filename);
-	if (ft->user) g_free(ft->user);
-	if (ft->message) g_free(ft->message);
-	if (ft->ip) g_free(ft->ip);
-	if (ft->cookie) g_free(ft->cookie);
-	g_free(ft);
-}
-
-static void warn_callback(GtkWidget *widget, struct file_transfer *ft)
-{
-        show_warn_dialog(ft->gc, ft->user);
-}
-
-static void info_callback(GtkWidget *widget, struct file_transfer *ft)
-{
-	serv_get_info(ft->gc, ft->user);
-}
-
-static void cancel_callback(GtkWidget *widget, struct file_transfer *ft)
-{
-	char buf[MSG_LEN];
-
-	if (ft->accepted) {
-		return;
-	}
-	
-	g_snprintf(buf, MSG_LEN, "toc_rvous_cancel %s %s %s", ft->user, ft->cookie, ft->UID);
-	sflap_send(ft->gc, buf, -1, TYPE_DATA);
-
-	free_ft(ft);
-}
-
-static void accept_callback(GtkWidget *widget, struct file_transfer *ft)
-{
-	char buf[BUF_LEN];
-	char fname[BUF_LEN];
-	char *c;
-
-	if (!strcmp(ft->UID, FILE_SEND_UID)) {
-		c = ft->filename + strlen(ft->filename);
-
-		while (c != ft->filename) {
-			if (*c == '/' || *c == '\\') {
-				strcpy(fname, c+1);
-				break;
-			}
-			c--;
-		}
-
-		if (c == ft->filename)
-	                strcpy(fname, ft->filename);
-	}
-	
-	gtk_widget_destroy(ft->window);
-	ft->window = NULL;
-	
-	ft->window = gtk_file_selection_new(_("Gaim - Save As..."));
-
-	gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(ft->window));
-
-	if (!strcmp(ft->UID, FILE_SEND_UID))
-		g_snprintf(buf, BUF_LEN - 1, "%s/%s", getenv("HOME"), fname);
-	else
-		g_snprintf(buf, BUF_LEN - 1, "%s/", getenv("HOME"));
-	gtk_file_selection_set_filename(GTK_FILE_SELECTION(ft->window), buf);
-
-	gtk_signal_connect(GTK_OBJECT(ft->window), "destroy",
-			   GTK_SIGNAL_FUNC(cancel_callback), ft);
-                
-	if (!strcmp(ft->UID, FILE_SEND_UID)) {
-		gtk_signal_connect(GTK_OBJECT(
-				GTK_FILE_SELECTION(ft->window)->ok_button),
-			        "clicked", GTK_SIGNAL_FUNC(do_get_file), ft);
-	} else {
-		gtk_signal_connect(GTK_OBJECT(
-				GTK_FILE_SELECTION(ft->window)->ok_button),
-				"clicked", GTK_SIGNAL_FUNC(do_send_file), ft);
-	}
-	gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(ft->window)->cancel_button),
-			   "clicked", GTK_SIGNAL_FUNC(cancel_callback), ft);
-
-	gtk_widget_show(ft->window);
-}
-
-static int read_file_header(int fd, struct file_header *header) {
-	char buf[257];
-	int read_rv = read(fd, buf, 256);
-	if (read_rv < 0)
-		return read_rv;
-	memcpy(&header->magic,		buf +   0,  4);
-	memcpy(&header->hdrlen,		buf +   4,  2);
-	memcpy(&header->hdrtype,	buf +   6,  2);
-	memcpy(&header->bcookie,	buf +   8,  8);
-	memcpy(&header->encrypt,	buf +  16,  2);
-	memcpy(&header->compress,	buf +  18,  2);
-	memcpy(&header->totfiles,	buf +  20,  2);
-	memcpy(&header->filesleft,	buf +  22,  2);
-	memcpy(&header->totparts,	buf +  24,  2);
-	memcpy(&header->partsleft,	buf +  26,  2);
-	memcpy(&header->totsize,	buf +  28,  4);
-	memcpy(&header->size,		buf +  32,  4);
-	memcpy(&header->modtime,	buf +  36,  4);
-	memcpy(&header->checksum,	buf +  40,  4);
-	memcpy(&header->rfrcsum,	buf +  44,  4);
-	memcpy(&header->rfsize,		buf +  48,  4);
-	memcpy(&header->cretime,	buf +  52,  4);
-	memcpy(&header->rfcsum,		buf +  56,  4);
-	memcpy(&header->nrecvd,		buf +  60,  4);
-	memcpy(&header->recvcsum,	buf +  64,  4);
-	memcpy(&header->idstring,	buf +  68, 32);
-	memcpy(&header->flags,		buf + 100,  1);
-	memcpy(&header->lnameoffset,	buf + 101,  1);
-	memcpy(&header->lsizeoffset,	buf + 102,  1);
-	memcpy(&header->dummy,		buf + 103, 69);
-	memcpy(&header->macfileinfo,	buf + 172, 16);
-	memcpy(&header->nencode,	buf + 188,  2);
-	memcpy(&header->nlanguage,	buf + 190,  2);
-	memcpy(&header->name,		buf + 192, 64);
-	return read_rv;
-}
-
-static int write_file_header(int fd, struct file_header *header) {
-	char buf[257];
-	memcpy(buf +   0, &header->magic,	 4);
-	memcpy(buf +   4, &header->hdrlen,	 2);
-	memcpy(buf +   6, &header->hdrtype,	 2);
-	memcpy(buf +   8, &header->bcookie,	 8);
-	memcpy(buf +  16, &header->encrypt,	 2);
-	memcpy(buf +  18, &header->compress,	 2);
-	memcpy(buf +  20, &header->totfiles,	 2);
-	memcpy(buf +  22, &header->filesleft,	 2);
-	memcpy(buf +  24, &header->totparts,	 2);
-	memcpy(buf +  26, &header->partsleft,	 2);
-	memcpy(buf +  28, &header->totsize,	 4);
-	memcpy(buf +  32, &header->size,	 4);
-	memcpy(buf +  36, &header->modtime,	 4);
-	memcpy(buf +  40, &header->checksum,	 4);
-	memcpy(buf +  44, &header->rfrcsum,	 4);
-	memcpy(buf +  48, &header->rfsize,	 4);
-	memcpy(buf +  52, &header->cretime,	 4);
-	memcpy(buf +  56, &header->rfcsum,	 4);
-	memcpy(buf +  60, &header->nrecvd,	 4);
-	memcpy(buf +  64, &header->recvcsum,	 4);
-	memcpy(buf +  68, &header->idstring,	32);
-	memcpy(buf + 100, &header->flags,	 1);
-	memcpy(buf + 101, &header->lnameoffset,	 1);
-	memcpy(buf + 102, &header->lsizeoffset,	 1);
-	memcpy(buf + 103, &header->dummy,	69);
-	memcpy(buf + 172, &header->macfileinfo,	16);
-	memcpy(buf + 188, &header->nencode,	 2);
-	memcpy(buf + 190, &header->nlanguage,	 2);
-	memcpy(buf + 192, &header->name,	64);
-	return write(fd, buf, 256);
-}
-
-static void do_get_file(GtkWidget *w, struct file_transfer *ft)
-{
-	char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window));
-	char buf[BUF_LONG];
-	char *buf2;
-	char tmp_buf[MSG_LEN];
-	struct file_header header;
-	int read_rv;
-	guint32 rcv;
-	int cont = 1;
-	GtkWidget *fw = NULL, *fbar = NULL, *label = NULL;
-	GtkWidget *button = NULL, *pct = NULL;
-
-	if (file_is_dir(file, ft->window)) {
-	  	return;
-	}
-
-	if (!(ft->f = fopen(file,"w"))) {
-                g_snprintf(buf, BUF_LONG / 2, _("Error writing file %s"), file);
-		do_error_dialog(buf, _("Error"));
-		ft->accepted = 0;
-		accept_callback(NULL, ft);
-		return;
-	}
-
-	ft->accepted = 1;
-	
-	gtk_widget_destroy(ft->window);
-	ft->window = NULL;
-	g_snprintf(tmp_buf, MSG_LEN, "toc_rvous_accept %s %s %s", ft->user, ft->cookie, ft->UID);
-	sflap_send(ft->gc, tmp_buf, -1, TYPE_DATA);
-
-
-
-	/* XXX is ft->port in host order or network order? */
-	ft->fd = proxy_connect(ft->ip, ft->port, NULL, 0, -1);
-
-	if (ft->fd <= -1) {
-		fclose(ft->f);
-		free_ft(ft);
-		return;
-	}
-
-	read_rv = read_file_header(ft->fd, &header);
-	if(read_rv < 0) {
-		close(ft->fd);
-		fclose(ft->f);
-		free_ft(ft);
-		return;
-	}
-
-	debug_printf("header length %d\n", header.hdrlen);
-
-	header.hdrtype = 0x202;
-	
-	buf2 = frombase64(ft->cookie);
-	memcpy(header.bcookie, buf2, 8);
-	snprintf(header.idstring, 32, "Gaim");
-	g_free(buf2);
-	header.encrypt = 0; header.compress = 0;
-	header.totparts = 1; header.partsleft = 1;
-
-	debug_printf("sending confirmation\n");
-	write_file_header(ft->fd, &header);
-
-	rcv = 0;
-
-	fw = gtk_dialog_new();
-	snprintf(buf, 2048, _("Receiving %s from %s"), ft->filename, ft->user);
-	label = gtk_label_new(buf);
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->vbox), label, 0, 0, 5);
-	gtk_widget_show(label);
-	fbar = gtk_progress_bar_new();
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), fbar, 0, 0, 5);
-	gtk_widget_show(fbar);
-	pct = gtk_label_new("0 %");
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), pct, 0, 0, 5);
-	gtk_widget_show(pct);
-	button = gtk_button_new_with_label(_("Cancel"));
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), button, 0, 0, 5);
-	gtk_widget_show(button);
-	if (display_options & OPT_DISP_COOL_LOOK)
-		gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
-	gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)toggle, &cont);
-	gtk_window_set_title(GTK_WINDOW(fw), _("Gaim - File Transfer"));
-	gtk_widget_realize(fw);
-	aol_icon(fw->window);
-	gtk_widget_show(fw);
-
-	debug_printf("Receiving %s from %s (%d bytes)\n", ft->filename, ft->user, ft->size);
-
-	fcntl(ft->fd, F_SETFL, O_NONBLOCK);
-
-	while (rcv != ft->size && cont) {
-		int i;
-		float pcnt = ((float)rcv)/((float)ft->size);
-		int remain = ft->size - rcv > 1024 ? 1024 : ft->size - rcv;
-		read_rv = read(ft->fd, buf, remain);
-		if(read_rv < 0) {
-			if (errno == EWOULDBLOCK) {
-				while(gtk_events_pending())
-					gtk_main_iteration();
-				continue;
-			}
-			gtk_widget_destroy(fw);
-			fw = NULL;
-			fclose(ft->f);
-			close(ft->fd);
-			free_ft(ft);
-			return;
-		}
-		rcv += read_rv;
-		for (i = 0; i < read_rv; i++)
-			fprintf(ft->f, "%c", buf[i]);
-		gtk_progress_bar_update(GTK_PROGRESS_BAR(fbar), pcnt);
-		sprintf(buf, "%d / %d K (%2.0f %%)", rcv/1024, ft->size/1024, 100*pcnt);
-		gtk_label_set_text(GTK_LABEL(pct), buf);
-		while(gtk_events_pending())
-			gtk_main_iteration();
-	}
-	fclose(ft->f);
-	gtk_widget_destroy(fw);
-	fw = NULL;
-
-	if (!cont) {
-		g_snprintf(tmp_buf, MSG_LEN, "toc_rvous_cancel %s %s %s", ft->user, ft->cookie, ft->UID);
-		sflap_send(ft->gc, tmp_buf, -1, TYPE_DATA);
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	debug_printf("Download complete.\n");
-
-	header.hdrtype = 0x402;
-	header.totparts = 0; header.partsleft = 0;
-	header.flags = 0;
-	header.recvcsum = header.checksum;
-	header.nrecvd = header.totsize;
-	write_file_header(ft->fd, &header);
-	close(ft->fd);
-
-	free_ft(ft);
-}
-
-static void send_file_callback(gpointer data, gint source,
-		GdkInputCondition condition) {
-	struct file_transfer *ft = (struct file_transfer *)data;
-	struct file_header fhdr;
-	int read_rv;
-	char buf[2048];
-	GtkWidget *fw = NULL, *fbar = NULL, *label = NULL;
-	GtkWidget *button = NULL, *pct = NULL;
-	int rcv, cont;
-
-	gdk_input_remove(snpa);
-	snpa = -1;
-
-	if (condition & GDK_INPUT_EXCEPTION) {
-		fclose(ft->f);
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	/* OK, so here's what's going on: we need to send a file. The person
-	 * sends us a file_header, then we send a file_header, then they send
-	 * us a file header, then we send the file, then they send a header,
-	 * and we're done. */
-
-	/* we can do some neat tricks because the other person sends us back
-	 * all the information we need in the file_header */
-
-	read_rv = read_file_header(ft->fd, &fhdr);
-	if (read_rv < 0) {
-		fclose(ft->f);
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	if (fhdr.hdrtype != 0xc12) {
-		debug_printf("%s decided to cancel. (%x)\n", ft->user, fhdr.hdrtype);
-		fclose(ft->f);
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	/* now we need to set the hdrtype to a certain value, but I don't know
-	 * what that value is, and I don't happen to have a win computer to do
-	 * my sniffing from :-P */
-	fhdr.hdrtype = ntohs(0x101);
-	fhdr.totfiles = 1;
-	fhdr.filesleft = 1;
-	fhdr.flags = 0x20;
-	write_file_header(ft->fd, &fhdr);
-	read_file_header(ft->fd, &fhdr);
-
-	fw = gtk_dialog_new();
-	snprintf(buf, 2048, _("Sending %s to %s"), fhdr.name, ft->user);
-	label = gtk_label_new(buf);
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->vbox), label, 0, 0, 5);
-	gtk_widget_show(label);
-	fbar = gtk_progress_bar_new();
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), fbar, 0, 0, 5);
-	gtk_widget_show(fbar);
-	pct = gtk_label_new("0 %");
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), pct, 0, 0, 5); 
-	gtk_widget_show(pct);
-	button = gtk_button_new_with_label(_("Cancel"));
-	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), button, 0, 0, 5);
-	gtk_widget_show(button);
-	if (display_options & OPT_DISP_COOL_LOOK)
-		gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
-	gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)toggle, &cont);
-	gtk_window_set_title(GTK_WINDOW(fw), _("Gaim - File Transfer"));
-	gtk_widget_realize(fw);
-	aol_icon(fw->window);
-	gtk_widget_show(fw);
-
-	debug_printf("Sending %s to %s (%ld bytes)\n", fhdr.name, ft->user, fhdr.totsize);
-
-	rcv = 0; cont = 1;
-	while (rcv != ntohl(fhdr.totsize) && cont) {
-		int i;
-		float pcnt = ((float)rcv)/((float)ntohl(fhdr.totsize));
-		int remain = ntohl(fhdr.totsize) - rcv > 1024 ? 1024 :
-			ntohl(fhdr.totsize) - rcv;
-		for (i = 0; i < remain; i++)
-			fscanf(ft->f, "%c", &buf[i]);
-		read_rv = write(ft->fd, buf, remain);
-		if (read_rv < 0) {
-			fclose(ft->f);
-			gtk_widget_destroy(fw);
-			fw = NULL;
-			fclose(ft->f);
-			close(ft->fd);
-			free_ft(ft);
-			return;
-		}
-		rcv += read_rv;
-		gtk_progress_bar_update(GTK_PROGRESS_BAR(fbar), pcnt);
-		sprintf(buf, "%d / %d K (%2.0f %%)", rcv/1024,
-				ntohl(fhdr.totsize)/1024, 100*pcnt);
-		gtk_label_set_text(GTK_LABEL(pct), buf);
-		while(gtk_events_pending())
-			gtk_main_iteration();
-	}
-	fclose(ft->f);
-	gtk_widget_destroy(fw);
-	fw = NULL;
-
-	if (!cont) {
-		char tmp_buf[MSG_LEN];
-		g_snprintf(tmp_buf, MSG_LEN, "toc_rvous_cancel %s %s %s", ft->user, ft->cookie, ft->UID);
-		sflap_send(ft->gc, tmp_buf, -1, TYPE_DATA);
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	debug_printf("Upload complete.\n");
-
-	read_file_header(ft->fd, &fhdr);
-
-	close(ft->fd);
-	free_ft(ft);
-}
-
-static void do_send_file(GtkWidget *w, struct file_transfer *ft) {
-	char *file = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window)));
-	char buf[BUF_LONG];
-	char *buf2;
-	char tmp_buf[MSG_LEN];
-	int read_rv;
-	int at;
-	struct file_header fhdr;
-	guint32 rcv = 0;
-	char *c;
-	struct stat st;
-	struct tm *fortime;
-
-	if (file_is_dir (file, ft->window)) {
-		g_free(file);
-		return;
-	}
-
-	stat(file, &st);
-	if (!(ft->f = fopen(file, "r"))) {
-		g_snprintf(buf, BUF_LONG / 2, _("Error reading file %s"), file);
-		do_error_dialog(buf, _("Error"));
-		ft->accepted = 0;
-		accept_callback(NULL, ft);
-		free_ft(ft);
-		return;
-	}
-
-	ft->accepted = 1;
-	ft->filename = file;
-
-	gtk_widget_destroy(ft->window);
-	ft->window = NULL;
-	g_snprintf(tmp_buf, MSG_LEN, "toc_rvous_accept %s %s %s", ft->user, ft->cookie, ft->UID);
-	sflap_send(ft->gc, tmp_buf, -1, TYPE_DATA);
-
-
-	/* XXX is ft->port in host order or network order? */
-	ft->fd = proxy_connect(ft->ip, ft->port, NULL, 0, -1);
-
-	if (ft->fd <= -1) {
-		free_ft(ft);
-		return;
-	}
-
-	/* here's where we differ from do_get_file */
-	/* 1. build/send header
-	 * 2. receive header
-	 * 3. send listing file
-	 * 4. receive header
-	 *
-	 * then we need to wait to actually send the file, if they want.
-	 *
-	 */
-
-	/* 1. build/send header */
-	c = file + strlen(file);
-	while (*(c - 1) != '/') c--;
-	buf2 = frombase64(ft->cookie);
-	debug_printf("Building header to send %s (cookie: %s)\n", file, buf2);
-	fhdr.magic[0] = 'O'; fhdr.magic[1] = 'F';
-	fhdr.magic[2] = 'T'; fhdr.magic[3] = '2';
-	fhdr.hdrlen = htons(256);
-	fhdr.hdrtype = htons(0x1108);
-	snprintf(fhdr.bcookie, 8, "%s", buf2);
-	g_free(buf2);
-	fhdr.encrypt = 0;
-	fhdr.compress = 0;
-	fhdr.totfiles = htons(1);
-	fhdr.filesleft = htons(1);
-	fhdr.totparts = htons(1);
-	fhdr.partsleft = htons(1);
-	fhdr.totsize = htonl((long)st.st_size); /* combined size of all files */
-	/* size = strlen("mm/dd/yyyy hh:mm sizesize 'name'\r\n") */
-	fhdr.size = htonl(28 + strlen(c)); /* size of listing.txt */
-	fhdr.modtime = htonl(time(NULL)); /* time since UNIX epoch */
-	fhdr.checksum = htonl(0x89f70000); /* ? i don't think this matters */
-	fhdr.rfrcsum = 0;
-	fhdr.rfsize = 0;
-	fhdr.cretime = 0;
-	fhdr.rfcsum = 0;
-	fhdr.nrecvd = 0;
-	fhdr.recvcsum = 0;
-	snprintf(fhdr.idstring, 32, "OFT_Windows ICBMFT V1.1 32");
-	fhdr.flags = 0x02;		/* don't ask me why */
-	fhdr.lnameoffset = 0x1A;	/* ? still no clue */
-	fhdr.lsizeoffset = 0x10;	/* whatever */
-	memset(fhdr.dummy, 0, 69);
-	memset(fhdr.macfileinfo, 0, 16);
-	fhdr.nencode = 0;
-	fhdr.nlanguage = 0;
-	snprintf(fhdr.name, 64, "listing.txt");
-	read_rv = write_file_header(ft->fd, &fhdr);
-	if (read_rv <= -1) {
-		debug_printf("Couldn't write opening header\n");
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	/* 2. receive header */
-	debug_printf("Receiving header\n");
-	read_rv = read_file_header(ft->fd, &fhdr);
-	if (read_rv <= -1) {
-		debug_printf("Couldn't read header\n");
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	/* 3. send listing file */
-	/* mm/dd/yyyy hh:mm sizesize name.ext\r\n */
-	/* creation date ^ */
-	debug_printf("Sending file\n");
-	fortime = localtime(&st.st_ctime);
-	at = g_snprintf(buf, ntohl(fhdr.size) + 1, "%2d/%2d/%4d %2d:%2d %8ld ",
-			fortime->tm_mon + 1, fortime->tm_mday, fortime->tm_year + 1900,
-			fortime->tm_hour + 1, fortime->tm_min + 1,
-			(long)st.st_size);
-	g_snprintf(buf + at, ntohl(fhdr.size) + 1 - at, "%s\r\n", c);
-	debug_printf("Sending listing.txt (%d bytes) to %s\n", ntohl(fhdr.size) + 1, ft->user);
-
-	read_rv = write(ft->fd, buf, ntohl(fhdr.size));
-	if (read_rv <= -1) {
-		debug_printf("Could not send file, wrote %d\n", rcv);
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	/* 4. receive header */
-	debug_printf("Receiving closing header\n");
-	read_rv = read_file_header(ft->fd, &fhdr);
-	if (read_rv <= -1) {
-		debug_printf("Couldn't read closing header\n");
-		close(ft->fd);
-		free_ft(ft);
-		return;
-	}
-
-	snpa = gdk_input_add(ft->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
-				send_file_callback, ft);
-
-}
-
-void accept_file_dialog(struct file_transfer *ft)
-{
-        GtkWidget *accept, *info, *warn, *cancel;
-        GtkWidget *label;
-        GtkWidget *vbox, *bbox;
-        char buf[1024];
-
-        
-        ft->window = gtk_window_new(GTK_WINDOW_DIALOG);
-        gtk_window_set_wmclass(GTK_WINDOW(ft->window), "accept_file", "Gaim");
-
-        accept = gtk_button_new_with_label(_("Accept"));
-        info = gtk_button_new_with_label(_("Info"));
-        warn = gtk_button_new_with_label(_("Warn"));
-        cancel = gtk_button_new_with_label(_("Cancel"));
-
-        bbox = gtk_hbox_new(TRUE, 10);
-        vbox = gtk_vbox_new(FALSE, 5);
-
-        gtk_widget_show(accept);
-        gtk_widget_show(info);
-        gtk_widget_show(warn);
-        gtk_widget_show(cancel);
-
-		if (display_options & OPT_DISP_COOL_LOOK)
-		{
-			gtk_button_set_relief(GTK_BUTTON(accept), GTK_RELIEF_NONE);
-			gtk_button_set_relief(GTK_BUTTON(info), GTK_RELIEF_NONE);
-			gtk_button_set_relief(GTK_BUTTON(warn), GTK_RELIEF_NONE);
-			gtk_button_set_relief(GTK_BUTTON(cancel), GTK_RELIEF_NONE);
-		}
-
-        gtk_box_pack_start(GTK_BOX(bbox), accept, TRUE, TRUE, 10);
-        gtk_box_pack_start(GTK_BOX(bbox), info, TRUE, TRUE, 10);
-        gtk_box_pack_start(GTK_BOX(bbox), warn, TRUE, TRUE, 10);
-        gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 10);
-
-	if (!strcmp(ft->UID, FILE_SEND_UID)) {
-	        g_snprintf(buf, sizeof(buf), _("%s requests you to accept the file: %s (%d bytes)"),
-				ft->user, ft->filename, ft->size);
-	} else {
-		g_snprintf(buf, sizeof(buf), _("%s requests you to send them a file"),
-				ft->user);
-	}
-        if (ft->message)
-		strncat(buf, ft->message, sizeof(buf) - strlen(buf));
-        label = gtk_label_new(buf);
-        gtk_widget_show(label);
-        gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 5);
-        gtk_box_pack_start(GTK_BOX(vbox), bbox, TRUE, TRUE, 5);
-
-        gtk_window_set_title(GTK_WINDOW(ft->window), _("Gaim - File Transfer?"));
-        gtk_window_set_focus(GTK_WINDOW(ft->window), accept);
-        gtk_container_add(GTK_CONTAINER(ft->window), vbox);
-        gtk_container_border_width(GTK_CONTAINER(ft->window), 10);
-        gtk_widget_show(vbox);
-        gtk_widget_show(bbox);
-        gtk_widget_realize(ft->window);
-        aol_icon(ft->window->window);
-
-        gtk_widget_show(ft->window);
-
-
-	gtk_signal_connect(GTK_OBJECT(accept), "clicked",
-			   GTK_SIGNAL_FUNC(accept_callback), ft);
-	gtk_signal_connect(GTK_OBJECT(cancel), "clicked",
-			   GTK_SIGNAL_FUNC(cancel_callback), ft);
-	gtk_signal_connect(GTK_OBJECT(warn), "clicked",
-			   GTK_SIGNAL_FUNC(warn_callback), ft);
-	gtk_signal_connect(GTK_OBJECT(info), "clicked",
-			   GTK_SIGNAL_FUNC(info_callback), ft);
-
-
-	if (ft->message) {
-		/* we'll do this later
-		while(gtk_events_pending())
-			gtk_main_iteration();
-		html_print(text, ft->message);
-		*/
-	}
-}
--- a/src/toc.c	Thu Feb 01 08:37:16 2001 +0000
+++ b/src/toc.c	Thu Feb 01 11:29:15 2001 +0000
@@ -46,7 +46,7 @@
 #include "pixmaps/dt_icon.xpm"
 #include "pixmaps/free_icon.xpm"
 
-#define REVISION "gaim:$Revision: 1445 $"
+#define REVISION "gaim:$Revision: 1467 $"
 
 #define TYPE_SIGNON    1
 #define TYPE_DATA      2
@@ -69,6 +69,27 @@
 #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 toc_data {
 	int toc_fd;
 	int seqno;
@@ -98,6 +119,7 @@
 
 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
@@ -161,7 +183,7 @@
 	close(((struct toc_data *)gc->proto_data)->toc_fd);
 }
 
-int sflap_send(struct gaim_connection *gc, char *buf, int olen, int type)
+static int sflap_send(struct gaim_connection *gc, char *buf, int olen, int type)
 {
 	int len;
 	int slen = 0;
@@ -337,8 +359,7 @@
 		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",
-			   FILE_SEND_UID, FILE_GET_UID);
+		g_snprintf(snd, sizeof snd, "toc_set_caps %s", FILE_SEND_UID);
 		sflap_send(gc, snd, -1, TYPE_DATA);
 
 		return;
@@ -561,7 +582,7 @@
 			int unk[4], i;
 			char *messages[4], *tmp, *name;
 			int subtype, files, totalsize = 0;
-			struct file_transfer *ft;
+			struct ft_request *ft;
 
 			for (i = 0; i < 4; i++) {
 				sscanf(strtok(NULL, ":"), "%d", &unk[i]);
@@ -588,7 +609,7 @@
 
 			name = tmp + 8;
 
-			ft = g_new0(struct file_transfer, 1);
+			ft = g_new0(struct ft_request, 1);
 			ft->cookie = g_strdup(cookie);
 			ft->ip = g_strdup(pip);
 			ft->port = port;
@@ -599,6 +620,7 @@
 			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;
 
@@ -606,12 +628,15 @@
 			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 */
+			/* they want us to send a file
 			int unk[4], i;
 			char *messages[4], *tmp;
-			struct file_transfer *ft;
+			struct ft_request *ft;
 
 			for (i = 0; i < 4; i++) {
 				sscanf(strtok(NULL, ":"), "%d", unk + i);
@@ -621,7 +646,7 @@
 			}
 			tmp = frombase64(strtok(NULL, ":"));
 
-			ft = g_new0(struct file_transfer, 1);
+			ft = g_new0(struct ft_request, 1);
 			ft->cookie = g_strdup(cookie);
 			ft->ip = g_strdup(pip);
 			ft->port = port;
@@ -638,6 +663,7 @@
 				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)) {
@@ -1219,3 +1245,284 @@
 	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;
+
+	GtkWidget *window;
+	FILE *file;
+	int recvsize;
+
+	gint inpa;
+};
+
+static void toc_get_file(gpointer a, struct file_transfer *ft) {
+	char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window));
+
+	if (file_is_dir(dirname, ft->window))
+		return;
+	gtk_widget_destroy(ft->window);
+}
+
+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->user);
+		g_free(ft->ip);
+		g_free(ft->cookie);
+		fclose(ft->file);
+		g_free(ft);
+		return;
+	}
+
+	if (ft->hdr.hdrtype != 0x202) {
+		char *buf = frombase64(ft->cookie);
+
+		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);
+
+		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);
+		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 = 0x402;
+		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);
+		ft->recvsize = 0;
+		if (ft->hdr.filesleft != 0) {
+			char *msg = g_strdup_printf("%s tried to send you more than one file, but"
+					" currently that is not possible.", ft->user);
+			do_error_dialog(msg, "Error");
+			g_free(msg);
+		}
+		gdk_input_remove(ft->inpa);
+		close(source);
+		g_free(ft->user);
+		g_free(ft->ip);
+		g_free(ft->cookie);
+		fclose(ft->file);
+		g_free(ft);
+	}
+}
+
+static void toc_send_file(gpointer a, struct file_transfer *old_ft) {
+	struct file_transfer *ft;
+	char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window));
+	int fd;
+	struct aim_user *user;
+	char *buf;
+
+	if (file_is_dir(dirname, old_ft->window))
+		return;
+	ft = g_new0(struct file_transfer, 1);
+	ft->file = fopen(dirname, "w");
+	if (!ft->file) {
+		do_error_dialog(_("Could not open file for writing!"), _("Error"));
+		g_free(ft);
+		gtk_widget_destroy(old_ft->window);
+		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);
+
+	buf = g_strdup_printf("toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_SEND_UID);
+	sflap_send(ft->gc, buf, -1, TYPE_DATA);
+	g_free(buf);
+
+	fd =
+	    proxy_connect(ft->ip, ft->port,
+			  user->proto_opt[USEROPT_SOCKSHOST],
+			  atoi(user->proto_opt[USEROPT_SOCKSPORT]),
+			  atoi(user->proto_opt[USEROPT_PROXYTYPE]));
+	if (fd < 0) {
+		do_error_dialog(_("Could not connect for transfer!"), _("Error"));
+		g_free(ft->cookie);
+		g_free(ft->user);
+		g_free(ft->ip);
+		g_free(ft);
+		return;
+	}
+
+	ft->inpa = gdk_input_add(fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, toc_send_file_callback, ft);
+}
+
+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->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);
+}