changeset 4650:4938d12f6d48

[gaim-migrate @ 4961] This is mostly just me cleaning up some of my mess. The one important change is... I set what is believed to be the UTF8 capability flag for ICQ. I'm hoping this will tell ICQ2002 and more recent that we are able to accept UTF8 messages. Please test this and let us know what happens. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Wed, 05 Mar 2003 05:10:47 +0000
parents f04e2a5b637a
children 877407fc8cc3
files src/gaim.h src/protocols/oscar/aim.h src/protocols/oscar/ft.c src/protocols/oscar/im.c src/protocols/oscar/info.c src/protocols/oscar/oscar.c src/util.c
diffstat 7 files changed, 125 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/src/gaim.h	Tue Mar 04 21:38:05 2003 +0000
+++ b/src/gaim.h	Wed Mar 05 05:10:47 2003 +0000
@@ -454,6 +454,7 @@
  * encoding by checking the locale and trying some sane defaults ...
  * if everything fails it returns NULL. */
 char *gaim_try_conv_to_utf8(const char *str);
+char *gaim_getip_from_fd(int fd);
 
 /* Functions in log.h */
 extern FILE *open_log_file (const char *, int);
--- a/src/protocols/oscar/aim.h	Tue Mar 04 21:38:05 2003 +0000
+++ b/src/protocols/oscar/aim.h	Wed Mar 05 05:10:47 2003 +0000
@@ -996,7 +996,8 @@
 	struct aim_fileheader_t fh;
 };
 
-faim_export fu32_t aim_oft_checksum(const unsigned char *buffer, int bufferlen, fu32_t prevcheck);
+faim_export fu32_t aim_oft_checksum_chunk(const unsigned char *buffer, int bufferlen, fu32_t prevcheck);
+faim_export fu32_t aim_oft_checksum_file(char *filename);
 faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur);
 faim_export int aim_odc_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing);
 faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding);
@@ -1010,24 +1011,25 @@
 
 
 /* info.c */
-#define AIM_CAPS_BUDDYICON      0x00000001
-#define AIM_CAPS_VOICE          0x00000002
-#define AIM_CAPS_IMIMAGE        0x00000004
-#define AIM_CAPS_CHAT           0x00000008
-#define AIM_CAPS_GETFILE        0x00000010
-#define AIM_CAPS_SENDFILE       0x00000020
-#define AIM_CAPS_GAMES          0x00000040
-#define AIM_CAPS_SAVESTOCKS     0x00000080
-#define AIM_CAPS_SENDBUDDYLIST  0x00000100
-#define AIM_CAPS_GAMES2         0x00000200
-#define AIM_CAPS_ICQ            0x00000400
-#define AIM_CAPS_APINFO         0x00000800
+#define AIM_CAPS_BUDDYICON	0x00000001
+#define AIM_CAPS_VOICE		0x00000002
+#define AIM_CAPS_IMIMAGE	0x00000004
+#define AIM_CAPS_CHAT		0x00000008
+#define AIM_CAPS_GETFILE	0x00000010
+#define AIM_CAPS_SENDFILE	0x00000020
+#define AIM_CAPS_GAMES		0x00000040
+#define AIM_CAPS_SAVESTOCKS	0x00000080
+#define AIM_CAPS_SENDBUDDYLIST	0x00000100
+#define AIM_CAPS_GAMES2		0x00000200
+#define AIM_CAPS_ICQ		0x00000400
+#define AIM_CAPS_APINFO		0x00000800
 #define AIM_CAPS_ICQRTF		0x00001000
 #define AIM_CAPS_EMPTY		0x00002000
-#define AIM_CAPS_ICQSERVERRELAY 0x00004000
-#define AIM_CAPS_ICQUNKNOWN     0x00008000
-#define AIM_CAPS_TRILLIANCRYPT  0x00010000
-#define AIM_CAPS_LAST           0x00020000
+#define AIM_CAPS_ICQSERVERRELAY	0x00004000
+#define AIM_CAPS_ICQUNKNOWN	0x00008000
+#define AIM_CAPS_TRILLIANCRYPT	0x00010000
+#define AIM_CAPS_ICQUTF8	0x00020000
+#define AIM_CAPS_LAST		0x00040000
 
 faim_export int aim_0002_000b(aim_session_t *sess, aim_conn_t *conn, const char *sn);
 
