Annotation of ChivanetAimPidgin/oscarprpl/src/c/family_icq.c, revision 1.1
1.1 ! snw 1: /*
! 2: * Purple's oscar protocol plugin
! 3: * This file is the legal property of its developers.
! 4: * Please see the AUTHORS file distributed alongside this file.
! 5: *
! 6: * This library is free software; you can redistribute it and/or
! 7: * modify it under the terms of the GNU Lesser General Public
! 8: * License as published by the Free Software Foundation; either
! 9: * version 2 of the License, or (at your option) any later version.
! 10: *
! 11: * This library is distributed in the hope that it will be useful,
! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: * Lesser General Public License for more details.
! 15: *
! 16: * You should have received a copy of the GNU Lesser General Public
! 17: * License along with this library; if not, write to the Free Software
! 18: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
! 19: */
! 20:
! 21: /*
! 22: * Family 0x0015 - Encapsulated ICQ.
! 23: *
! 24: */
! 25:
! 26: #include "encoding.h"
! 27: #include "oscar.h"
! 28:
! 29: #define AIM_ICQ_INFO_REQUEST 0x04b2
! 30: #define AIM_ICQ_ALIAS_REQUEST 0x04ba
! 31:
! 32: static
! 33: int compare_icq_infos(gconstpointer a, gconstpointer b)
! 34: {
! 35: const struct aim_icq_info* aa = a;
! 36: const guint16* bb = b;
! 37: return aa->reqid - *bb;
! 38: }
! 39:
! 40: static void aim_icq_freeinfo(struct aim_icq_info *info) {
! 41: int i;
! 42:
! 43: if (!info)
! 44: return;
! 45: g_free(info->nick);
! 46: g_free(info->first);
! 47: g_free(info->last);
! 48: g_free(info->email);
! 49: g_free(info->homecity);
! 50: g_free(info->homestate);
! 51: g_free(info->homephone);
! 52: g_free(info->homefax);
! 53: g_free(info->homeaddr);
! 54: g_free(info->mobile);
! 55: g_free(info->homezip);
! 56: g_free(info->personalwebpage);
! 57: if (info->email2)
! 58: for (i = 0; i < info->numaddresses; i++)
! 59: g_free(info->email2[i]);
! 60: g_free(info->email2);
! 61: g_free(info->workcity);
! 62: g_free(info->workstate);
! 63: g_free(info->workphone);
! 64: g_free(info->workfax);
! 65: g_free(info->workaddr);
! 66: g_free(info->workzip);
! 67: g_free(info->workcompany);
! 68: g_free(info->workdivision);
! 69: g_free(info->workposition);
! 70: g_free(info->workwebpage);
! 71: g_free(info->info);
! 72: g_free(info->status_note_title);
! 73: g_free(info->auth_request_reason);
! 74: }
! 75:
! 76: static
! 77: int error(OscarData *od, aim_modsnac_t *error_snac, ByteStream *bs)
! 78: {
! 79: aim_snac_t *original_snac = aim_remsnac(od, error_snac->id);
! 80: guint16 *request_type;
! 81: GSList *original_info_ptr;
! 82: struct aim_icq_info *original_info;
! 83: guint16 reason;
! 84: gchar *uin;
! 85:
! 86: if (!original_snac || (original_snac->family != SNAC_FAMILY_ICQ) || !original_snac->data) {
! 87: purple_debug_misc("oscar", "icq: the original snac for the error packet was not found");
! 88: g_free(original_snac);
! 89: return 0;
! 90: }
! 91:
! 92: request_type = original_snac->data;
! 93: original_info_ptr = g_slist_find_custom(od->icq_info, &original_snac->id, compare_icq_infos);
! 94:
! 95: if (!original_info_ptr) {
! 96: purple_debug_misc("oscar", "icq: the request info for the error packet was not found");
! 97: g_free(original_snac);
! 98: return 0;
! 99: }
! 100:
! 101: original_info = original_info_ptr->data;
! 102:
! 103: reason = byte_stream_get16(bs);
! 104: uin = g_strdup_printf("%u", original_info->uin);
! 105: switch (*request_type) {
! 106: case AIM_ICQ_INFO_REQUEST:
! 107: oscar_user_info_display_error(od, reason, uin);
! 108: break;
! 109: case AIM_ICQ_ALIAS_REQUEST:
! 110: /* Couldn't retrieve an alias for the buddy requesting authorization; have to make do with UIN only. */
! 111: if (original_info->for_auth_request)
! 112: oscar_auth_recvrequest(od->gc, uin, NULL, original_info->auth_request_reason);
! 113: break;
! 114: default:
! 115: purple_debug_misc("oscar", "icq: got an error packet with unknown request type %u", *request_type);
! 116: break;
! 117: }
! 118:
! 119: aim_icq_freeinfo(original_info);
! 120: od->icq_info = g_slist_remove(od->icq_info, original_info_ptr);
! 121: g_free(original_snac->data);
! 122: g_free(original_snac);
! 123: return 1;
! 124: }
! 125:
! 126: int
! 127: aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware)
! 128: {
! 129: FlapConnection *conn;
! 130: ByteStream bs;
! 131: aim_snacid_t snacid;
! 132: int bslen;
! 133:
! 134: if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
! 135: return -EINVAL;
! 136:
! 137: bslen = 2+4+2+2+2+2+2+1+1+1+1+1+1;
! 138:
! 139: byte_stream_new(&bs, 4 + bslen);
! 140:
! 141: snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
! 142:
! 143: /* For simplicity, don't bother using a tlvlist */
! 144: byte_stream_put16(&bs, 0x0001);
! 145: byte_stream_put16(&bs, bslen);
! 146:
! 147: byte_stream_putle16(&bs, bslen - 2);
! 148: byte_stream_putuid(&bs, od);
! 149: byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
! 150: byte_stream_putle16(&bs, snacid); /* eh. */
! 151: byte_stream_putle16(&bs, 0x0c3a); /* shrug. */
! 152: byte_stream_putle16(&bs, 0x030c);
! 153: byte_stream_putle16(&bs, 0x0001);
! 154: byte_stream_putle8(&bs, webaware);
! 155: byte_stream_putle8(&bs, 0xf8);
! 156: byte_stream_putle8(&bs, 0x02);
! 157: byte_stream_putle8(&bs, 0x01);
! 158: byte_stream_putle8(&bs, 0x00);
! 159: byte_stream_putle8(&bs, !auth_required);
! 160:
! 161: flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
! 162:
! 163: byte_stream_destroy(&bs);
! 164:
! 165: return 0;
! 166: }
! 167:
! 168: /**
! 169: * Change your ICQ password.
! 170: *
! 171: * @param od The oscar session
! 172: * @param passwd The new password. If this is longer than 8 characters it
! 173: * will be truncated.
! 174: * @return Return 0 if no errors, otherwise return the error number.
! 175: */
! 176: int aim_icq_changepasswd(OscarData *od, const char *passwd)
! 177: {
! 178: FlapConnection *conn;
! 179: ByteStream bs;
! 180: aim_snacid_t snacid;
! 181: int bslen, passwdlen;
! 182:
! 183: if (!passwd)
! 184: return -EINVAL;
! 185:
! 186: if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
! 187: return -EINVAL;
! 188:
! 189: passwdlen = strlen(passwd);
! 190: if (passwdlen > MAXICQPASSLEN)
! 191: passwdlen = MAXICQPASSLEN;
! 192: bslen = 2+4+2+2+2+2+passwdlen+1;
! 193:
! 194: byte_stream_new(&bs, 4 + bslen);
! 195:
! 196: snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
! 197:
! 198: /* For simplicity, don't bother using a tlvlist */
! 199: byte_stream_put16(&bs, 0x0001);
! 200: byte_stream_put16(&bs, bslen);
! 201:
! 202: byte_stream_putle16(&bs, bslen - 2);
! 203: byte_stream_putuid(&bs, od);
! 204: byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
! 205: byte_stream_putle16(&bs, snacid); /* eh. */
! 206: byte_stream_putle16(&bs, 0x042e); /* shrug. */
! 207: byte_stream_putle16(&bs, passwdlen+1);
! 208: byte_stream_putraw(&bs, (const guint8 *)passwd, passwdlen);
! 209: byte_stream_putle8(&bs, '\0');
! 210:
! 211: flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
! 212:
! 213: byte_stream_destroy(&bs);
! 214:
! 215: return 0;
! 216: }
! 217:
! 218: int aim_icq_getallinfo(OscarData *od, const char *uin)
! 219: {
! 220: FlapConnection *conn;
! 221: ByteStream bs;
! 222: aim_snacid_t snacid;
! 223: int bslen;
! 224: struct aim_icq_info *info;
! 225: guint16 request_type = AIM_ICQ_INFO_REQUEST;
! 226:
! 227: if (!uin || uin[0] < '0' || uin[0] > '9')
! 228: return -EINVAL;
! 229:
! 230: if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
! 231: return -EINVAL;
! 232:
! 233: bslen = 2 + 4 + 2 + 2 + 2 + 4;
! 234:
! 235: byte_stream_new(&bs, 4 + bslen);
! 236:
! 237: snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, &request_type, sizeof(request_type));
! 238:
! 239: /* For simplicity, don't bother using a tlvlist */
! 240: byte_stream_put16(&bs, 0x0001);
! 241: byte_stream_put16(&bs, bslen);
! 242:
! 243: byte_stream_putle16(&bs, bslen - 2);
! 244: byte_stream_putuid(&bs, od);
! 245: byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
! 246: byte_stream_putle16(&bs, snacid); /* eh. */
! 247: byte_stream_putle16(&bs, request_type); /* shrug. */
! 248: byte_stream_putle32(&bs, atoi(uin));
! 249:
! 250: flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs, FALSE);
! 251:
! 252: byte_stream_destroy(&bs);
! 253:
! 254: /* Keep track of this request and the ICQ number and request ID */
! 255: info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
! 256: info->reqid = snacid;
! 257: info->uin = atoi(uin);
! 258: od->icq_info = g_slist_prepend(od->icq_info, info);
! 259:
! 260: return 0;
! 261: }
! 262:
! 263: int aim_icq_getalias(OscarData *od, const char *uin, gboolean for_auth_request, char *auth_request_reason)
! 264: {
! 265: FlapConnection *conn;
! 266: ByteStream bs;
! 267: aim_snacid_t snacid;
! 268: int bslen;
! 269: struct aim_icq_info *info;
! 270: guint16 request_type = AIM_ICQ_ALIAS_REQUEST;
! 271:
! 272: if (!uin || uin[0] < '0' || uin[0] > '9')
! 273: return -EINVAL;
! 274:
! 275: if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
! 276: return -EINVAL;
! 277:
! 278: purple_debug_info("oscar", "Requesting ICQ alias for %s\n", uin);
! 279:
! 280: bslen = 2 + 4 + 2 + 2 + 2 + 4;
! 281:
! 282: byte_stream_new(&bs, 4 + bslen);
! 283:
! 284: snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, &request_type, sizeof(request_type));
! 285:
! 286: /* For simplicity, don't bother using a tlvlist */
! 287: byte_stream_put16(&bs, 0x0001);
! 288: byte_stream_put16(&bs, bslen);
! 289:
! 290: byte_stream_putle16(&bs, bslen - 2);
! 291: byte_stream_putuid(&bs, od);
! 292: byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
! 293: byte_stream_putle16(&bs, snacid); /* eh. */
! 294: byte_stream_putle16(&bs, request_type); /* shrug. */
! 295: byte_stream_putle32(&bs, atoi(uin));
! 296:
! 297: flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs, FALSE);
! 298:
! 299: byte_stream_destroy(&bs);
! 300:
! 301: /* Keep track of this request and the ICQ number and request ID */
! 302: info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
! 303: info->reqid = snacid;
! 304: info->uin = atoi(uin);
! 305: info->for_auth_request = for_auth_request;
! 306: info->auth_request_reason = g_strdup(auth_request_reason);
! 307: od->icq_info = g_slist_prepend(od->icq_info, info);
! 308:
! 309: return 0;
! 310: }
! 311:
! 312: /*
! 313: * Send an SMS message. This is the non-US way. The US-way is to IM
! 314: * their cell phone number (+19195551234).
! 315: *
! 316: * We basically construct and send an XML message. The format is:
! 317: * <icq_sms_message>
! 318: * <destination>full_phone_without_leading_+</destination>
! 319: * <text>message</text>
! 320: * <codepage>1252</codepage>
! 321: * <senders_UIN>self_uin</senders_UIN>
! 322: * <senders_name>self_name</senders_name>
! 323: * <delivery_receipt>Yes|No</delivery_receipt>
! 324: * <time>Wkd, DD Mmm YYYY HH:MM:SS TMZ</time>
! 325: * </icq_sms_message>
! 326: *
! 327: * Yeah hi Peter, whaaaat's happening. If there's any way to use
! 328: * a codepage other than 1252 that would be great. Thaaaanks.
! 329: */
! 330: int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias)
! 331: {
! 332: FlapConnection *conn;
! 333: PurpleAccount *account;
! 334: ByteStream bs;
! 335: aim_snacid_t snacid;
! 336: int bslen, xmllen;
! 337: char *xml;
! 338: const char *timestr, *username;
! 339: time_t t;
! 340: struct tm *tm;
! 341: gchar *stripped;
! 342:
! 343: if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
! 344: return -EINVAL;
! 345:
! 346: if (!name || !msg || !alias)
! 347: return -EINVAL;
! 348:
! 349: account = purple_connection_get_account(od->gc);
! 350: username = purple_account_get_username(account);
! 351:
! 352: time(&t);
! 353: tm = gmtime(&t);
! 354: timestr = purple_utf8_strftime("%a, %d %b %Y %T %Z", tm);
! 355:
! 356: stripped = purple_markup_strip_html(msg);
! 357:
! 358: /* The length of xml included the null terminating character */
! 359: xmllen = 209 + strlen(name) + strlen(stripped) + strlen(username) + strlen(alias) + strlen(timestr) + 1;
! 360:
! 361: xml = g_new(char, xmllen);
! 362: snprintf(xml, xmllen, "<icq_sms_message>"
! 363: "<destination>%s</destination>"
! 364: "<text>%s</text>"
! 365: "<codepage>1252</codepage>"
! 366: "<senders_UIN>%s</senders_UIN>"
! 367: "<senders_name>%s</senders_name>"
! 368: "<delivery_receipt>Yes</delivery_receipt>"
! 369: "<time>%s</time>"
! 370: "</icq_sms_message>",
! 371: name, stripped, username, alias, timestr);
! 372:
! 373: bslen = 36 + xmllen;
! 374:
! 375: byte_stream_new(&bs, 4 + bslen);
! 376:
! 377: snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
! 378:
! 379: /* For simplicity, don't bother using a tlvlist */
! 380: byte_stream_put16(&bs, 0x0001);
! 381: byte_stream_put16(&bs, bslen);
! 382:
! 383: byte_stream_putle16(&bs, bslen - 2);
! 384: byte_stream_putuid(&bs, od);
! 385: byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
! 386: byte_stream_putle16(&bs, snacid); /* eh. */
! 387:
! 388: /* From libicq200-0.3.2/src/SNAC-SRV.cpp */
! 389: byte_stream_putle16(&bs, 0x1482);
! 390: byte_stream_put16(&bs, 0x0001);
! 391: byte_stream_put16(&bs, 0x0016);
! 392: byte_stream_put32(&bs, 0x00000000);
! 393: byte_stream_put32(&bs, 0x00000000);
! 394: byte_stream_put32(&bs, 0x00000000);
! 395: byte_stream_put32(&bs, 0x00000000);
! 396:
! 397: byte_stream_put16(&bs, 0x0000);
! 398: byte_stream_put16(&bs, xmllen);
! 399: byte_stream_putstr(&bs, xml);
! 400: byte_stream_put8(&bs, 0x00);
! 401:
! 402: flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
! 403:
! 404: byte_stream_destroy(&bs);
! 405:
! 406: g_free(xml);
! 407: g_free(stripped);
! 408:
! 409: return 0;
! 410: }
! 411:
! 412: static void
! 413: gotalias(OscarData *od, struct aim_icq_info *info)
! 414: {
! 415: PurpleConnection *gc = od->gc;
! 416: PurpleAccount *account = purple_connection_get_account(gc);
! 417: PurpleBuddy *b;
! 418: gchar *utf8 = oscar_utf8_try_convert(account, od, info->nick);
! 419:
! 420: if (info->for_auth_request) {
! 421: oscar_auth_recvrequest(gc, g_strdup_printf("%u", info->uin), utf8, info->auth_request_reason);
! 422: } else {
! 423: if (utf8 && *utf8) {
! 424: gchar who[16];
! 425: g_snprintf(who, sizeof(who), "%u", info->uin);
! 426: serv_got_alias(gc, who, utf8);
! 427: if ((b = purple_find_buddy(account, who))) {
! 428: purple_blist_node_set_string((PurpleBlistNode*)b, "servernick", utf8);
! 429: }
! 430: }
! 431: g_free(utf8);
! 432: }
! 433: }
! 434:
! 435: /**
! 436: * Subtype 0x0003 - Response to SNAC_FAMILY_ICQ/0x002, contains an ICQesque packet.
! 437: */
! 438: static int
! 439: icqresponse(OscarData *od, aim_modsnac_t *snac, ByteStream *bs)
! 440: {
! 441: GSList *tlvlist;
! 442: aim_tlv_t *datatlv;
! 443: ByteStream qbs;
! 444: guint32 ouruin;
! 445: guint16 cmdlen, cmd, reqid;
! 446:
! 447: if (!(tlvlist = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tlvlist, 0x0001, 1))) {
! 448: aim_tlvlist_free(tlvlist);
! 449: purple_debug_misc("oscar", "corrupt ICQ response\n");
! 450: return 0;
! 451: }
! 452:
! 453: byte_stream_init(&qbs, datatlv->value, datatlv->length);
! 454:
! 455: cmdlen = byte_stream_getle16(&qbs);
! 456: ouruin = byte_stream_getle32(&qbs);
! 457: cmd = byte_stream_getle16(&qbs);
! 458: reqid = byte_stream_getle16(&qbs);
! 459:
! 460: purple_debug_misc("oscar", "icq response: %d bytes, %u, 0x%04x, 0x%04x\n", cmdlen, ouruin, cmd, reqid);
! 461:
! 462: if (cmd == 0x07da) { /* information */
! 463: guint16 subtype;
! 464: GSList *info_ptr;
! 465: struct aim_icq_info *info;
! 466:
! 467: subtype = byte_stream_getle16(&qbs);
! 468: byte_stream_advance(&qbs, 1); /* 0x0a */
! 469:
! 470: /* find other data from the same request */
! 471: info_ptr = g_slist_find_custom(od->icq_info, &reqid, compare_icq_infos);
! 472: if (!info_ptr) {
! 473: struct aim_icq_info *new_info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
! 474: new_info->reqid = reqid;
! 475: info_ptr = od->icq_info = g_slist_prepend(od->icq_info, new_info);
! 476: }
! 477:
! 478: info = info_ptr->data;
! 479: switch (subtype) {
! 480: case 0x00a0: { /* hide ip status */
! 481: /* nothing */
! 482: } break;
! 483:
! 484: case 0x00aa: { /* password change status */
! 485: /* nothing */
! 486: } break;
! 487:
! 488: case 0x00c8: { /* general and "home" information */
! 489: info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 490: info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 491: info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 492: info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 493: info->homecity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 494: info->homestate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 495: info->homephone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 496: info->homefax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 497: info->homeaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 498: info->mobile = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 499: info->homezip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 500: info->homecountry = byte_stream_getle16(&qbs);
! 501: /* 0x0a 00 02 00 */
! 502: /* 1 byte timezone? */
! 503: /* 1 byte hide email flag? */
! 504: } break;
! 505:
! 506: case 0x00dc: { /* personal information */
! 507: info->age = byte_stream_getle8(&qbs);
! 508: info->unknown = byte_stream_getle8(&qbs);
! 509: info->gender = byte_stream_getle8(&qbs); /* Not specified=0x00, Female=0x01, Male=0x02 */
! 510: info->personalwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 511: info->birthyear = byte_stream_getle16(&qbs);
! 512: info->birthmonth = byte_stream_getle8(&qbs);
! 513: info->birthday = byte_stream_getle8(&qbs);
! 514: info->language1 = byte_stream_getle8(&qbs);
! 515: info->language2 = byte_stream_getle8(&qbs);
! 516: info->language3 = byte_stream_getle8(&qbs);
! 517: /* 0x00 00 01 00 00 01 00 00 00 00 00 */
! 518: } break;
! 519:
! 520: case 0x00d2: { /* work information */
! 521: info->workcity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 522: info->workstate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 523: info->workphone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 524: info->workfax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 525: info->workaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 526: info->workzip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 527: info->workcountry = byte_stream_getle16(&qbs);
! 528: info->workcompany = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 529: info->workdivision = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 530: info->workposition = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 531: byte_stream_advance(&qbs, 2); /* 0x01 00 */
! 532: info->workwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 533: } break;
! 534:
! 535: case 0x00e6: { /* additional personal information */
! 536: info->info = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)-1);
! 537: } break;
! 538:
! 539: case 0x00eb: { /* email address(es) */
! 540: int i;
! 541: info->numaddresses = byte_stream_getle16(&qbs);
! 542: info->email2 = (char **)g_new0(char *, info->numaddresses);
! 543: for (i = 0; i < info->numaddresses; i++) {
! 544: info->email2[i] = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 545: if (i+1 != info->numaddresses)
! 546: byte_stream_advance(&qbs, 1); /* 0x00 */
! 547: }
! 548: } break;
! 549:
! 550: case 0x00f0: { /* personal interests */
! 551: } break;
! 552:
! 553: case 0x00fa: { /* past background and current organizations */
! 554: } break;
! 555:
! 556: case 0x0104: { /* alias info */
! 557: info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 558: info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 559: info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 560: byte_stream_advance(&qbs, byte_stream_getle16(&qbs)); /* email address? */
! 561: /* Then 0x00 02 00 */
! 562: } break;
! 563:
! 564: case 0x010e: { /* unknown */
! 565: /* 0x00 00 */
! 566: } break;
! 567:
! 568: case 0x019a: { /* simple info */
! 569: byte_stream_advance(&qbs, 2);
! 570: info->uin = byte_stream_getle32(&qbs);
! 571: info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 572: info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 573: info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 574: info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
! 575: /* Then 0x00 02 00 00 00 00 00 */
! 576: } break;
! 577:
! 578: /* status note title and send request for status note text */
! 579: case 0x0fb4: {
! 580: GSList *tlvlist;
! 581: aim_tlv_t *tlv;
! 582: FlapConnection *conn;
! 583: char *uin = NULL;
! 584: char *status_note_title = NULL;
! 585:
! 586: conn = flap_connection_findbygroup(od, 0x0004);
! 587: if (conn == NULL)
! 588: {
! 589: purple_debug_misc("oscar", "icq/0x0fb4: flap connection was not found.\n");
! 590: break;
! 591: }
! 592:
! 593: byte_stream_advance(&qbs, 0x02); /* length */
! 594: byte_stream_advance(&qbs, 0x2f); /* unknown stuff */
! 595:
! 596: tlvlist = aim_tlvlist_read(&qbs);
! 597:
! 598: tlv = aim_tlv_gettlv(tlvlist, 0x0032, 1);
! 599: if (tlv != NULL)
! 600: /* Get user number */
! 601: uin = aim_tlv_getvalue_as_string(tlv);
! 602:
! 603: tlv = aim_tlv_gettlv(tlvlist, 0x0226, 1);
! 604: if (tlv != NULL)
! 605: /* Get status note title */
! 606: status_note_title = aim_tlv_getvalue_as_string(tlv);
! 607:
! 608: aim_tlvlist_free(tlvlist);
! 609:
! 610: if (uin == NULL || status_note_title == NULL)
! 611: {
! 612: purple_debug_misc("oscar", "icq/0x0fb4: uin or "
! 613: "status_note_title was not found\n");
! 614: g_free(uin);
! 615: g_free(status_note_title);
! 616: break;
! 617: }
! 618:
! 619: if (status_note_title[0] == '\0')
! 620: {
! 621: PurpleAccount *account;
! 622: PurpleBuddy *buddy;
! 623: PurplePresence *presence;
! 624: PurpleStatus *status;
! 625:
! 626: account = purple_connection_get_account(od->gc);
! 627: buddy = purple_find_buddy(account, uin);
! 628: presence = purple_buddy_get_presence(buddy);
! 629: status = purple_presence_get_active_status(presence);
! 630:
! 631: purple_prpl_got_user_status(account, uin,
! 632: purple_status_get_id(status),
! 633: "message", NULL, NULL);
! 634:
! 635: g_free(status_note_title);
! 636: }
! 637: else
! 638: {
! 639: struct aim_icq_info *info;
! 640: ByteStream bs;
! 641: guint32 bslen;
! 642: aim_snacid_t snacid;
! 643: guchar cookie[8];
! 644:
! 645: info = g_new0(struct aim_icq_info, 1);
! 646:
! 647: bslen = 13 + strlen(uin) + 30 + 6 + 4 + 55 + 85 + 4;
! 648: byte_stream_new(&bs, 4 + bslen);
! 649:
! 650: snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
! 651:
! 652: aim_icbm_makecookie(cookie);
! 653:
! 654: byte_stream_putraw(&bs, cookie, 8); /* ICBM cookie */
! 655: byte_stream_put16(&bs, 0x0002); /* message channel */
! 656: byte_stream_put8(&bs, strlen(uin)); /* uin */
! 657: byte_stream_putstr(&bs, uin);
! 658:
! 659: byte_stream_put16(&bs, 0x0005); /* rendez vous data */
! 660: byte_stream_put16(&bs, 0x00b2);
! 661: byte_stream_put16(&bs, 0x0000); /* request */
! 662: byte_stream_putraw(&bs, cookie, 8); /* ICBM cookie */
! 663: byte_stream_put32(&bs, 0x09461349); /* ICQ server relaying */
! 664: byte_stream_put16(&bs, 0x4c7f);
! 665: byte_stream_put16(&bs, 0x11d1);
! 666: byte_stream_put32(&bs, 0x82224445);
! 667: byte_stream_put32(&bs, 0x53540000);
! 668:
! 669: byte_stream_put16(&bs, 0x000a); /* unknown TLV */
! 670: byte_stream_put16(&bs, 0x0002);
! 671: byte_stream_put16(&bs, 0x0001);
! 672:
! 673: byte_stream_put16(&bs, 0x000f); /* unknown TLV */
! 674: byte_stream_put16(&bs, 0x0000);
! 675:
! 676: byte_stream_put16(&bs, 0x2711); /* extended data */
! 677: byte_stream_put16(&bs, 0x008a);
! 678: byte_stream_putle16(&bs, 0x001b); /* length */
! 679: byte_stream_putle16(&bs, 0x0009); /* version */
! 680: byte_stream_putle32(&bs, 0x00000000); /* plugin: none */
! 681: byte_stream_putle32(&bs, 0x00000000);
! 682: byte_stream_putle32(&bs, 0x00000000);
! 683: byte_stream_putle32(&bs, 0x00000000);
! 684: byte_stream_putle16(&bs, 0x0000); /* unknown */
! 685: byte_stream_putle32(&bs, 0x00000000); /* client capabilities flags */
! 686: byte_stream_put8(&bs, 0x00); /* unknown */
! 687: byte_stream_putle16(&bs, 0x0064); /* downcounter? */
! 688: byte_stream_putle16(&bs, 0x000e); /* length */
! 689: byte_stream_putle16(&bs, 0x0064); /* downcounter? */
! 690: byte_stream_putle32(&bs, 0x00000000); /* unknown */
! 691: byte_stream_putle32(&bs, 0x00000000);
! 692: byte_stream_putle32(&bs, 0x00000000);
! 693: byte_stream_put8(&bs, 0x1a); /* message type: plugin message descibed by text string */
! 694: byte_stream_put8(&bs, 0x00); /* message flags */
! 695: byte_stream_putle16(&bs, 0x0000); /* status code */
! 696: byte_stream_putle16(&bs, 0x0001); /* priority code */
! 697: byte_stream_putle16(&bs, 0x0000); /* text length */
! 698:
! 699: byte_stream_put8(&bs, 0x3a); /* message dump */
! 700: byte_stream_put32(&bs, 0x00811a18);
! 701: byte_stream_put32(&bs, 0xbc0e6c18);
! 702: byte_stream_put32(&bs, 0x47a5916f);
! 703: byte_stream_put32(&bs, 0x18dcc76f);
! 704: byte_stream_put32(&bs, 0x1a010013);
! 705: byte_stream_put32(&bs, 0x00000041);
! 706: byte_stream_put32(&bs, 0x77617920);
! 707: byte_stream_put32(&bs, 0x53746174);
! 708: byte_stream_put32(&bs, 0x7573204d);
! 709: byte_stream_put32(&bs, 0x65737361);
! 710: byte_stream_put32(&bs, 0x67650100);
! 711: byte_stream_put32(&bs, 0x00000000);
! 712: byte_stream_put32(&bs, 0x00000000);
! 713: byte_stream_put32(&bs, 0x00000000);
! 714: byte_stream_put32(&bs, 0x00000015);
! 715: byte_stream_put32(&bs, 0x00000000);
! 716: byte_stream_put32(&bs, 0x0000000d);
! 717: byte_stream_put32(&bs, 0x00000074);
! 718: byte_stream_put32(&bs, 0x6578742f);
! 719: byte_stream_put32(&bs, 0x782d616f);
! 720: byte_stream_put32(&bs, 0x6c727466);
! 721:
! 722: byte_stream_put16(&bs, 0x0003); /* server ACK requested */
! 723: byte_stream_put16(&bs, 0x0000);
! 724:
! 725: info->uin = atoi(uin);
! 726: info->status_note_title = status_note_title;
! 727:
! 728: memcpy(&info->icbm_cookie, cookie, 8);
! 729:
! 730: od->icq_info = g_slist_prepend(od->icq_info, info);
! 731:
! 732: flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, snacid, &bs, FALSE);
! 733:
! 734: byte_stream_destroy(&bs);
! 735: }
! 736:
! 737: g_free(uin);
! 738:
! 739: } break;
! 740:
! 741: } /* End switch statement */
! 742:
! 743: if (!(snac->flags & 0x0001)) {
! 744: if (subtype != 0x0104)
! 745: oscar_user_info_display_icq(od, info);
! 746:
! 747: if (info->uin && info->nick)
! 748: gotalias(od, info);
! 749:
! 750: aim_icq_freeinfo(info);
! 751: od->icq_info = g_slist_remove(od->icq_info, info);
! 752: }
! 753: }
! 754:
! 755: aim_tlvlist_free(tlvlist);
! 756:
! 757: return 1;
! 758: }
! 759:
! 760: static int
! 761: snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
! 762: {
! 763: if (snac->subtype == 0x0001)
! 764: return error(od, snac, bs);
! 765: else if (snac->subtype == 0x0003)
! 766: return icqresponse(od, snac, bs);
! 767:
! 768: return 0;
! 769: }
! 770:
! 771: static void
! 772: icq_shutdown(OscarData *od, aim_module_t *mod)
! 773: {
! 774: GSList *cur;
! 775: for (cur = od->icq_info; cur; cur = cur->next)
! 776: aim_icq_freeinfo(cur->data);
! 777: g_slist_free(od->icq_info);
! 778: }
! 779:
! 780: int
! 781: icq_modfirst(OscarData *od, aim_module_t *mod)
! 782: {
! 783: mod->family = SNAC_FAMILY_ICQ;
! 784: mod->version = 0x0001;
! 785: mod->toolid = 0x0110;
! 786: mod->toolversion = 0x047c;
! 787: mod->flags = 0;
! 788: strncpy(mod->name, "icq", sizeof(mod->name));
! 789: mod->snachandler = snachandler;
! 790: mod->shutdown = icq_shutdown;
! 791:
! 792: return 0;
! 793: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>