comparison libpurple/protocols/oscar/family_icbm.c @ 27782:9cd7892b2c8b

propagate from branch 'im.pidgin.pidgin' (head dfdceb0b08475c3e5750b3e6430d154e9a747d67) to branch 'im.pidgin.pidgin.yaz' (head 7982395e45644f3f5d8b4a39018946e19ea9572f)
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Tue, 04 Mar 2008 18:12:32 +0000
parents 0f3a131d23da 75d53b0fae6c
children 8dfe3a985fc1
comparison
equal deleted inserted replaced
27781:11713f052640 27782:9cd7892b2c8b
2369 flap_connection_send(conn, frame); 2369 flap_connection_send(conn, frame);
2370 2370
2371 return 0; 2371 return 0;
2372 } 2372 }
2373 2373
2374 static void parse_status_note_text(OscarData *od, guchar *cookie, char *sn, ByteStream *bs)
2375 {
2376 struct aim_icq_info *info;
2377 struct aim_icq_info *prev_info;
2378 char *response;
2379 char *encoding;
2380 char *stripped_encoding;
2381 char *status_note_title;
2382 char *status_note_text;
2383 char *stripped_status_note_text;
2384 char *status_note;
2385 guint32 length;
2386 guint16 version;
2387 guint32 capability;
2388 guint8 message_type;
2389 guint16 status_code;
2390 guint16 text_length;
2391 guint32 request_length;
2392 guint32 response_length;
2393 guint32 encoding_length;
2394 PurpleAccount *account;
2395 PurpleBuddy *buddy;
2396 PurplePresence *presence;
2397 PurpleStatus *status;
2398
2399 for (prev_info = NULL, info = od->icq_info; info != NULL; prev_info = info, info = info->next)
2400 {
2401 if (memcmp(&info->icbm_cookie, cookie, 8) == 0)
2402 {
2403 if (prev_info == NULL)
2404 od->icq_info = info->next;
2405 else
2406 prev_info->next = info->next;
2407
2408 break;
2409 }
2410 }
2411
2412 if (info == NULL)
2413 return;
2414
2415 status_note_title = info->status_note_title;
2416 g_free(info);
2417
2418 length = byte_stream_getle16(bs);
2419 if (length != 27) {
2420 purple_debug_misc("oscar", "clientautoresp: incorrect header "
2421 "size; expected 27, received %u.\n", length);
2422 g_free(status_note_title);
2423 return;
2424 }
2425
2426 version = byte_stream_getle16(bs);
2427 if (version != 9) {
2428 purple_debug_misc("oscar", "clientautoresp: incorrect version; "
2429 "expected 9, received %u.\n", version);
2430 g_free(status_note_title);
2431 return;
2432 }
2433
2434 capability = aim_locate_getcaps(od, bs, 0x10);
2435 if (capability != OSCAR_CAPABILITY_EMPTY) {
2436 purple_debug_misc("oscar", "clientautoresp: plugin ID is not null.\n");
2437 g_free(status_note_title);
2438 return;
2439 }
2440
2441 byte_stream_advance(bs, 2); /* unknown */
2442 byte_stream_advance(bs, 4); /* client capabilities flags */
2443 byte_stream_advance(bs, 1); /* unknown */
2444 byte_stream_advance(bs, 2); /* downcouner? */
2445
2446 length = byte_stream_getle16(bs);
2447 if (length != 14) {
2448 purple_debug_misc("oscar", "clientautoresp: incorrect header "
2449 "size; expected 14, received %u.\n", length);
2450 g_free(status_note_title);
2451 return;
2452 }
2453
2454 byte_stream_advance(bs, 2); /* downcounter? */
2455 byte_stream_advance(bs, 12); /* unknown */
2456
2457 message_type = byte_stream_get8(bs);
2458 if (message_type != 0x1a) {
2459 purple_debug_misc("oscar", "clientautoresp: incorrect message "
2460 "type; expected 0x1a, received 0x%x.\n", message_type);
2461 g_free(status_note_title);
2462 return;
2463 }
2464
2465 byte_stream_advance(bs, 1); /* message flags */
2466
2467 status_code = byte_stream_getle16(bs);
2468 if (status_code != 0) {
2469 purple_debug_misc("oscar", "clientautoresp: incorrect status "
2470 "code; expected 0, received %u.\n", status_code);
2471 g_free(status_note_title);
2472 return;
2473 }
2474
2475 byte_stream_advance(bs, 2); /* priority code */
2476
2477 text_length = byte_stream_getle16(bs);
2478 byte_stream_advance(bs, text_length); /* text */
2479
2480 length = byte_stream_getle16(bs);
2481 byte_stream_advance(bs, 18); /* unknown */
2482
2483 request_length = byte_stream_getle32(bs);
2484 if (length != 18 + 4 + request_length + 17) {
2485 purple_debug_misc("oscar", "clientautoresp: incorrect block; "
2486 "expected length is %u, got %u.\n",
2487 18 + 4 + request_length + 17, length);
2488 g_free(status_note_title);
2489 return;
2490 }
2491
2492 byte_stream_advance(bs, request_length); /* x request */
2493 byte_stream_advance(bs, 17); /* unknown */
2494
2495 length = byte_stream_getle32(bs);
2496 response_length = byte_stream_getle32(bs);
2497 response = byte_stream_getstr(bs, response_length);
2498 encoding_length = byte_stream_getle32(bs);
2499 if (length != 4 + response_length + 4 + encoding_length) {
2500 purple_debug_misc("oscar", "clientautoresp: incorrect block; "
2501 "expected length is %u, got %u.\n",
2502 4 + response_length + 4 + encoding_length, length);
2503 g_free(status_note_title);
2504 g_free(response);
2505 return;
2506 }
2507
2508 encoding = byte_stream_getstr(bs, encoding_length);
2509
2510 account = purple_connection_get_account(od->gc);
2511
2512 stripped_encoding = oscar_encoding_extract(encoding);
2513 status_note_text = oscar_encoding_to_utf8(account, stripped_encoding, response, response_length);
2514 stripped_status_note_text = purple_markup_strip_html(status_note_text);
2515
2516 if (stripped_status_note_text != NULL && stripped_status_note_text[0] != 0)
2517 status_note = g_strdup_printf("%s: %s", status_note_title, stripped_status_note_text);
2518 else
2519 status_note = g_strdup(status_note_title);
2520
2521 g_free(status_note_title);
2522 g_free(response);
2523 g_free(encoding);
2524 g_free(stripped_encoding);
2525 g_free(status_note_text);
2526 g_free(stripped_status_note_text);
2527
2528 buddy = purple_find_buddy(account, sn);
2529 if (buddy == NULL)
2530 {
2531 purple_debug_misc("oscar", "clientautoresp: buddy %s was not found.\n", sn);
2532 g_free(status_note);
2533 return;
2534 }
2535
2536 purple_debug_misc("oscar", "clientautoresp: setting status "
2537 "message to \"%s\".\n", status_note);
2538
2539 presence = purple_buddy_get_presence(buddy);
2540 status = purple_presence_get_active_status(presence);
2541
2542 purple_prpl_got_user_status(account, sn,
2543 purple_status_get_id(status),
2544 "message", status_note, NULL);
2545
2546 g_free(status_note);
2547 }
2548
2374 /* 2549 /*
2375 * Subtype 0x000b - Receive the response from an ICQ status message 2550 * Subtype 0x000b - Receive the response from an ICQ status message
2376 * request (in which case this contains the ICQ status message) or 2551 * request (in which case this contains the ICQ status message) or
2377 * a file transfer or direct IM request was declined. 2552 * a file transfer or direct IM request was declined.
2378 */ 2553 */
2391 sn = byte_stream_getstr(bs, snlen); 2566 sn = byte_stream_getstr(bs, snlen);
2392 reason = byte_stream_get16(bs); 2567 reason = byte_stream_get16(bs);
2393 2568
2394 if (channel == 0x0002) 2569 if (channel == 0x0002)
2395 { 2570 {
2396 /* parse status note text */ 2571 if (reason == 0x0003) /* channel-specific */
2397 2572 /* parse status note text */
2398 struct aim_icq_info *info = NULL; 2573 parse_status_note_text(od, cookie, sn, bs);
2399 struct aim_icq_info *prev_info = NULL;
2400 char *response = NULL;
2401 char *encoding = NULL;
2402 char *stripped_encoding = NULL;
2403 char *status_note_text = NULL;
2404 char *stripped_status_note_text = NULL;
2405 char *status_note = NULL;
2406
2407 /*
2408 * TODO: Using a while statement here is kind of an ugly hack
2409 * to be able to use 'break'. We might as well be using
2410 * 'goto'. Should probably get rid of this.
2411 */
2412 while (reason == 0x0003) /* channel-specific */
2413 {
2414 guint32 length;
2415 guint16 version;
2416 guint32 capability;
2417 guint8 message_type;
2418 guint16 status_code;
2419 guint16 text_length;
2420 guint32 request_length;
2421 guint32 response_length;
2422 guint32 encoding_length;
2423 PurpleAccount *account;
2424 PurpleBuddy *buddy;
2425 PurplePresence *presence;
2426 PurpleStatus *status;
2427
2428 for (info = od->icq_info; info != NULL; info = info->next)
2429 {
2430 if (memcmp(&info->icbm_cookie, cookie, 8) == 0)
2431 {
2432 if (prev_info == NULL)
2433 od->icq_info = info->next;
2434 else
2435 prev_info->next = info->next;
2436
2437 break;
2438 }
2439
2440 prev_info = info;
2441 }
2442
2443 if (info == NULL)
2444 break;
2445
2446 if ((length = byte_stream_getle16(bs)) != 27)
2447 {
2448 purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 27, received %u.\n", length);
2449 break;
2450 }
2451 if ((version = byte_stream_getle16(bs)) != 9)
2452 {
2453 purple_debug_misc("oscar", "clientautoresp: incorrect version; expected 9, received %u.\n", version);
2454 break;
2455 }
2456 capability = aim_locate_getcaps(od, bs, 0x10);
2457 if (capability != OSCAR_CAPABILITY_EMPTY)
2458 {
2459 purple_debug_misc("oscar", "clientautoresp: plugin ID is not null.\n");
2460 break;
2461 }
2462 byte_stream_advance(bs, 2); /* unknown */
2463 byte_stream_advance(bs, 4); /* client capabilities flags */
2464 byte_stream_advance(bs, 1); /* unknown */
2465 byte_stream_advance(bs, 2); /* downcouner? */
2466
2467 if ((length = byte_stream_getle16(bs)) != 14)
2468 {
2469 purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 14, received %u.\n", length);
2470 break;
2471 }
2472 byte_stream_advance(bs, 2); /* downcounter? */
2473 byte_stream_advance(bs, 12); /* unknown */
2474
2475 if ((message_type = byte_stream_get8(bs)) != 0x1a)
2476 {
2477 purple_debug_misc("oscar", "clientautoresp: incorrect message type; expected 0x1a, received 0x%x.\n", message_type);
2478 break;
2479 }
2480 byte_stream_advance(bs, 1); /* message flags */
2481 if ((status_code = byte_stream_getle16(bs)) != 0)
2482 {
2483 purple_debug_misc("oscar", "clientautoresp: incorrect status code; expected 0, received %u.\n", status_code);
2484 break;
2485 }
2486 byte_stream_advance(bs, 2); /* priority code */
2487
2488 text_length = byte_stream_getle16(bs);
2489 byte_stream_advance(bs, text_length); /* text */
2490
2491 length = byte_stream_getle16(bs);
2492 byte_stream_advance(bs, 18); /* unknown */
2493 if (length != 18 + 4 + (request_length = byte_stream_getle32(bs)) + 17)
2494 {
2495 purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 18 + 4 + request_length + 17, length);
2496 break;
2497 }
2498 byte_stream_advance(bs, request_length); /* x request */
2499 byte_stream_advance(bs, 17); /* unknown */
2500
2501 length = byte_stream_getle32(bs);
2502 response_length = byte_stream_getle32(bs);
2503 response = byte_stream_getstr(bs, response_length);
2504 if (length != 4 + response_length + 4 + (encoding_length = byte_stream_getle32(bs)))
2505 {
2506 purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 4 + response_length + 4 + encoding_length, length);
2507 break;
2508 }
2509 encoding = byte_stream_getstr(bs, encoding_length);
2510
2511 account = purple_connection_get_account(od->gc);
2512 stripped_encoding = oscar_encoding_extract(encoding);
2513 status_note_text = oscar_encoding_to_utf8(account, stripped_encoding, response, response_length);
2514 stripped_status_note_text = purple_markup_strip_html(status_note_text);
2515
2516 if (stripped_status_note_text != NULL && stripped_status_note_text[0] != 0)
2517 status_note = g_strdup_printf("%s: %s", info->status_note_title, stripped_status_note_text);
2518 else
2519 status_note = g_strdup(info->status_note_title);
2520
2521 buddy = purple_find_buddy(account, sn);
2522 if (buddy == NULL)
2523 {
2524 purple_debug_misc("oscar", "clientautoresp: buddy %s was not found.\n", sn);
2525 break;
2526 }
2527
2528 purple_debug_misc("oscar", "clientautoresp: setting status message to \"%s\".\n", status_note);
2529
2530 presence = purple_buddy_get_presence(buddy);
2531 status = purple_presence_get_active_status(presence);
2532
2533 purple_prpl_got_user_status(account, sn,
2534 purple_status_get_id(status),
2535 "message", status_note, NULL);
2536
2537 break;
2538 }
2539
2540 g_free(status_note);
2541 g_free(stripped_status_note_text);
2542 g_free(status_note_text);
2543 g_free(stripped_encoding);
2544 g_free(encoding);
2545 g_free(response);
2546 g_free(info->status_note_title);
2547 g_free(info);
2548 2574
2549 byte_stream_get16(bs); /* Unknown */ 2575 byte_stream_get16(bs); /* Unknown */
2550 byte_stream_get16(bs); /* Unknown */ 2576 byte_stream_get16(bs); /* Unknown */
2551 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) 2577 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
2552 ret = userfunc(od, conn, frame, channel, sn, reason, cookie); 2578 ret = userfunc(od, conn, frame, channel, sn, reason, cookie);