--- a/src/protocols/oscar/ft.c	Tue Mar 04 21:38:05 2003 +0000
+++ b/src/protocols/oscar/ft.c	Wed Mar 05 05:10:47 2003 +0000
@@ -113,7 +113,7 @@
  * @param bufsize Size of buffer.
  * @param prevcheck Previous checksum.
  */
-faim_export fu32_t aim_oft_checksum(const unsigned char *buffer, int bufferlen, fu32_t prevcheck)
+faim_export fu32_t aim_oft_checksum_chunk(const unsigned char *buffer, int bufferlen, fu32_t prevcheck)
 {
 	fu32_t check = (prevcheck >> 16) & 0xffff, oldcheck;
 	int i;
@@ -138,6 +138,22 @@
 	return check << 16;
 }
 
+faim_export fu32_t aim_oft_checksum_file(char *filename) {
+	FILE *fd;
+	fu32_t checksum = 0xffff0000;
+
+	if ((fd = fopen(filename, "rb"))) {
+		int bytes;
+		char buffer[1024];
+
+		while ((bytes = fread(buffer, 1, 1024, fd)))
+			checksum = aim_oft_checksum_chunk(buffer, bytes, checksum);
+		fclose(fd);
+	}
+
+	return checksum;
+}
+
 /**
  * Create a listening socket on a given port.
  *
--- a/src/protocols/oscar/im.c	Tue Mar 04 21:38:05 2003 +0000
+++ b/src/protocols/oscar/im.c	Wed Mar 05 05:10:47 2003 +0000
@@ -711,7 +711,8 @@
 /*		aim_addtlvtochain_raw(&subtl, 0x000e, 2, "en");
 		aim_addtlvtochain_raw(&subtl, 0x000d, 8, "us-ascii");
 		aim_addtlvtochain_raw(&subtl, 0x000c, 24, "Please accept this file."); */
-		aim_addtlvtochain_raw(&subtl, 0x0003, 4, ip);
+		if (ip[0])
+			aim_addtlvtochain_raw(&subtl, 0x0003, 4, ip);
 		aim_addtlvtochain16(&subtl, 0x0005, port);
 
 		/* TLV t(2711) */
--- a/src/protocols/oscar/info.c	Tue Mar 04 21:38:05 2003 +0000
+++ b/src/protocols/oscar/info.c	Wed Mar 05 05:10:47 2003 +0000
@@ -303,13 +303,22 @@
 	 {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
-	/* from ICQ2002a
-	{AIM_CAPS_ICQUNKNOWN2,
+	{AIM_CAPS_ICQUTF8,
 	 {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, */
+	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+	{AIM_CAPS_ICQUNKNOWN,
+	 {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,
+	  0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}},
+
+	/*
+	{AIM_CAPS_ICQ2GO,
+	 {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd,
+	  0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}},
+	*/
 
 	{AIM_CAPS_ICQRTF,
-	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 
+	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
 	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}},
 
 	/* supposed to be ICQRTF?
@@ -317,21 +326,17 @@
 	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 
 	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}}, */
 
