static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { aim_userinfo_t userinfo; char *text_encoding = NULL, *text = NULL; aim_rxcallback_t userfunc; aim_tlvlist_t *tlvlist; aim_snac_t *origsnac = NULL; struct aim_priv_inforeq *inforeq; int ret = 0; origsnac = aim_remsnac(sess, snac->id); if (!origsnac || !origsnac->data) { faimdprintf(sess, 0, "parse_userinfo_middle: major problem: no snac stored!\n"); return 0; } inforeq = (struct aim_priv_inforeq *)origsnac->data; if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) && (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE)) { faimdprintf(sess, 0, "parse_userinfo_middle: unknown infotype in request! (0x%04x)\n", inforeq->infotype); return 0; } aim_extractuserinfo(sess, bs, &userinfo); tlvlist = aim_readtlvchain(bs); /* * Depending on what informational text was requested, different * TLVs will appear here. * * Profile will be 1 and 2, away message will be 3 and 4. */ if (aim_gettlv(tlvlist, 0x0001, 1)) { text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1); text = aim_gettlv_str(tlvlist, 0x0002, 1); } else if (aim_gettlv(tlvlist, 0x0003, 1)) { text_encoding = aim_gettlv_str(tlvlist, 0x0003, 1); text = aim_gettlv_str(tlvlist, 0x0004, 1); } if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, &userinfo, text_encoding, text, inforeq->infotype); free(text_encoding); free(text); aim_freetlvchain(&tlvlist); if (origsnac) free(origsnac->data); free(origsnac); return ret; }
static int error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_snac_t *snac2; guint16 error, chatnav_error; GSList *tlvlist; snac2 = aim_remsnac(od, snac->id); if (!snac2) { purple_debug_warning("oscar", "chatnav error: received response to unknown request (%08x)\n", snac->id); return 0; } if (snac2->family != SNAC_FAMILY_CHATNAV) { purple_debug_warning("oscar", "chatnav error: received response that maps to corrupt request (fam=%04x)\n", snac2->family); g_free(snac2->data); g_free(snac2); return 0; } /* * We now know what the original SNAC subtype was. */ if (snac2->type == 0x0008) /* create room */ { error = byte_stream_get16(bs); tlvlist = aim_tlvlist_read(bs); chatnav_error = aim_tlv_get16(tlvlist, 0x0008, 1); purple_debug_warning("oscar", "Could not join room, error=0x%04hx, chatnav_error=0x%04hx\n", error, chatnav_error); purple_notify_error(od->gc, NULL, _("Could not join chat room"), chatnav_error == 0x0033 ? _("Invalid chat room name") : _("Unknown error"), purple_request_cpar_from_connection(od->gc)); ret = 1; } g_free(snac2->data); g_free(snac2); return ret; }
static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { aim_userinfo_t userinfo; char *text_encoding = NULL, *text = NULL; guint16 text_length = 0; aim_rxcallback_t userfunc; aim_tlvlist_t *tlvlist; aim_tlv_t *tlv; aim_snac_t *origsnac = NULL; struct aim_priv_inforeq *inforeq; int ret = 0; origsnac = aim_remsnac(sess, snac->id); if (!origsnac || !origsnac->data) { imcb_error(sess->aux_data, "major problem: no snac stored!"); return 0; } inforeq = (struct aim_priv_inforeq *)origsnac->data; if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) && (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE) && (inforeq->infotype != AIM_GETINFO_CAPABILITIES)) { imcb_error(sess->aux_data, "unknown infotype in request!"); return 0; } aim_extractuserinfo(sess, bs, &userinfo); tlvlist = aim_readtlvchain(bs); /* * Depending on what informational text was requested, different * TLVs will appear here. * * Profile will be 1 and 2, away message will be 3 and 4, caps * will be 5. */ if (inforeq->infotype == AIM_GETINFO_GENERALINFO) { text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1); if((tlv = aim_gettlv(tlvlist, 0x0002, 1))) { text = g_new0(char, tlv->length); memcpy(text, tlv->value, tlv->length); text_length = tlv->length; }
/* * Subtype 0x0009 * * Since multiple things can trigger this callback, we must lookup the * snacid to determine the original snac subtype that was called. * * XXX This isn't really how this works. But this is: Every d/9 response * has a 16bit value at the beginning. That matches to: * Short Desc = 1 * Full Desc = 2 * Instance Info = 4 * Nav Short Desc = 8 * Nav Instance Info = 16 * And then everything is really asynchronous. There is no specific * attachment of a response to a create room request, for example. Creating * the room yields no different a response than requesting the room's info. * */ static int parseinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_snac_t *snac2; int ret = 0; if (!(snac2 = aim_remsnac(od, snac->id))) { purple_debug_misc("oscar", "faim: chatnav_parse_info: received response to unknown request! (%08x)\n", snac->id); return 0; } if (snac2->family != SNAC_FAMILY_CHATNAV) { purple_debug_misc("oscar", "faim: chatnav_parse_info: received response that maps to corrupt request! (fam=%04x)\n", snac2->family); g_free(snac2->data); g_free(snac2); return 0; } /* * We now know what the original SNAC subtype was. */ if (snac2->type == 0x0002) /* request chat rights */ ret = parseinfo_perms(od, conn, mod, frame, snac, bs, snac2); else if (snac2->type == 0x0003) /* request exchange info */ purple_debug_misc("oscar", "chatnav_parse_info: response to exchange info\n"); else if (snac2->type == 0x0004) /* request room info */ purple_debug_misc("oscar", "chatnav_parse_info: response to room info\n"); else if (snac2->type == 0x0005) /* request more room info */ purple_debug_misc("oscar", "chatnav_parse_info: response to more room info\n"); else if (snac2->type == 0x0006) /* request occupant list */ purple_debug_misc("oscar", "chatnav_parse_info: response to occupant info\n"); else if (snac2->type == 0x0007) /* search for a room */ purple_debug_misc("oscar", "chatnav_parse_info: search results\n"); else if (snac2->type == 0x0008) /* create room */ ret = parseinfo_create(od, conn, mod, frame, snac, bs, snac2); else purple_debug_misc("oscar", "chatnav_parse_info: unknown request subtype (%04x)\n", snac2->type); if (snac2) g_free(snac2->data); g_free(snac2); return ret; }
/* * Subtype 0x0001 */ static int error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; aim_snac_t *snac2; guint16 reason; char *sn; int was_explicit; if (!(snac2 = aim_remsnac(od, snac->id))) { purple_debug_misc("oscar", "faim: locate.c, error(): received response from unknown request!\n"); return 0; } if ((snac2->family != 0x0002) && (snac2->type != 0x0015)) { purple_debug_misc("oscar", "faim: locate.c, error(): received response from invalid request! %d\n", snac2->family); return 0; } if (!(sn = snac2->data)) { purple_debug_misc("oscar", "faim: locate.c, error(): received response from request without a screen name!\n"); return 0; } reason = byte_stream_get16(bs); /* * Remove this screen name from our queue. If the client requested * this buddy's info explicitly, then notify them that we do not have * info for this buddy. */ was_explicit = aim_locate_gotuserinfo(od, conn, sn); if (was_explicit == TRUE) if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, reason, sn); if (snac2) g_free(snac2->data); g_free(snac2); return ret; }
/* * Since multiple things can trigger this callback, we must lookup the * snacid to determine the original snac subtype that was called. * * XXX This isn't really how this works. But this is: Every d/9 response * has a 16bit value at the beginning. That matches to: * Short Desc = 1 * Full Desc = 2 * Instance Info = 4 * Nav Short Desc = 8 * Nav Instance Info = 16 * And then everything is really asynchronous. There is no specific * attachment of a response to a create room request, for example. Creating * the room yields no different a response than requesting the room's info. * */ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { aim_snac_t *snac2; int ret = 0; if (!(snac2 = aim_remsnac(sess, snac->id))) { faimdprintf(sess, 0, "faim: chatnav_parse_info: received response to unknown request! (%08lx)\n", snac->id); return 0; } if (snac2->family != 0x000d) { faimdprintf(sess, 0, "faim: chatnav_parse_info: recieved response that maps to corrupt request! (fam=%04x)\n", snac2->family); return 0; } /* * We now know what the original SNAC subtype was. */ if (snac2->type == 0x0002) /* request chat rights */ ret = parseinfo_perms(sess, mod, rx, snac, bs, snac2); else if (snac2->type == 0x0003) /* request exchange info */ faimdprintf(sess, 0, "chatnav_parse_info: resposne to exchange info\n"); else if (snac2->type == 0x0004) /* request room info */ faimdprintf(sess, 0, "chatnav_parse_info: response to room info\n"); else if (snac2->type == 0x0005) /* request more room info */ faimdprintf(sess, 0, "chatnav_parse_info: response to more room info\n"); else if (snac2->type == 0x0006) /* request occupant list */ faimdprintf(sess, 0, "chatnav_parse_info: response to occupant info\n"); else if (snac2->type == 0x0007) /* search for a room */ faimdprintf(sess, 0, "chatnav_parse_info: search results\n"); else if (snac2->type == 0x0008) /* create room */ ret = parseinfo_create(sess, mod, rx, snac, bs, snac2); else faimdprintf(sess, 0, "chatnav_parse_info: unknown request subtype (%04x)\n", snac2->type); if (snac2) free(snac2->data); free(snac2); return ret; }
/* * Should be generic enough to handle the errors for all groups. * */ static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { int ret = 0; int error = 0; aim_rxcallback_t userfunc; aim_snac_t *snac2; snac2 = aim_remsnac(sess, snac->id); if (aim_bstream_empty(bs)) error = aimbs_get16(bs); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL); if (snac2) g_free(snac2->data); g_free(snac2); return ret; }
/* * Subtype 0x0001 */ static int error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; aim_snac_t *snac2; guint16 reason; char *bn; if (!(snac2 = aim_remsnac(od, snac->id))) { purple_debug_misc("oscar", "locate error: received response from unknown request!\n"); return 0; } if ((snac2->family != SNAC_FAMILY_LOCATE) && (snac2->type != 0x0015)) { purple_debug_misc("oscar", "locate error: received response from invalid request! %d\n", snac2->family); g_free(snac2->data); g_free(snac2); return 0; } if (!(bn = snac2->data)) { purple_debug_misc("oscar", "locate error: received response from request without a buddy name!\n"); g_free(snac2); return 0; } reason = byte_stream_get16(bs); /* Notify the user that we do not have info for this buddy */ if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, reason, bn); if (snac2) g_free(snac2->data); g_free(snac2); return ret; }
/* * Subtype 0x0003 * */ static int reply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { int j = 0, m, ret = 0; aim_tlvlist_t *tlvlist; char *cur = NULL, *buf = NULL; aim_rxcallback_t userfunc; aim_snac_t *snac2; char *searchaddr = NULL; if ((snac2 = aim_remsnac(sess, snac->id))) searchaddr = (char *)snac2->data; tlvlist = aim_readtlvchain(bs); m = aim_counttlvchain(&tlvlist); /* XXX uhm. */ while ((cur = aim_gettlv_str(tlvlist, 0x0001, j+1)) && j < m) { buf = realloc(buf, (j+1) * (MAXSNLEN+1)); strncpy(&buf[j * (MAXSNLEN+1)], cur, MAXSNLEN); free(cur); j++; } aim_freetlvchain(&tlvlist); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, searchaddr, j, buf); /* XXX freesnac()? */ if (snac2) free(snac2->data); free(snac2); free(buf); return ret; }
/* * Subtype 0x0001 * * XXX can this be integrated with the rest of the error handling? */ static int error(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; aim_snac_t *snac2; /* XXX the modules interface should have already retrieved this for us */ if (!(snac2 = aim_remsnac(sess, snac->id))) { faimdprintf(sess, 2, "search error: couldn't get a snac for 0x%08lx\n", snac->id); return 0; } if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, snac2->data /* address */); /* XXX freesnac()? */ if (snac2) free(snac2->data); free(snac2); return ret; }
/* This is for cleaning up old SNACs that either don't get replies or a reply was never received for. Garabage collection. Plain and simple. maxage is the _minimum_ age in seconds to keep SNACs */ int aim_cleansnacs(int maxage) { struct aim_snac_t *cur = aim_outstanding_snacs; time_t curtime; curtime = time(&curtime); while (cur) { #if 1 if ( (cur) && (((cur->issuetime) + maxage) < curtime)) { printf("aimsnac: WARNING purged obsolete snac %ul\n", (unsigned int) cur->id); #if 1 aim_remsnac(cur->id); #endif } #endif cur = cur->next; } return 0; }
/* * Since multiple things can trigger this callback, we must lookup the * snacid to determine the original snac subtype that was called. * * XXX This isn't really how this works. But this is: Every d/9 response * has a 16bit value at the beginning. That matches to: * Short Desc = 1 * Full Desc = 2 * Instance Info = 4 * Nav Short Desc = 8 * Nav Instance Info = 16 * And then everything is really asynchronous. There is no specific * attachment of a response to a create room request, for example. Creating * the room yields no different a response than requesting the room's info. * */ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { aim_snac_t *snac2; int ret = 0; if (!(snac2 = aim_remsnac(sess, snac->id))) { imcb_error(sess->aux_data, "received response to unknown request!"); return 0; } if (snac2->family != 0x000d) { imcb_error(sess->aux_data, "recieved response that maps to corrupt request!"); return 0; } /* * We now know what the original SNAC subtype was. */ if (snac2->type == 0x0002) /* request chat rights */ ret = parseinfo_perms(sess, mod, rx, snac, bs, snac2); else if (snac2->type == 0x0003) {} /* request exchange info */ else if (snac2->type == 0x0004) {} /* request room info */ else if (snac2->type == 0x0005) {} /* request more room info */ else if (snac2->type == 0x0006) {} /* request occupant list */ else if (snac2->type == 0x0007) {} /* search for a room */ else if (snac2->type == 0x0008) /* create room */ ret = parseinfo_create(sess, mod, rx, snac, bs, snac2); else imcb_error(sess->aux_data, "unknown request subtype"); if (snac2) g_free(snac2->data); g_free(snac2); return ret; }
/* * Subtype 0x0001 */ static int error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_snac_t *snac2; guint16 reason; char *bn; snac2 = aim_remsnac(od, snac->id); if (!snac2) { purple_debug_misc("oscar", "locate error: received response from unknown request!\n"); return 0; } if ((snac2->family != SNAC_FAMILY_LOCATE) && (snac2->type != 0x0015)) { purple_debug_misc("oscar", "locate error: received response from invalid request! %d\n", snac2->family); g_free(snac2->data); g_free(snac2); return 0; } bn = snac2->data; if (!bn) { purple_debug_misc("oscar", "locate error: received response from request without a buddy name!\n"); g_free(snac2); return 0; } reason = byte_stream_get16(bs); oscar_user_info_display_error(od, reason, bn); g_free(snac2->data); g_free(snac2); return 1; }