diff -Bur bitlbee-0.92/protocols/oscar/aim.h bitlbee-typing/protocols/oscar/aim.h --- bitlbee-0.92/protocols/oscar/aim.h 2004-10-10 07:24:06.000000000 -0400 +++ bitlbee-typing/protocols/oscar/aim.h 2005-05-24 15:58:47.000000000 -0400 @@ -811,6 +811,7 @@ aim_conn_t *aim_directim_connect(aim_session_t *, const char *sn, const char *addr, const guint8 *cookie); int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type); +int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 type2); aim_conn_t *aim_sendfile_initiate(aim_session_t *, const char *destsn, const char *filename, guint16 numfiles, guint32 totsize); aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn); diff -Bur bitlbee-0.92/protocols/oscar/aim_cbtypes.h bitlbee-typing/protocols/oscar/aim_cbtypes.h --- bitlbee-0.92/protocols/oscar/aim_cbtypes.h 2004-07-14 08:28:33.000000000 -0400 +++ bitlbee-typing/protocols/oscar/aim_cbtypes.h 2005-05-24 15:58:47.000000000 -0400 @@ -99,6 +99,7 @@ #define AIM_CB_MSG_MISSEDCALL 0x000a #define AIM_CB_MSG_CLIENTAUTORESP 0x000b #define AIM_CB_MSG_ACK 0x000c +#define AIM_CB_MSG_MTN 0x0014 #define AIM_CB_MSG_DEFAULT 0xffff /* diff -Bur bitlbee-0.92/protocols/oscar/im.c bitlbee-typing/protocols/oscar/im.c --- bitlbee-0.92/protocols/oscar/im.c 2004-10-10 07:24:06.000000000 -0400 +++ bitlbee-typing/protocols/oscar/im.c 2005-05-24 16:10:01.000000000 -0400 @@ -1987,6 +1987,90 @@ return ret; } +/* + * Subtype 0x0014 - Send a mini typing notification (mtn) packet. + * + * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, + * and Gaim 0.60 and newer. + * + */ +int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 type2) +{ + aim_conn_t *conn; + aim_frame_t *fr; + aim_snacid_t snacid; + + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) + return -EINVAL; + + if (!sn) + return -EINVAL; + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+11+strlen(sn)+2))) + return -ENOMEM; + + snacid = aim_cachesnac(sess, 0x0004, 0x0014, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0004, 0x0014, 0x0000, snacid); + + /* + * 8 days of light + * Er, that is to say, 8 bytes of 0's + */ + aimbs_put16(&fr->data, 0x0000); + aimbs_put16(&fr->data, 0x0000); + aimbs_put16(&fr->data, 0x0000); + aimbs_put16(&fr->data, 0x0000); + + /* + * Type 1 (should be 0x0001 for mtn) + */ + aimbs_put16(&fr->data, type1); + + /* + * Dest sn + */ + aimbs_put8(&fr->data, strlen(sn)); + aimbs_putraw(&fr->data, sn, strlen(sn)); + + /* + * Type 2 (should be 0x0000, 0x0001, or 0x0002 for mtn) + */ + aimbs_put16(&fr->data, type2); + + aim_tx_enqueue(sess, fr); + + return 0; +} + +/* + * Subtype 0x0014 - Receive a mini typing notification (mtn) packet. + * + * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, + * and Gaim 0.60 and newer. + * + */ +static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +{ + int ret = 0; + aim_rxcallback_t userfunc; + char *sn; + guint8 snlen; + guint16 type1, type2; + + aim_bstream_advance(bs, 8); /* Unknown - All 0's */ + type1 = aimbs_get16(bs); + snlen = aimbs_get8(bs); + sn = aimbs_getstr(bs, snlen); + type2 = aimbs_get16(bs); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, type1, sn, type2); + + g_free(sn); + + return ret; +} + static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { @@ -2002,6 +2086,8 @@ return clientautoresp(sess, mod, rx, snac, bs); else if (snac->subtype == 0x000c) return msgack(sess, mod, rx, snac, bs); + else if (snac->subtype == 0x0014) + return mtn_receive(sess, mod, rx, snac, bs); return 0; } diff -Bur bitlbee-0.92/protocols/oscar/oscar.c bitlbee-typing/protocols/oscar/oscar.c --- bitlbee-0.92/protocols/oscar/oscar.c 2005-02-23 17:26:59.000000000 -0500 +++ bitlbee-typing/protocols/oscar/oscar.c 2005-05-24 15:58:47.000000000 -0400 @@ -215,6 +215,7 @@ static int gaim_ssi_parseack (aim_session_t *, aim_frame_t *, ...); static int gaim_icqinfo (aim_session_t *, aim_frame_t *, ...); +static int gaim_parsemtn (aim_session_t *, aim_frame_t *, ...); static char *msgerrreason[] = { "Invalid error", @@ -548,6 +549,7 @@ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RIGHTSINFO, gaim_ssi_parserights, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_LIST, gaim_ssi_parselist, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_SRVACK, gaim_ssi_parseack, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parsemtn, 0); ((struct oscar_data *)gc->proto_data)->conn = bosconn; for (i = 0; i < (int)strlen(info->bosip); i++) { @@ -1663,6 +1665,7 @@ va_end(ap); /* Maybe senderwarn and recverwarn should be user preferences... */ + params->flags = 0x0000000b; params->maxmsglen = 8000; params->minmsginterval = 0; @@ -2286,6 +2289,25 @@ } +int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) +{ + struct gaim_connection * gc = sess->aux_data; + va_list ap; + guint16 type1, type2; + char * sn; + + va_start(ap, fr); + type1 = va_arg(ap, int); + sn = va_arg(ap, char*); + type2 = va_arg(ap, int); + va_end(ap); + + if(type2 == 0x0001 || type2 == 0x0002) + serv_got_typing(gc, sn, 0); + + return 1; +} + static char *oscar_get_status_string( struct gaim_connection *gc, int number ) { struct oscar_data *od = gc->proto_data; @@ -2314,6 +2336,12 @@ } } +int oscar_send_typing(struct gaim_connection *gc, char * who, int typing) +{ + struct oscar_data *od = gc->proto_data; + return( aim_im_sendmtn(od->sess, 1, who, typing ? 0x0002 : 0x0000) ); +} + static struct prpl *my_protocol = NULL; void oscar_init(struct prpl *ret) { @@ -2335,5 +2363,7 @@ ret->keepalive = oscar_keepalive; ret->get_status_string = oscar_get_status_string; + ret->send_typing = oscar_send_typing; + my_protocol = ret; }