-	{AIM_CAPS_ICQUNKNOWN,
-	 {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,
-	  0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}},
-
-	{AIM_CAPS_EMPTY,
-	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+	{AIM_CAPS_APINFO, 
+         {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6,
+	  0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}},
 
 	{AIM_CAPS_TRILLIANCRYPT,
 	 {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb,
 	  0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}},
 
-	{AIM_CAPS_APINFO, 
-         {0xAA, 0x4A, 0x32, 0xB5, 0xF8, 0x84, 0x48, 0xc6,
-	  0xA3, 0xD7, 0x8C, 0x50, 0x97, 0x19, 0xFD, 0x5B}},
+	{AIM_CAPS_EMPTY,
+	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
 
 	{AIM_CAPS_LAST}
 };
--- a/src/protocols/oscar/oscar.c	Tue Mar 04 21:38:05 2003 +0000
+++ b/src/protocols/oscar/oscar.c	Wed Mar 05 05:10:47 2003 +0000
@@ -95,7 +95,7 @@
 
 /* Set AIM caps, because Gaim can still do them over ICQ and 
  * Winicq doesn't mind. */
-static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_IMIMAGE | AIM_CAPS_SENDFILE;
+static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_IMIMAGE | AIM_CAPS_SENDFILE | AIM_CAPS_ICQUTF8;
 /* static int caps_icq = AIM_CAPS_ICQ; */
 /* What does AIM_CAPS_ICQ actually mean? -SE */
 
@@ -180,6 +180,8 @@
 /* BBB */
 struct oscar_xfer_data {
 	fu8_t cookie[8];
+	char *clientip;
+	char *clientip2;
 	fu32_t modtime;
 	fu32_t checksum;
 	aim_conn_t *conn;
@@ -336,67 +338,57 @@
 		return;
 
 	if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
-		xfer->filename = g_path_get_basename(xfer->local_filename);
-		if (xfer->local_port) {
-			int i;
-			char ip[4];
-			gchar **ipsplit = g_strsplit(xfer->local_ip, ".", 4);
+		int i;
+		char ip[4];
+		gchar **ipsplit;
+
+		if (xfer->local_ip) {
+			ipsplit = g_strsplit(xfer->local_ip, ".", 4);
 			for (i=0; ipsplit[i]; i++)
 				ip[i] = atoi(ipsplit[i]);
 			g_strfreev(ipsplit);
+		} else {
+			memset(ip, 0x00, 4);
+		}
+
+		xfer->filename = g_path_get_basename(xfer->local_filename);
+		xfer_data->checksum = aim_oft_checksum_file(xfer->local_filename);
+
+		/*
+		 * Try a few random ports.  Maybe we need a 
+		 * way to tell libfaim to listen for multiple 
+		 * connections on one listener socket.
+		 */
+		xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port);
+		for (i=0; (i<5 && !xfer_data->conn); i++) {
+			xfer->local_port = (rand() % (65535-1024)) + 1024;
 			xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port);
-			if (!xfer_data->conn) {
-				/*
-				 * Try a few random ports.  Maybe we need a 
-				 * way to tell libfaim to listen for multiple 
-				 * connections on one listener socket.
-				 */
-				for (i=0; (i<5 && !xfer_data->conn); i++) {
-					xfer->local_port = (rand() % (65535-1024)) + 1024;
-					xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port);
-				}
-			}
-			if (xfer_data->conn) {
-				xfer->watcher = gaim_input_add(xfer_data->conn->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn);
-				aim_im_sendch2_sendfile_ask(od->sess, xfer_data->cookie, xfer->who, ip, xfer->local_port, xfer->filename, 1, xfer->size);
-				aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_established, 0);
-				/* Calculate a checksum thingy.  This is ugly. */
-				/* if ((fd = open(xfer->local_filename, O_RDONLY))) {
-					int bytes;
-					char buf[1024];
-					xfer_data->checksum = 0xffff0000;
-					while ((bytes = aim_recv(fd, buf, 1024)) > 0)
-						xfer_data->checksum = aim_oft_checksum(buf, bytes, xfer_data->checksum);
-					close(fd);
-				} */
-			} else {
-				do_error_dialog(_("File Transfer Aborted"), _("Unable to establish listener socket."), GAIM_ERROR);
-				/* XXX - The below line causes a crash because the transfer is canceled before the "Ok" callback on the file selection thing exists, I think */
-				/* gaim_xfer_cancel(xfer); */
-			}
+		}
+		if (xfer_data->conn) {
+			xfer->watcher = gaim_input_add(xfer_data->conn->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn);
+			aim_im_sendch2_sendfile_ask(od->sess, xfer_data->cookie, xfer->who, ip, xfer->local_port, xfer->filename, 1, xfer->size);
+			aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_established, 0);
 		} else {
+			do_error_dialog(_("File Transfer Aborted"), _("Unable to establish listener socket."), GAIM_ERROR);
+			/* XXX - The below line causes a crash because the transfer is canceled before the "Ok" callback on the file selection thing exists, I think */
 			/* gaim_xfer_cancel(xfer); */
 		}
 	} else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
