# HG changeset patch # User Mark Doliner # Date 1048405135 0 # Node ID 773135edda4a09095509093f6be1c4b0a4aa3ad5 # Parent e6c7d67c1f3a39b83aaa4d8f35d74349c5bafc2a [gaim-migrate @ 5200] Added 3-stage typing notification for oscar direct connect (incoming and outgoing). Previously Gaim only had "typing" and "no text entered." I added support for "text typed." Made Gaim correctly recognize and send the auto-response flag for direct connections. So messages will probably show up as "AUTO-REPLY" for you and your amigo. Have gaim save your blist after recieving someone's icon, which is a bugfix from my code from last night, I think. Fixed a memleak in icon.c thanks to Nathan Walp. committer: Tailor Script diff -r e6c7d67c1f3a -r 773135edda4a src/protocols/oscar/aim.h --- a/src/protocols/oscar/aim.h Sat Mar 22 23:28:49 2003 +0000 +++ b/src/protocols/oscar/aim.h Sun Mar 23 07:38:55 2003 +0000 @@ -1004,7 +1004,7 @@ 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); +faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding, int isawaymsg); faim_export const char *aim_odc_getsn(aim_conn_t *conn); faim_export aim_conn_t *aim_odc_getconn(aim_session_t *sess, const char *sn); faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn); diff -r e6c7d67c1f3a -r 773135edda4a src/protocols/oscar/ft.c --- a/src/protocols/oscar/ft.c Sat Mar 22 23:28:49 2003 +0000 +++ b/src/protocols/oscar/ft.c Sun Mar 23 07:38:55 2003 +0000 @@ -306,7 +306,8 @@ * * @param sess The session. * @param conn The already-connected ODC connection. - * @param typing If true, notify user has started typing; if false, notify user has stopped. + * @param typing If 0x0002, sends a "typing" message, 0x0001 sends "typed," and + * 0x0000 sends "stopped." * @return Return 0 if no errors, otherwise return the error number. */ faim_export int aim_odc_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing) @@ -320,7 +321,7 @@ if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) return -EINVAL; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, 0))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0001, 0))) return -ENOMEM; memcpy(fr->hdr.rend.magic, "ODC2", 4); fr->hdr.rend.hdrlen = hdrlen; @@ -345,8 +346,12 @@ aimbs_put16(hdrbs, 0x0000); aimbs_put16(hdrbs, 0x0000); - /* flags -- 0x000e for "started typing", 0x0002 for "stopped typing */ - aimbs_put16(hdrbs, ( typing ? 0x000e : 0x0002)); + if (typing == 0x0002) + aimbs_put16(hdrbs, 0x0002 | 0x0008); + else if (typing == 0x0001) + aimbs_put16(hdrbs, 0x0002 | 0x0004); + else + aimbs_put16(hdrbs, 0x0002); aimbs_put16(hdrbs, 0x0000); aimbs_put16(hdrbs, 0x0000); @@ -380,9 +385,10 @@ * @param msg Null-terminated string to send. * @param len The length of the message to send, including binary data. * @param encoding 0 for ascii, 2 for Unicode, 3 for ISO 8859-1. + * @param isawaymsg 0 if this is not an auto-response, 1 if it is. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding) +faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding, int isawaymsg) { aim_frame_t *fr; aim_bstream_t *hdrbs; @@ -419,8 +425,8 @@ aimbs_put16(hdrbs, 0x0000); aimbs_put16(hdrbs, 0x0000); - /* flags -- 0x000e for "started typing", 0x0002 for "stopped typing, 0x0000 for message */ - aimbs_put16(hdrbs, 0x0000); + /* flags - used for typing notification and to mark if this is an away message */ + aimbs_put16(hdrbs, 0x0000 | isawaymsg); aimbs_put16(hdrbs, 0x0000); aimbs_put16(hdrbs, 0x0000); @@ -624,6 +630,7 @@ static int handlehdr_odc(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *frr, aim_bstream_t *bs) { aim_frame_t fr; + int ret = 0; aim_rxcallback_t userfunc; fu32_t payloadlength; fu16_t flags, encoding; @@ -647,54 +654,48 @@ faimdprintf(sess, 2, "faim: OFT frame: handlehdr_odc: %04x / %04x / %s\n", payloadlength, flags, snptr); - if (flags & 0x0002) { - int ret = 0; - - if (flags & 0x000c) { - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) - ret = userfunc(sess, &fr, snptr, 1); - return ret; - } - + if (flags & 0x0008) { + if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) + ret = userfunc(sess, &fr, snptr, 2); + } else if (flags & 0x0004) { + if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) + ret = userfunc(sess, &fr, snptr, 1); + } else { if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) ret = userfunc(sess, &fr, snptr, 0); - - return ret; + } - } else if (((flags & 0x000f) == 0x0000) && payloadlength) { - char *msg, *msg2; - int ret = 0; + if (payloadlength) { + char *msg; int recvd = 0; - int i; + int i, isawaymsg; + + isawaymsg = flags & 0x0001; if (!(msg = calloc(1, payloadlength+1))) - return -1; - msg2 = msg; - + return -ENOMEM; + while (payloadlength - recvd) { if (payloadlength - recvd >= 1024) - i = aim_recv(conn->fd, msg2, 1024); + i = aim_recv(conn->fd, &msg[recvd], 1024); else - i = aim_recv(conn->fd, msg2, payloadlength - recvd); + i = aim_recv(conn->fd, &msg[recvd], payloadlength - recvd); if (i <= 0) { free(msg); return -1; } recvd = recvd + i; - msg2 = msg2 + i; if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER))) - userfunc(sess, &fr, snptr, (double)recvd / payloadlength); + ret = userfunc(sess, &fr, snptr, (double)recvd / payloadlength); } - if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) ) - ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding); + if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING))) + ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding, isawaymsg); free(msg); - - return ret; } - return 0; + return ret; } /** diff -r e6c7d67c1f3a -r 773135edda4a src/protocols/oscar/icon.c --- a/src/protocols/oscar/icon.c Sat Mar 22 23:28:49 2003 +0000 +++ b/src/protocols/oscar/icon.c Sun Mar 23 07:38:55 2003 +0000 @@ -73,6 +73,7 @@ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) return userfunc(sess, rx, sn, iconcsum, iconcsumlen, icon, iconlen); + free(sn); free(iconcsum); free(icon); diff -r e6c7d67c1f3a -r 773135edda4a src/protocols/oscar/info.c --- a/src/protocols/oscar/info.c Sat Mar 22 23:28:49 2003 +0000 +++ b/src/protocols/oscar/info.c Sun Mar 23 07:38:55 2003 +0000 @@ -274,6 +274,9 @@ {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + /* + * Windows AIM calls this "Add-ins," which is probably more accurate + */ {AIM_CAPS_SAVESTOCKS, {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, diff -r e6c7d67c1f3a -r 773135edda4a src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Sat Mar 22 23:28:49 2003 +0000 +++ b/src/protocols/oscar/oscar.c Sun Mar 23 07:38:55 2003 +0000 @@ -3390,6 +3390,7 @@ b16 = tobase16(iconcsum, iconcsumlen); b = gaim_find_buddy(gc->account, sn); gaim_buddy_set_setting(b, "icon_checksum", b16); + gaim_blist_save(); free(b16); } @@ -4081,7 +4082,12 @@ struct oscar_data *od = (struct oscar_data *)gc->proto_data; struct direct_im *dim = find_direct_im(od, name); if (dim) - aim_odc_send_typing(od->sess, dim->conn, typing); + if (typing == TYPING) + aim_odc_send_typing(od->sess, dim->conn, 0x0002); + else if (typing == TYPED) + aim_odc_send_typing(od->sess, dim->conn, 0x0001); + else + aim_odc_send_typing(od->sess, dim->conn, 0x0000); else { struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(name)); if (bi && bi->typingnot) { @@ -4106,7 +4112,10 @@ if (dim && dim->connected) { /* If we're directly connected, send a direct IM */ /* XXX - The last parameter below is the encoding. Let Paco-Paco do something with it. */ - ret = aim_odc_send_im(od->sess, dim->conn, message, len == -1 ? strlen(message) : len, 0); + if (imflags & IM_FLAG_AWAY) + ret = aim_odc_send_im(od->sess, dim->conn, message, len == -1 ? strlen(message) : len, 0, 1); + else + ret = aim_odc_send_im(od->sess, dim->conn, message, len == -1 ? strlen(message) : len, 0, 0); } else if (len != -1) { /* Trying to send an IM image outside of a direct connection. */ oscar_ask_direct_im(gc, name); @@ -5232,22 +5241,27 @@ } static int gaim_odc_incoming(aim_session_t *sess, aim_frame_t *fr, ...) { + struct gaim_connection *gc = sess->aux_data; + int imflags = 0; va_list ap; - char *msg, *sn; - int len, encoding; - struct gaim_connection *gc = sess->aux_data; + char *sn, *msg; + int len, encoding, isawaymsg; va_start(ap, fr); sn = va_arg(ap, char *); msg = va_arg(ap, char *); len = va_arg(ap, int); encoding = va_arg(ap, int); + isawaymsg = va_arg(ap, int); va_end(ap); debug_printf("Got DirectIM message from %s\n", sn); + if (isawaymsg) + imflags |= IM_FLAG_AWAY; + /* XXX - I imagine Paco-Paco will want to do some voodoo with the encoding here */ - serv_got_im(gc, sn, msg, 0, time(NULL), len); + serv_got_im(gc, sn, msg, imflags, time(NULL), len); return 1; } @@ -5263,11 +5277,13 @@ typing = va_arg(ap, int); va_end(ap); - if (typing) { + if (typing == 0x0002) { /* 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", sn); serv_got_typing(gc, sn, 0, TYPING); - } else + } else if (typing == 0x0001) + serv_got_typing(gc, sn, 0, TYPED); + else serv_got_typing_stopped(gc, sn); return 1; }