# HG changeset patch # User Rob Flynn # Date 1018579430 0 # Node ID bcdbffc2c3e6ee8c781a559456a46e7005198ced # Parent aa18e79365b7557bf9edb7129aae7e9b68b0397b [gaim-migrate @ 3156] the kingant ate sean's picnic, too committer: Tailor Script diff -r aa18e79365b7 -r bcdbffc2c3e6 ChangeLog --- a/ChangeLog Fri Apr 12 02:40:41 2002 +0000 +++ b/ChangeLog Fri Apr 12 02:43:50 2002 +0000 @@ -12,6 +12,7 @@ * Fixed broken signal handling in gdm-started GNOME sessions (Thanks Jim Seymour, Vann, Robert McQueen) * Oscar group syncronization (Thanks, Mark Doliner) + * ICQ Authorization via Oscar (Thanks, Mark Doliner) version 0.55 (03/29/2002): * Jabber improvements (Thanks Jim Seymour) diff -r aa18e79365b7 -r bcdbffc2c3e6 src/protocols/oscar/aim.h --- a/src/protocols/oscar/aim.h Fri Apr 12 02:40:41 2002 +0000 +++ b/src/protocols/oscar/aim.h Fri Apr 12 02:43:50 2002 +0000 @@ -832,6 +832,17 @@ void *destructor; /* used internally only */ }; +/* Valid values for channel 4 args->type */ +#define AIM_ICQMSG_AUTHREQUEST 0x0006 +#define AIM_ICQMSG_AUTHDENIED 0x0007 +#define AIM_ICQMSG_AUTHGRANTED 0x0008 + +struct aim_incomingim_ch4_args { + fu32_t uin; /* Of the sender of the ICBM */ + fu16_t type; + char *msg; /* Reason for auth request, deny, or accept */ +}; + faim_export int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args); faim_export int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args); faim_export int aim_send_im(aim_session_t *, const char *destsn, unsigned short flags, const char *msg); @@ -844,6 +855,7 @@ faim_export aim_conn_t *aim_directim_connect(aim_session_t *, const char *sn, const char *addr, const fu8_t *cookie); faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize); +faim_export int aim_send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message); faim_export aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn); faim_export int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size); diff -r aa18e79365b7 -r bcdbffc2c3e6 src/protocols/oscar/im.c --- a/src/protocols/oscar/im.c Fri Apr 12 02:40:41 2002 +0000 +++ b/src/protocols/oscar/im.c Fri Apr 12 02:43:50 2002 +0000 @@ -732,6 +732,84 @@ return 0; } +/* + * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." + * The new way is to use SSI. I like the new way a lot better. This seems like such a hack, + * mostly because it's in network byte order. Figuring this stuff out sometimes takes a while, + * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people + * were taking when they merged the two protocols. + * + * sn is the destination screen name + * type is the type of message. 0x0007 for authorization denied. 0x0008 for authorization granted + * message is the message you want to send, it should be null terminated + */ +faim_export int aim_send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message) +{ + aim_conn_t *conn; + aim_frame_t *fr; + aim_snacid_t snacid; + int i; + + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) + return -EINVAL; + + if (!sn || !type || !message) + return -EINVAL; + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+3+strlen(sn)+12+strlen(message)+1+4))) + return -ENOMEM; + + snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + + /* + * Cookie + */ + for (i=0; i<8; i++) + aimbs_put8(&fr->data, (fu8_t)rand()); + + /* + * Channel (4) + */ + aimbs_put16(&fr->data, 0x0004); + + /* + * Dest sn + */ + aimbs_put8(&fr->data, strlen(sn)); + aimbs_putraw(&fr->data, sn, strlen(sn)); + + /* + * TLV t(0005) + * + * ICQ data (the UIN and the message). + */ + aimbs_put16(&fr->data, 0x0005); + aimbs_put16(&fr->data, 4 + 2+2+strlen(message)+1); + + /* + * Your UIN + */ + aimbs_putle32(&fr->data, atoi(sess->sn)); + + /* + * TLV t(type) l(strlen(message)+1) v(message+NULL) + */ + aimbs_putle16(&fr->data, type); + aimbs_putle16(&fr->data, strlen(message)+1); + aimbs_putraw(&fr->data, message, strlen(message)+1); + + /* + * TLV t(0006) l(0000) v() + */ + aimbs_put16(&fr->data, 0x0006); + aimbs_put16(&fr->data, 0x0000); + + aim_tx_enqueue(sess, fr); + + return 0; +} + static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { int i, ret = 0; @@ -1519,6 +1597,33 @@ return ret; } +static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie) +{ + aim_bstream_t meat; + aim_rxcallback_t userfunc; + aim_tlv_t *block; + struct aim_incomingim_ch4_args args; + int ret; + + /* + * Make a bstream for the meaty part. Yum. Meat. + */ + if (!(block = aim_gettlv(tlvlist, 0x0005, 1))) + return -1; + aim_bstream_init(&meat, block->value, block->length); + + args.uin = aimbs_getle32(&meat); + args.type = aimbs_getle16(&meat); + args.msg = aimbs_getraw(&meat, aimbs_getle16(&meat)); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); + + free(args.msg); + + return ret; +} + /* * It can easily be said that parsing ICBMs is THE single * most difficult thing to do in the in AIM protocol. In @@ -1556,7 +1661,10 @@ * Channel 0x0002 is the Rendevous channel, which * is where Chat Invitiations and various client-client * connection negotiations come from. - * + * + * Channel 0x0004 is used for ICQ authorization, or + * possibly any system notice. + * */ channel = aimbs_get16(bs); @@ -1602,6 +1710,13 @@ aim_freetlvchain(&tlvlist); + } else if (channel == 4) { + aim_tlvlist_t *tlvlist; + + tlvlist = aim_readtlvchain(bs); + ret = incomingim_ch4(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie); + aim_freetlvchain(&tlvlist); + } else { faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); diff -r aa18e79365b7 -r bcdbffc2c3e6 src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Fri Apr 12 02:40:41 2002 +0000 +++ b/src/protocols/oscar/oscar.c Fri Apr 12 02:43:50 2002 +0000 @@ -161,6 +161,11 @@ gboolean request; }; +struct icq_auth { + struct gaim_connection *gc; + fu32_t uin; +}; + static struct direct_im *find_direct_im(struct oscar_data *od, const char *who) { GSList *d = od->direct_ims; char *n = g_strdup(normalize(who)); @@ -1440,6 +1445,77 @@ return 1; } +static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { + char *uin, message; + struct oscar_data *od = (struct oscar_data *)data->gc->proto_data; + uin = g_strdup_printf("%d", data->uin); + message = 0; + aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); + show_got_added(data->gc, NULL, uin, NULL, NULL); + g_free(uin); + data->uin = 0; +} + +static void gaim_icq_authdeny(gpointer w, struct icq_auth *data) { + if (data->uin) { + char *uin, *message; + struct oscar_data *od = (struct oscar_data *)data->gc->proto_data; + uin = g_strdup_printf("%d", data->uin); + message = g_strdup_printf("No reason given."); + aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHDENIED, message); + g_free(uin); + g_free(message); + } + g_free(data); +} + +/* + * For when other people ask you for authorization + */ +static void gaim_icq_authask(struct gaim_connection *gc, fu32_t uin, char *msg) { + struct icq_auth *data = g_new(struct icq_auth, 1); + /* The first 6 chars of the message are some type of alien gibberish, so skip them */ + char *dialog_msg = g_strdup_printf("The user %d wants to add you to their buddy list for the following reason:\n\n%s", uin, (msg && strlen(msg)>6) ? msg+6 : "No reason given."); + debug_printf("Received an authorization request from UIN %ld\n", uin); + data->gc = gc; + data->uin = uin; + do_ask_dialog(dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny); + g_free(dialog_msg); +} + +static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args) { + struct gaim_connection *gc = sess->aux_data; + + switch (args->type) { + case 0x0006: { /* Someone requested authorization */ + gaim_icq_authask(gc, args->uin, args->msg); + } break; + + case 0x0007: { /* Someone has denied you authorization */ + char *dialog_msg; + dialog_msg = g_strdup_printf(_("The user %d has denied your request to add them to your contact list for the following reason:\n\n"), args->uin, args->msg ? args->msg : _("No reason given.")); + do_error_dialog(dialog_msg, _("Gaim - ICQ Authorization Denied")); + g_free(dialog_msg); + } break; + + case 0x0008: { /* Someone has granted you authorization */ + char *dialog_msg; + dialog_msg = g_strdup_printf(_("The user %d has granted your request to add them to your contact list."), args->uin); + do_error_dialog(dialog_msg, _("Gaim - ICQ Authorization Granted")); + g_free(dialog_msg); + } break; + + case 0x0012: { + /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */ + } break; + + default: { + debug_printf("Received a channel 4 message of unknown type (type 0x%04d).\n", args->type); + } break; + } + + return 1; +} static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) { int channel, ret = 0; @@ -1450,24 +1526,28 @@ channel = va_arg(ap, int); userinfo = va_arg(ap, aim_userinfo_t *); - /* channel 1: standard message */ - if (channel == 1) { - struct aim_incomingim_ch1_args *args; - - args = va_arg(ap, struct aim_incomingim_ch1_args *); - - ret = incomingim_chan1(sess, fr->conn, userinfo, args); - - } else if (channel == 2) { - struct aim_incomingim_ch2_args *args; - - args = va_arg(ap, struct aim_incomingim_ch2_args *); - - ret = incomingim_chan2(sess, fr->conn, userinfo, args); - } else if (channel == 3) { - printf("Chan 3\n"); - } else if (channel == 4) { - printf("Chan 4\n"); + switch (channel) { + case 1: { /* standard message */ + struct aim_incomingim_ch1_args *args; + args = va_arg(ap, struct aim_incomingim_ch1_args *); + ret = incomingim_chan1(sess, fr->conn, userinfo, args); + } break; + + case 2: { /* rendevous */ + struct aim_incomingim_ch2_args *args; + args = va_arg(ap, struct aim_incomingim_ch2_args *); + ret = incomingim_chan2(sess, fr->conn, userinfo, args); + } break; + + case 4: { /* ICQ */ + struct aim_incomingim_ch4_args *args; + args = va_arg(ap, struct aim_incomingim_ch4_args *); + ret = incomingim_chan4(sess, fr->conn, userinfo, args); + } break; + + default: { + debug_printf("ICBM received on unsupported channel (channel 0x%04d).", channel); + } break; } va_end(ap); @@ -2269,16 +2349,44 @@ msg = va_arg(ap, struct aim_icq_offlinemsg *); va_end(ap); - if (msg->type == 0x0001) { - char sender[32]; - char *tmp = g_strdup(msg->msg); - time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); - g_snprintf(sender, sizeof(sender), "%lu", msg->sender); - strip_linefeed(tmp); - serv_got_im(gc, sender, tmp, 0, t, -1); - g_free(tmp); - } else { - debug_printf("unknown offline message type 0x%04x\n", msg->type); + debug_printf("Received offline message of type 0x%04x\n", msg->type); + + switch (msg->type) { + case 0x0001: { /* Basic offline message */ + char sender[32]; + char *dialog_msg = g_strdup(msg->msg); + time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); + g_snprintf(sender, sizeof(sender), "%lu", msg->sender); + strip_linefeed(dialog_msg); + serv_got_im(gc, sender, dialog_msg, 0, t, -1); + g_free(dialog_msg); + } break; + + case 0x0006: { /* Authorization request */ + gaim_icq_authask(gc, msg->sender, msg->msg); + } break; + + case 0x0007: { /* Someone has denied you authorization */ + char *dialog_msg; + dialog_msg = g_strdup_printf(_("The user %d has denied your request to add them to your contact list for the following reason:\n\n"), msg->sender, msg->msg ? msg->msg : _("No reason given.")); + do_error_dialog(dialog_msg, _("Gaim - ICQ Authorization Denied")); + g_free(dialog_msg); + } break; + + case 0x0008: { /* Someone has granted you authorization */ + char *dialog_msg; + dialog_msg = g_strdup_printf(_("The user %d has granted your request to add them to your contact list."), msg->sender); + do_error_dialog(dialog_msg, _("Gaim - ICQ Authorization Granted")); + g_free(dialog_msg); + } break; + + case 0x0012: { + /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */ + } break; + + default: { + debug_printf("unknown offline message type 0x%04x\n", msg->type); + } } return 1;