-		if (xfer->remote_ip && xfer->remote_port) {
-			xfer_data->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL);
-			if (xfer_data->conn) {
-				xfer_data->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
-				aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0);
-				xfer_data->conn->fd = xfer->fd = proxy_connect(gc->account, xfer->remote_ip, xfer->remote_port, oscar_sendfile_connected, xfer);
-				if (xfer->fd == -1) {
-					do_error_dialog(_("File Transfer Aborted"), _("Unable to establish file descriptor."), GAIM_ERROR);
-					/* gaim_xfer_cancel? */
-				}
-			} else {
-				do_error_dialog(_("File Transfer Aborted"), _("Unable to create new connection."), GAIM_ERROR);
+		xfer_data->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL);
+		if (xfer_data->conn) {
+			xfer_data->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
+			aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0);
+			xfer_data->conn->fd = xfer->fd = proxy_connect(gc->account, xfer->remote_ip, xfer->remote_port, oscar_sendfile_connected, xfer);
+			if (xfer->fd == -1) {
+				do_error_dialog(_("File Transfer Aborted"), _("Unable to establish file descriptor."), GAIM_ERROR);
 				/* gaim_xfer_cancel? */
-				/* Try a different port? Ask them to connect to us? */
 			}
 		} else {
-			/* I have a feeling this would crash */
-			/* gaim_xfer_cancel(xfer); */
+			do_error_dialog(_("File Transfer Aborted"), _("Unable to create new connection."), GAIM_ERROR);
+			/* gaim_xfer_cancel? */
+			/* Try a different port? Ask them to connect to us? */
 		}
+
 	}
 }
 
@@ -479,7 +471,7 @@
 	if (!(xfer_data = xfer->data))
 		return;
 
-	/* xfer_data->checksum = aim_oft_checksum(buffer, size, xfer_data->checksum); */
+	/* xfer_data->checksum = aim_oft_checksum_chunk(buffer, size, xfer_data->checksum); */
 }
 
 static struct gaim_xfer *
@@ -520,39 +512,6 @@
 	return NULL;
 }
 
-#if 0
-/* XXX there must be a better way than this.... -- wtm */
-static struct oscar_file_transfer *find_oft_by_conn(struct gaim_connection *gc, aim_conn_t *conn) {
-	GSList *g = ((struct oscar_data *)gc->proto_data)->file_transfers;
-	struct oscar_file_transfer *f = NULL;
-
-	while (g) {
-		f = (struct oscar_file_transfer *)g->data;
-		if (f->conn == conn)
-			break;
-		g = g->next;
-		f = NULL;
-	}
-
-	return f;
-}
-
-static struct oscar_file_transfer *find_oft_by_xfer(struct gaim_connection *gc, struct file_transfer *xfer) {
-	GSList *g = ((struct oscar_data *)gc->proto_data)->file_transfers;
-	struct oscar_file_transfer *f = NULL;
-
-	while (g) {
-		f = (struct oscar_file_transfer *)g->data;
-		if (f->xfer == xfer)
-			break;
-		g = g->next;
-		f = NULL;
-	}
-
-	return f;
-}
-#endif
-
 static int gaim_parse_auth_resp  (aim_session_t *, aim_frame_t *, ...);
 static int gaim_parse_login      (aim_session_t *, aim_frame_t *, ...);
 static int gaim_handle_redirect  (aim_session_t *, aim_frame_t *, ...);
@@ -977,15 +936,10 @@
 	xfer->data = xfer_data;
 
 	/* Set the info about the incoming file */
-	if (od) {
-		/* XXX - Create core gaim functions for getting ip and getting port from an fd */
-		aim_session_t *sess;
+	if (od && od->sess) {
 		aim_conn_t *conn;
-		struct sockaddr addr;
-		socklen_t namelen = sizeof(addr);
-		if ((sess = od->sess) && (conn = aim_conn_findbygroup(sess, 0x0004)))
-			if (!getsockname(conn->fd, &addr, &namelen))
-				xfer->local_ip = g_strdup(inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr));
+		if ((conn = aim_conn_findbygroup(od->sess, 0x0004)))
+			xfer->local_ip = gaim_getip_from_fd(conn->fd);
 	}
 	xfer->local_port = 5190;
 
