comparison src/protocols/oscar/oscar.c @ 3212:56746b0868db

[gaim-migrate @ 3229] More OSCAR stuff from KingAnt! committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Sun, 05 May 2002 19:02:08 +0000
parents 5e90ecb578c5
children f1ac8b51ec6b
comparison
equal deleted inserted replaced
3211:3ef95e625bbc 3212:56746b0868db
241 static int gaim_account_confirm (aim_session_t *, aim_frame_t *, ...); 241 static int gaim_account_confirm (aim_session_t *, aim_frame_t *, ...);
242 static int gaim_parse_oncoming (aim_session_t *, aim_frame_t *, ...); 242 static int gaim_parse_oncoming (aim_session_t *, aim_frame_t *, ...);
243 static int gaim_parse_offgoing (aim_session_t *, aim_frame_t *, ...); 243 static int gaim_parse_offgoing (aim_session_t *, aim_frame_t *, ...);
244 static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...); 244 static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...);
245 static int gaim_parse_misses (aim_session_t *, aim_frame_t *, ...); 245 static int gaim_parse_misses (aim_session_t *, aim_frame_t *, ...);
246 static int gaim_parse_clientauto (aim_session_t *, aim_frame_t *, ...);
246 static int gaim_parse_user_info (aim_session_t *, aim_frame_t *, ...); 247 static int gaim_parse_user_info (aim_session_t *, aim_frame_t *, ...);
247 static int gaim_parse_motd (aim_session_t *, aim_frame_t *, ...); 248 static int gaim_parse_motd (aim_session_t *, aim_frame_t *, ...);
248 static int gaim_chatnav_info (aim_session_t *, aim_frame_t *, ...); 249 static int gaim_chatnav_info (aim_session_t *, aim_frame_t *, ...);
249 static int gaim_chat_join (aim_session_t *, aim_frame_t *, ...); 250 static int gaim_chat_join (aim_session_t *, aim_frame_t *, ...);
250 static int gaim_chat_leave (aim_session_t *, aim_frame_t *, ...); 251 static int gaim_chat_leave (aim_session_t *, aim_frame_t *, ...);
689 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0); 690 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0);
690 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0); 691 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0);
691 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0); 692 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0);
692 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0); 693 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0);
693 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, gaim_parse_misses, 0); 694 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, gaim_parse_misses, 0);
695 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_CLIENTAUTORESP, gaim_parse_clientauto, 0);
694 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, gaim_parse_ratechange, 0); 696 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, gaim_parse_ratechange, 0);
695 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, gaim_parse_evilnotify, 0); 697 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, gaim_parse_evilnotify, 0);
696 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, gaim_parse_searcherror, 0); 698 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, gaim_parse_searcherror, 0);
697 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, gaim_parse_searchreply, 0); 699 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, gaim_parse_searchreply, 0);
698 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0); 700 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0);
1624 nummissed, 1626 nummissed,
1625 userinfo->sn); 1627 userinfo->sn);
1626 break; 1628 break;
1627 } 1629 }
1628 do_error_dialog(buf, _("Gaim - Error")); 1630 do_error_dialog(buf, _("Gaim - Error"));
1631
1632 return 1;
1633 }
1634
1635 static char *gaim_icq_status(int state) {
1636 /* Make a cute little string that shows the status of the dude or dudet */
1637 if (state & AIM_ICQ_STATE_CHAT)
1638 return g_strdup_printf("Free For Chat");
1639 else if (state & AIM_ICQ_STATE_DND)
1640 return g_strdup_printf("Do Not Disturb");
1641 else if (state & AIM_ICQ_STATE_OUT)
1642 return g_strdup_printf("Not Available");
1643 else if (state & AIM_ICQ_STATE_BUSY)
1644 return g_strdup_printf("Occupied");
1645 else if (state & AIM_ICQ_STATE_AWAY)
1646 return g_strdup_printf("Away");
1647 else if (state & AIM_ICQ_STATE_WEBAWARE)
1648 return g_strdup_printf("Web Aware");
1649 else if (state & AIM_ICQ_STATE_INVISIBLE)
1650 return g_strdup_printf("Invisible");
1651 else
1652 return g_strdup_printf("Online");
1653 }
1654
1655 static int gaim_parse_clientauto(aim_session_t *sess, aim_frame_t *fr, ...) {
1656 struct gaim_connection *gc = sess->aux_data;
1657 va_list ap;
1658 fu16_t chan, reason;
1659 char *who;
1660
1661 va_start(ap, fr);
1662 chan = (fu16_t)va_arg(ap, unsigned int);
1663 who = va_arg(ap, char *);
1664 reason = (fu16_t)va_arg(ap, unsigned int);
1665
1666 switch(reason) {
1667 case 0x0003: { /* Reply from an ICQ status message request */
1668 int state = (int)va_arg(ap, fu32_t);
1669 char *msg = va_arg(ap, char *);
1670 char *status_msg = gaim_icq_status(state);
1671 char *dialog_msg, **splitmsg;
1672 struct oscar_data *od = gc->proto_data;
1673 GSList *l = od->evilhack;
1674 gboolean evilhack = FALSE;
1675
1676 /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
1677 splitmsg = g_strsplit(msg, "\r\n", 0);
1678
1679 /* If who is in od->evilhack, then we're just getting the away message, otherwise this
1680 * will just get appended to the info box (which is already showing). */
1681 while (l) {
1682 char *x = l->data;
1683 if (!strcmp(x, normalize(who))) {
1684 evilhack = TRUE;
1685 g_free(x);
1686 od->evilhack = g_slist_remove(od->evilhack, x);
1687 break;
1688 }
1689 l = l->next;
1690 }
1691
1692 if (evilhack)
1693 dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<BR><HR><BR>%s<BR>"), who, status_msg, g_strjoinv("<BR>", splitmsg));
1694 else
1695 dialog_msg = g_strdup_printf(_("<B>Status:</B> %s<BR><HR><BR>%s<BR>"), status_msg, g_strjoinv("<BR>", splitmsg));
1696 g_show_info_text(gc, who, 2, dialog_msg, NULL);
1697
1698 g_free(status_msg);
1699 g_free(dialog_msg);
1700 g_strfreev(splitmsg);
1701 } break;
1702
1703 default: {
1704 debug_printf("Received an unknown client auto-response from %s. Type 0x%04x\n", who, reason);
1705 } break;
1706 }
1707 va_end(ap);
1629 1708
1630 return 1; 1709 return 1;
1631 } 1710 }
1632 1711
1633 static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) { 1712 static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) {
2395 } 2474 }
2396 2475
2397 static int gaim_simpleinfo(aim_session_t *sess, aim_frame_t *fr, ...) 2476 static int gaim_simpleinfo(aim_session_t *sess, aim_frame_t *fr, ...)
2398 { 2477 {
2399 struct gaim_connection *gc = sess->aux_data; 2478 struct gaim_connection *gc = sess->aux_data;
2479 struct buddy *budlight;
2400 va_list ap; 2480 va_list ap;
2401 struct aim_icq_simpleinfo *info; 2481 struct aim_icq_simpleinfo *info;
2402 char buf[16 * 1024]; 2482 char buf[16 * 1024];
2403 char who[16]; 2483 char who[16];
2404 2484
2409 g_snprintf(who, sizeof who, "%lu", info->uin); 2489 g_snprintf(who, sizeof who, "%lu", info->uin);
2410 g_snprintf(buf, sizeof buf, 2490 g_snprintf(buf, sizeof buf,
2411 "<B>UIN:</B> %lu<BR>" 2491 "<B>UIN:</B> %lu<BR>"
2412 "<B>Nick:</B> %s<BR>" 2492 "<B>Nick:</B> %s<BR>"
2413 "<B>Name:</B> %s %s<BR>" 2493 "<B>Name:</B> %s %s<BR>"
2414 "<B>Email:</B> %s\n", 2494 "<B>Email:</B> %s<BR>\n",
2415 info->uin, 2495 info->uin,
2416 info->nick, 2496 info->nick,
2417 info->first, info->last, 2497 info->first, info->last,
2418 info->email); 2498 info->email);
2419 2499
2420 g_show_info_text(gc, who, FALSE, buf, NULL); 2500 /* If the contact is away, then we also want to get their status message
2501 * and show it in the same window as info. g_show_info_text gets the status
2502 * message if the third arg is 0 (this seems really gross to me). The
2503 * parse-icq-status-message function knows if it is putting it's message in
2504 * an info window because the name will _not_ be in od->evilhack. For getting
2505 * only the away message the contact's UIN is put in od->evilhack. */
2506 if ((budlight = find_buddy(gc, who)) && ((budlight->uc >> 7) & (AIM_ICQ_STATE_AWAY || AIM_ICQ_STATE_DND || AIM_ICQ_STATE_OUT || AIM_ICQ_STATE_BUSY || AIM_ICQ_STATE_CHAT))) {
2507 if (budlight->caps & AIM_CAPS_ICQSERVERRELAY)
2508 g_show_info_text(gc, who, 0, buf, NULL);
2509 else {
2510 char *state_msg = gaim_icq_status((budlight->uc & 0xff80) >> 7);
2511 g_show_info_text(gc, who, 2, buf, "<B>Status:</B> ", state_msg, "<BR>\n<HR><BR><I>Remote client does not support sending status messages.</I><BR>\n", NULL);
2512 free(state_msg);
2513 }
2514 } else {
2515 char *state_msg = gaim_icq_status((budlight->uc & 0xff80) >> 7);
2516 g_show_info_text(gc, who, 2, buf, "<B>Status:</B> ", state_msg, NULL);
2517 free(state_msg);
2518 }
2421 2519
2422 return 1; 2520 return 1;
2423 } 2521 }
2424 2522
2425 static int gaim_popup(aim_session_t *sess, aim_frame_t *fr, ...) 2523 static int gaim_popup(aim_session_t *sess, aim_frame_t *fr, ...)
2457 len = num * (MAXSNLEN + 1) + 1024; 2555 len = num * (MAXSNLEN + 1) + 1024;
2458 buf = g_malloc(len); 2556 buf = g_malloc(len);
2459 at += g_snprintf(buf + at, len - at, "<B>%s has the following screen names:</B><BR>", address); 2557 at += g_snprintf(buf + at, len - at, "<B>%s has the following screen names:</B><BR>", address);
2460 for (i = 0; i < num; i++) 2558 for (i = 0; i < num; i++)
2461 at += g_snprintf(buf + at, len - at, "%s<BR>", &SNs[i * (MAXSNLEN + 1)]); 2559 at += g_snprintf(buf + at, len - at, "%s<BR>", &SNs[i * (MAXSNLEN + 1)]);
2462 g_show_info_text(NULL, NULL, FALSE, buf, NULL); 2560 g_show_info_text(NULL, NULL, 2, buf, NULL);
2463 g_free(buf); 2561 g_free(buf);
2464 2562
2465 return 1; 2563 return 1;
2466 } 2564 }
2467 2565
2633 * first and then get the regular info, since it's too difficult to 2731 * first and then get the regular info, since it's too difficult to
2634 * insert in the middle. i hate people. */ 2732 * insert in the middle. i hate people. */
2635 aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_AWAYMESSAGE); 2733 aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_AWAYMESSAGE);
2636 } 2734 }
2637 2735
2638 static void oscar_get_away(struct gaim_connection *g, char *name) { 2736 static void oscar_get_away(struct gaim_connection *g, char *who) {
2639 struct oscar_data *odata = (struct oscar_data *)g->proto_data; 2737 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
2640 if (!odata->icq) 2738 if (odata->icq) {
2641 aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_GENERALINFO); 2739 struct buddy *budlight = find_buddy(g, who);
2740 if (budlight)
2741 if ((budlight->uc & 0xff80) >> 7)
2742 if (budlight->caps & AIM_CAPS_ICQSERVERRELAY)
2743 aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7);
2744 else
2745 debug_printf("Error: Remote client does not support retrieval of status messages.\n");
2746 else
2747 debug_printf("Error: The user %s has no status message, therefore not requesting.\n", who);
2748 else
2749 debug_printf("Error: Could not find %s in local contact list, therefore unable to request status message.\n", who);
2750 } else
2751 aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_GENERALINFO);
2642 } 2752 }
2643 2753
2644 static void oscar_get_caps(struct gaim_connection *g, char *name) { 2754 static void oscar_get_caps(struct gaim_connection *g, char *name) {
2645 struct oscar_data *odata = (struct oscar_data *)g->proto_data; 2755 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
2646 aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_CAPABILITIES); 2756 aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_CAPABILITIES);
2727 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); 2837 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
2728 else if (!strcmp(state, "Away")) { 2838 else if (!strcmp(state, "Away")) {
2729 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY); 2839 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY);
2730 gc->away = ""; 2840 gc->away = "";
2731 } else if (!strcmp(state, "Do Not Disturb")) { 2841 } else if (!strcmp(state, "Do Not Disturb")) {
2732 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_DND); 2842 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY);
2733 gc->away = ""; 2843 gc->away = "";
2734 } else if (!strcmp(state, "Not Available")) { 2844 } else if (!strcmp(state, "Not Available")) {
2735 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY); 2845 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY);
2736 gc->away = ""; 2846 gc->away = "";
2737 } else if (!strcmp(state, "Occupied")) { 2847 } else if (!strcmp(state, "Occupied")) {
2738 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_BUSY); 2848 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY);
2739 gc->away = ""; 2849 gc->away = "";
2740 } else if (!strcmp(state, "Free For Chat")) { 2850 } else if (!strcmp(state, "Free For Chat")) {
2741 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_CHAT); 2851 aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_CHAT);
2742 gc->away = ""; 2852 gc->away = "";
2743 } else if (!strcmp(state, "Invisible")) { 2853 } else if (!strcmp(state, "Invisible")) {
3234 uc >>= 7; 3344 uc >>= 7;
3235 if (uc & AIM_ICQ_STATE_INVISIBLE) 3345 if (uc & AIM_ICQ_STATE_INVISIBLE)
3236 return icon_offline_xpm; 3346 return icon_offline_xpm;
3237 if (uc & AIM_ICQ_STATE_CHAT) 3347 if (uc & AIM_ICQ_STATE_CHAT)
3238 return icon_ffc_xpm; 3348 return icon_ffc_xpm;
3349 if (uc & AIM_ICQ_STATE_DND)
3350 return icon_dnd_xpm;
3351 if (uc & AIM_ICQ_STATE_OUT)
3352 return icon_na_xpm;
3239 if (uc & AIM_ICQ_STATE_BUSY) 3353 if (uc & AIM_ICQ_STATE_BUSY)
3240 return icon_occ_xpm; 3354 return icon_occ_xpm;
3241 if (uc & AIM_ICQ_STATE_OUT)
3242 return icon_na_xpm;
3243 if (uc & AIM_ICQ_STATE_DND)
3244 return icon_dnd_xpm;
3245 if (uc & AIM_ICQ_STATE_AWAY) 3355 if (uc & AIM_ICQ_STATE_AWAY)
3246 return icon_away_xpm; 3356 return icon_away_xpm;
3247 return icon_online_xpm; 3357 return icon_online_xpm;
3248 } 3358 }
3249 if (uc & UC_UNAVAILABLE) 3359 if (uc & UC_UNAVAILABLE)
3431 } 3541 }
3432 3542
3433 static void oscar_get_away_msg(struct gaim_connection *gc, char *who) { 3543 static void oscar_get_away_msg(struct gaim_connection *gc, char *who) {
3434 struct oscar_data *od = gc->proto_data; 3544 struct oscar_data *od = gc->proto_data;
3435 od->evilhack = g_slist_append(od->evilhack, g_strdup(normalize(who))); 3545 od->evilhack = g_slist_append(od->evilhack, g_strdup(normalize(who)));
3436 oscar_get_info(gc, who); 3546 if (od->icq) {
3547 struct buddy *budlight = find_buddy(gc, who);
3548 if (budlight)
3549 if ((budlight->uc >> 7) & (AIM_ICQ_STATE_AWAY || AIM_ICQ_STATE_DND || AIM_ICQ_STATE_OUT || AIM_ICQ_STATE_BUSY || AIM_ICQ_STATE_CHAT))
3550 if (budlight->caps & AIM_CAPS_ICQSERVERRELAY)
3551 aim_send_im_ch2_geticqmessage(od->sess, who, (budlight->uc & 0xff80) >> 7);
3552 else {
3553 char *state_msg = gaim_icq_status((budlight->uc & 0xff80) >> 7);
3554 char *dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<BR><HR><BR><I>Remote client does not support sending status messages.</I><BR>"), who, state_msg);
3555 g_show_info_text(gc, who, 2, dialog_msg, NULL);
3556 free(state_msg);
3557 free(dialog_msg);
3558 }
3559 else {
3560 char *state_msg = gaim_icq_status((budlight->uc & 0xff80) >> 7);
3561 char *dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<BR><HR><BR><I>User has no status message.</I><BR>"), who, state_msg);
3562 g_show_info_text(gc, who, 2, dialog_msg, NULL);
3563 free(state_msg);
3564 free(dialog_msg);
3565 }
3566 else
3567 do_error_dialog("Could not find contact in local list, therefore unable to request status message.\n", "Gaim - Error");
3568 } else
3569 oscar_get_info(gc, who);
3437 } 3570 }
3438 3571
3439 static GList *oscar_buddy_menu(struct gaim_connection *gc, char *who) { 3572 static GList *oscar_buddy_menu(struct gaim_connection *gc, char *who) {
3440 GList *m = NULL; 3573 GList *m = NULL;
3441 struct proto_buddy_menu *pbm; 3574 struct proto_buddy_menu *pbm;
3446 pbm->label = _("Get Info"); 3579 pbm->label = _("Get Info");
3447 pbm->callback = oscar_get_info; 3580 pbm->callback = oscar_get_info;
3448 pbm->gc = gc; 3581 pbm->gc = gc;
3449 m = g_list_append(m, pbm); 3582 m = g_list_append(m, pbm);
3450 3583
3451 if (!odata->icq) { 3584 if (odata->icq) {
3585 pbm = g_new0(struct proto_buddy_menu, 1);
3586 pbm->label = _("Get Status Msg");
3587 pbm->callback = oscar_get_away_msg;
3588 pbm->gc = gc;
3589 m = g_list_append(m, pbm);
3590 } else {
3452 pbm = g_new0(struct proto_buddy_menu, 1); 3591 pbm = g_new0(struct proto_buddy_menu, 1);
3453 pbm->label = _("Get Away Msg"); 3592 pbm->label = _("Get Away Msg");
3454 pbm->callback = oscar_get_away_msg; 3593 pbm->callback = oscar_get_away_msg;
3455 pbm->gc = gc; 3594 pbm->gc = gc;
3456 m = g_list_append(m, pbm); 3595 m = g_list_append(m, pbm);