@@ -1801,7 +1755,7 @@
 /*
  * This is called when a buddy sends us some file info.  This happens when they 
  * are sending a file to you, and you have just established a connection to them.
- * You should send them the exactly same info except use the real cookie.  We also 
+ * You should send them the exact same info except use the real cookie.  We also 
  * get like totally ready to like, receive the file, kay?
  */
 static int oscar_sendfile_prompt(aim_session_t *sess, aim_frame_t *fr, ...) {
@@ -2105,7 +2059,6 @@
 			struct gaim_xfer *xfer;
 			struct oscar_xfer_data *xfer_data;
 
-			/* XXX - Should do something with args->clientip or args->clientip2 */
 			if (!args->cookie || !args->verifiedip || !args->port ||
 			    !args->info.sendfile.filename || !args->info.sendfile.totsize ||
 			    !args->info.sendfile.totfiles || !args->reqclass)
@@ -2134,9 +2087,12 @@
 			/* Set the info about the incoming file */
 			gaim_xfer_set_filename(xfer, args->info.sendfile.filename);
 			gaim_xfer_set_size(xfer, args->info.sendfile.totsize);
-			/* XXX - xfer->remote_ip = g_strdup(args->verifiedip); */
-			xfer->remote_ip = g_strdup(args->clientip2);
 			xfer->remote_port = args->port;
+			xfer->remote_ip = g_strdup(args->verifiedip);
+			if (args->clientip)
+				xfer_data->clientip = g_strdup(args->clientip);
+			if (args->clientip2)
+				xfer_data->clientip2 = g_strdup(args->clientip2);
 
 			 /* Setup our I/O op functions */
 			gaim_xfer_set_init_fnc(xfer, oscar_xfer_init);
@@ -2181,8 +2137,8 @@
 		char buf[256];
 
 		if (!args->verifiedip) {
-				debug_printf("directim kill blocked (%s)\n", userinfo->sn);
-				return 1;
+			debug_printf("directim kill blocked (%s)\n", userinfo->sn);
+			return 1;
 		}
 
 		debug_printf("%s received direct im request from %s (%s)\n",
@@ -2192,8 +2148,7 @@
 		d->sn = g_strdup(userinfo->sn);
 		strncpy(d->ip, args->verifiedip, sizeof(d->ip));
 		memcpy(d->cookie, args->cookie, 8);
-		g_snprintf(buf, sizeof buf, "%s has just asked to directly connect to %s.",
-				userinfo->sn, gc->username);
+		g_snprintf(buf, sizeof buf, _("%s has just asked to directly connect to %s"), userinfo->sn, gc->username);
 		do_ask_dialog(buf, _("This requires a direct connection between the two computers and is necessary for IM Images.  Because your IP address will be revealed, this may be considered a privacy risk."), d, _("Connect"), accept_direct_im, _("Cancel"), cancel_direct_im, my_protocol->plug ? my_protocol->plug->handle : NULL, FALSE);
 	} else {
 		debug_printf("Unknown reqclass %hu\n", args->reqclass);
@@ -5196,6 +5151,7 @@
 			pbm->callback = oscar_ask_direct_im;
 			pbm->gc = gc;
 			m = g_list_append(m, pbm);
+
 #if 0
 			pbm = g_new0(struct proto_buddy_menu, 1);
 			pbm->label = _("Send File");
--- a/src/util.c	Tue Mar 04 21:38:05 2003 +0000
+++ b/src/util.c	Wed Mar 05 05:10:47 2003 +0000
@@ -1307,3 +1307,14 @@
 
 	return(NULL);
 }
+
+char *gaim_getip_from_fd(int fd)
+{
+	struct sockaddr addr;
+	socklen_t namelen = sizeof(addr);
+
+	if (getsockname(fd, &addr, &namelen))
+		return NULL;
+
+	return g_strdup(inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr));
+}