comparison src/protocols/yahoo/yahoo.c @ 6729:7b878ee8f064

[gaim-migrate @ 7256] Tim Ringenbach (marv_sf) writes: " This adds Chat and Conference support to the Yahoo! prpl. I think I got all the major bugs out, and it works pretty good. You can invite others, and accept inventations for both chats and conferences, you can join a chat from the Buddies menu in the buddy list, like you would for irc, and you can initiate a conference by right clicking on a buddy, like you would for msn. You can also attempt to join user in chat, which will fail if they're not actually in a chat. (Apparently the offical version can't tell before hand either.) Oh, and you can chat." committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Wed, 03 Sep 2003 12:45:17 +0000
parents 0c5637b5462e
children e7e21e5d1d16
comparison
equal deleted inserted replaced
6728:fa7359c3f93c 6729:7b878ee8f064
32 #include "server.h" 32 #include "server.h"
33 #include "util.h" 33 #include "util.h"
34 #include "html.h" 34 #include "html.h"
35 35
36 #include "yahoo.h" 36 #include "yahoo.h"
37 #include "yahoochat.h"
37 #include "md5.h" 38 #include "md5.h"
38 39
39 /* XXX */ 40 /* XXX */
40 #include "gtkinternal.h" 41 #include "gtkinternal.h"
41 #include "gaim.h" 42 #include "gaim.h"
51 #define YAHOO_PAGER_PORT 5050 52 #define YAHOO_PAGER_PORT 5050
52 #define YAHOO_PROFILE_URL "http://profiles.yahoo.com/" 53 #define YAHOO_PROFILE_URL "http://profiles.yahoo.com/"
53 54
54 #define YAHOO_PROTO_VER 0x0900 55 #define YAHOO_PROTO_VER 0x0900
55 56
56 enum yahoo_service { /* these are easier to see in hex */
57 YAHOO_SERVICE_LOGON = 1,
58 YAHOO_SERVICE_LOGOFF,
59 YAHOO_SERVICE_ISAWAY,
60 YAHOO_SERVICE_ISBACK,
61 YAHOO_SERVICE_IDLE, /* 5 (placemarker) */
62 YAHOO_SERVICE_MESSAGE,
63 YAHOO_SERVICE_IDACT,
64 YAHOO_SERVICE_IDDEACT,
65 YAHOO_SERVICE_MAILSTAT,
66 YAHOO_SERVICE_USERSTAT, /* 0xa */
67 YAHOO_SERVICE_NEWMAIL,
68 YAHOO_SERVICE_CHATINVITE,
69 YAHOO_SERVICE_CALENDAR,
70 YAHOO_SERVICE_NEWPERSONALMAIL,
71 YAHOO_SERVICE_NEWCONTACT,
72 YAHOO_SERVICE_ADDIDENT, /* 0x10 */
73 YAHOO_SERVICE_ADDIGNORE,
74 YAHOO_SERVICE_PING,
75 YAHOO_SERVICE_GROUPRENAME,
76 YAHOO_SERVICE_SYSMESSAGE = 0x14,
77 YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
78 YAHOO_SERVICE_CONFINVITE = 0x18,
79 YAHOO_SERVICE_CONFLOGON,
80 YAHOO_SERVICE_CONFDECLINE,
81 YAHOO_SERVICE_CONFLOGOFF,
82 YAHOO_SERVICE_CONFADDINVITE,
83 YAHOO_SERVICE_CONFMSG,
84 YAHOO_SERVICE_CHATLOGON,
85 YAHOO_SERVICE_CHATLOGOFF,
86 YAHOO_SERVICE_CHATMSG = 0x20,
87 YAHOO_SERVICE_GAMELOGON = 0x28,
88 YAHOO_SERVICE_GAMELOGOFF,
89 YAHOO_SERVICE_GAMEMSG = 0x2a,
90 YAHOO_SERVICE_FILETRANSFER = 0x46,
91 YAHOO_SERVICE_NOTIFY = 0x4B,
92 YAHOO_SERVICE_AUTHRESP = 0x54,
93 YAHOO_SERVICE_LIST = 0x55,
94 YAHOO_SERVICE_AUTH = 0x57,
95 YAHOO_SERVICE_ADDBUDDY = 0x83,
96 YAHOO_SERVICE_REMBUDDY = 0x84
97 };
98
99 enum yahoo_status {
100 YAHOO_STATUS_AVAILABLE = 0,
101 YAHOO_STATUS_BRB,
102 YAHOO_STATUS_BUSY,
103 YAHOO_STATUS_NOTATHOME,
104 YAHOO_STATUS_NOTATDESK,
105 YAHOO_STATUS_NOTINOFFICE,
106 YAHOO_STATUS_ONPHONE,
107 YAHOO_STATUS_ONVACATION,
108 YAHOO_STATUS_OUTTOLUNCH,
109 YAHOO_STATUS_STEPPEDOUT,
110 YAHOO_STATUS_INVISIBLE = 12,
111 YAHOO_STATUS_CUSTOM = 99,
112 YAHOO_STATUS_IDLE = 999,
113 YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */
114 YAHOO_STATUS_TYPING = 0x16
115 };
116 #define YAHOO_STATUS_GAME 0x2 /* Games don't fit into the regular status model */
117
118 struct yahoo_data {
119 int fd;
120 guchar *rxqueue;
121 int rxlen;
122 GHashTable *hash;
123 GHashTable *games;
124 int current_status;
125 gboolean logged_in;
126 };
127
128 struct yahoo_pair {
129 int key;
130 char *value;
131 };
132
133 struct yahoo_packet {
134 guint16 service;
135 guint32 status;
136 guint32 id;
137 GSList *hash;
138 };
139
140 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4) 57 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
141 58
142 static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id) 59 struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
143 { 60 {
144 struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1); 61 struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
145 62
146 pkt->service = service; 63 pkt->service = service;
147 pkt->status = status; 64 pkt->status = status;
148 pkt->id = id; 65 pkt->id = id;
149 66
150 return pkt; 67 return pkt;
151 } 68 }
152 69
153 static void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value) 70 void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value)
154 { 71 {
155 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); 72 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
156 pair->key = key; 73 pair->key = key;
157 pair->value = g_strdup(value); 74 pair->value = g_strdup(value);
158 pkt->hash = g_slist_append(pkt->hash, pair); 75 pkt->hash = g_slist_append(pkt->hash, pair);
312 229
313 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); 230 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
314 #endif 231 #endif
315 } 232 }
316 233
317 static int yahoo_send_packet(struct yahoo_data *yd, struct yahoo_packet *pkt) 234 int yahoo_send_packet(struct yahoo_data *yd, struct yahoo_packet *pkt)
318 { 235 {
319 int pktlen = yahoo_packet_length(pkt); 236 int pktlen = yahoo_packet_length(pkt);
320 int len = YAHOO_PACKET_HDRLEN + pktlen; 237 int len = YAHOO_PACKET_HDRLEN + pktlen;
321 int ret; 238 int ret;
322 239
343 g_free(data); 260 g_free(data);
344 261
345 return ret; 262 return ret;
346 } 263 }
347 264
348 static void yahoo_packet_free(struct yahoo_packet *pkt) 265 void yahoo_packet_free(struct yahoo_packet *pkt)
349 { 266 {
350 while (pkt->hash) { 267 while (pkt->hash) {
351 struct yahoo_pair *pair = pkt->hash->data; 268 struct yahoo_pair *pair = pkt->hash->data;
352 g_free(pair->value); 269 g_free(pair->value);
353 g_free(pair); 270 g_free(pair);
915 yahoo_process_list(gc, pkt); 832 yahoo_process_list(gc, pkt);
916 break; 833 break;
917 case YAHOO_SERVICE_AUTH: 834 case YAHOO_SERVICE_AUTH:
918 yahoo_process_auth(gc, pkt); 835 yahoo_process_auth(gc, pkt);
919 break; 836 break;
837 case YAHOO_SERVICE_CONFINVITE:
838 case YAHOO_SERVICE_CONFADDINVITE:
839 yahoo_process_conference_invite(gc, pkt);
840 break;
841 case YAHOO_SERVICE_CONFDECLINE:
842 yahoo_process_conference_decline(gc, pkt);
843 break;
844 case YAHOO_SERVICE_CONFLOGON:
845 yahoo_process_conference_logon(gc, pkt);
846 break;
847 case YAHOO_SERVICE_CONFLOGOFF:
848 yahoo_process_conference_logoff(gc, pkt);
849 break;
850 case YAHOO_SERVICE_CONFMSG:
851 yahoo_process_conference_message(gc, pkt);
852 break;
853 case YAHOO_SERVICE_CHATONLINE:
854 yahoo_process_chat_online(gc, pkt);
855 break;
856 case YAHOO_SERVICE_CHATLOGOUT:
857 yahoo_process_chat_logout(gc, pkt);
858 break;
859 case YAHOO_SERVICE_CHATGOTO:
860 yahoo_process_chat_goto(gc, pkt);
861 break;
862 case YAHOO_SERVICE_CHATJOIN:
863 yahoo_process_chat_join(gc, pkt);
864 break;
865 case YAHOO_SERVICE_CHATLEAVE: /* XXX is this right? */
866 case YAHOO_SERVICE_CHATEXIT:
867 yahoo_process_chat_exit(gc, pkt);
868 break;
869 case YAHOO_SERVICE_CHATINVITE: /* XXX never seen this one, might not do it right */
870 case YAHOO_SERVICE_CHATADDINVITE:
871 yahoo_process_chat_addinvite(gc, pkt);
872 break;
873 case YAHOO_SERVICE_COMMENT:
874 yahoo_process_chat_message(gc, pkt);
875 break;
920 default: 876 default:
921 gaim_debug(GAIM_DEBUG_ERROR, "yahoo", 877 gaim_debug(GAIM_DEBUG_ERROR, "yahoo",
922 "Unhandled service 0x%02x\n", pkt->service); 878 "Unhandled service 0x%02x\n", pkt->service);
923 break; 879 break;
924 } 880 }
1028 gaim_connection_update_progress(gc, _("Connecting"), 1, 2); 984 gaim_connection_update_progress(gc, _("Connecting"), 1, 2);
1029 985
1030 yd->fd = -1; 986 yd->fd = -1;
1031 yd->hash = g_hash_table_new(g_str_hash, g_str_equal); 987 yd->hash = g_hash_table_new(g_str_hash, g_str_equal);
1032 yd->games = g_hash_table_new(g_str_hash, g_str_equal); 988 yd->games = g_hash_table_new(g_str_hash, g_str_equal);
989 yd->confs = NULL;
990 yd->conf_id = 2;
1033 991
1034 if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", YAHOO_PAGER_HOST), 992 if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", YAHOO_PAGER_HOST),
1035 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), 993 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT),
1036 yahoo_got_connected, gc) != 0) { 994 yahoo_got_connected, gc) != 0) {
1037 gaim_connection_error(gc, _("Connection problem")); 995 gaim_connection_error(gc, _("Connection problem"));
1051 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; 1009 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
1052 g_hash_table_foreach_remove(yd->hash, yahoo_destroy_hash, NULL); 1010 g_hash_table_foreach_remove(yd->hash, yahoo_destroy_hash, NULL);
1053 g_hash_table_destroy(yd->hash); 1011 g_hash_table_destroy(yd->hash);
1054 g_hash_table_foreach_remove(yd->games, yahoo_destroy_hash, NULL); 1012 g_hash_table_foreach_remove(yd->games, yahoo_destroy_hash, NULL);
1055 g_hash_table_destroy(yd->games); 1013 g_hash_table_destroy(yd->games);
1014
1015 g_slist_free(yd->confs);
1016
1056 if (yd->fd >= 0) 1017 if (yd->fd >= 0)
1057 close(yd->fd); 1018 close(yd->fd);
1058 1019
1059 if (yd->rxqueue) 1020 if (yd->rxqueue)
1060 g_free(yd->rxqueue); 1021 g_free(yd->rxqueue);
1116 default: 1077 default:
1117 return _("Online"); 1078 return _("Online");
1118 } 1079 }
1119 } 1080 }
1120 1081
1082 static void yahoo_initiate_conference(GaimConnection *gc, const char *name)
1083 {
1084 GHashTable *components;
1085 struct yahoo_data *yd;
1086 int id;
1087
1088 yd = gc->proto_data;
1089 id = yd->conf_id;
1090
1091 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1092 g_hash_table_replace(components, g_strdup("room"),
1093 g_strdup_printf("%s-%d", gaim_connection_get_display_name(gc), id));
1094 g_hash_table_replace(components, g_strdup("topic"), g_strdup("Join my conference..."));
1095 g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
1096 yahoo_c_join(gc, components);
1097 g_hash_table_destroy(components);
1098
1099 yahoo_c_invite(gc, id, "Join my conference...", name);
1100 }
1101
1121 static void yahoo_game(GaimConnection *gc, const char *name) { 1102 static void yahoo_game(GaimConnection *gc, const char *name) {
1122 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; 1103 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
1123 char *game = g_hash_table_lookup(yd->games, name); 1104 char *game = g_hash_table_lookup(yd->games, name);
1124 char *t; 1105 char *t;
1125 char url[256]; 1106 char url[256];
1181 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; 1162 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
1182 GaimBuddy *b = gaim_find_buddy(gc->account, who); /* this should never be null. if it is, 1163 GaimBuddy *b = gaim_find_buddy(gc->account, who); /* this should never be null. if it is,
1183 segfault and get the bug report. */ 1164 segfault and get the bug report. */
1184 static char buf2[1024]; 1165 static char buf2[1024];
1185 1166
1167 pbm = g_new0(struct proto_buddy_menu, 1);
1168 pbm->label = _("Join in Chat");
1169 pbm->callback = yahoo_chat_goto;
1170 pbm->gc = gc;
1171 m = g_list_append(m, pbm);
1172
1173 pbm = g_new0(struct proto_buddy_menu, 1);
1174 pbm->label = _("Initiate Conference");
1175 pbm->callback = yahoo_initiate_conference;
1176 pbm->gc = gc;
1177 m = g_list_append(m, pbm);
1178
1186 if (b->uc | YAHOO_STATUS_GAME) { 1179 if (b->uc | YAHOO_STATUS_GAME) {
1187 char *game = g_hash_table_lookup(yd->games, b->name); 1180 char *game = g_hash_table_lookup(yd->games, b->name);
1188 char *room; 1181 char *room;
1189 if (!game) 1182 if (!game)
1190 return m; 1183 return m;
1191 if (game) { 1184 if (game) {
1192 char *t; 1185 char *t;
1193 pbm = g_new0(struct proto_buddy_menu, 1); 1186 pbm = g_new0(struct proto_buddy_menu, 1);
1194 if (!(room = strstr(game, "&follow="))) /* skip ahead to the url */ 1187 if (!(room = strstr(game, "&follow="))) /* skip ahead to the url */
1195 return NULL; 1188 return m;
1196 while (*room && *room != '\t') /* skip to the tab */ 1189 while (*room && *room != '\t') /* skip to the tab */
1197 room++; 1190 room++;
1198 t = room++; /* room as now at the name */ 1191 t = room++; /* room as now at the name */
1199 while (*t != '\n') 1192 while (*t != '\n')
1200 t++; /* replace the \n with a space */ 1193 t++; /* replace the \n with a space */
1201 *t = ' '; 1194 *t = ' ';
1202 g_snprintf(buf2, sizeof buf2, "%s", room); 1195 g_snprintf(buf2, sizeof buf2, "%s", room);
1203 pbm->label = buf2; 1196 pbm->label = buf2;
1204 pbm->callback = yahoo_game; 1197 pbm->callback = yahoo_game;
1205 pbm->gc = gc; 1198 pbm->gc = gc;
1206 m = g_list_append(m, pbm); 1199 m = g_list_append(m, pbm);
1207 } 1200 }
1208 } 1201 }
1209 1202
1210 return m; 1203 return m;
1211 } 1204 }
1212 1205
1213 static void yahoo_act_id(GaimConnection *gc, const char *entry) 1206 static void yahoo_act_id(GaimConnection *gc, const char *entry)
1214 { 1207 {
1399 { 1392 {
1400 struct yahoo_data *yd = gc->proto_data; 1393 struct yahoo_data *yd = gc->proto_data;
1401 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, 0); 1394 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, 0);
1402 yahoo_send_packet(yd, pkt); 1395 yahoo_send_packet(yd, pkt);
1403 yahoo_packet_free(pkt); 1396 yahoo_packet_free(pkt);
1397
1398 if (!yd->chat_online)
1399 return;
1400
1401 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, 0);
1402 yahoo_packet_hash(pkt, 109, gaim_connection_get_display_name(gc));
1403 yahoo_send_packet(yd, pkt);
1404 yahoo_packet_free(pkt);
1404 } 1405 }
1405 1406
1406 static void yahoo_add_buddy(GaimConnection *gc, const char *who) 1407 static void yahoo_add_buddy(GaimConnection *gc, const char *who)
1407 { 1408 {
1408 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; 1409 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
1617 static GaimPlugin *my_protocol = NULL; 1618 static GaimPlugin *my_protocol = NULL;
1618 1619
1619 static GaimPluginProtocolInfo prpl_info = 1620 static GaimPluginProtocolInfo prpl_info =
1620 { 1621 {
1621 GAIM_PROTO_YAHOO, 1622 GAIM_PROTO_YAHOO,
1622 OPT_PROTO_MAIL_CHECK, 1623 OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
1623 NULL, 1624 NULL, /* user_splits */
1624 NULL, 1625 NULL, /* protocol_options */
1625 yahoo_list_icon, 1626 yahoo_list_icon,
1626 yahoo_list_emblems, 1627 yahoo_list_emblems,
1627 yahoo_status_text, 1628 yahoo_status_text,
1628 yahoo_tooltip_text, 1629 yahoo_tooltip_text,
1629 yahoo_away_states, 1630 yahoo_away_states,
1630 yahoo_actions, 1631 yahoo_actions,
1631 yahoo_buddy_menu, 1632 yahoo_buddy_menu,
1632 NULL, 1633 yahoo_c_info,
1633 yahoo_login, 1634 yahoo_login,
1634 yahoo_close, 1635 yahoo_close,
1635 yahoo_send_im, 1636 yahoo_send_im,
1636 NULL, 1637 NULL, /* set info */
1637 yahoo_send_typing, 1638 yahoo_send_typing,
1638 yahoo_get_info, 1639 yahoo_get_info,
1639 yahoo_set_away, 1640 yahoo_set_away,
1640 NULL, 1641 NULL, /* get_away */
1641 NULL, 1642 NULL, /* set_dir */
1642 NULL, 1643 NULL, /* get_dir */
1643 NULL, 1644 NULL, /* dir_search */
1644 yahoo_set_idle, 1645 yahoo_set_idle,
1645 NULL, 1646 NULL, /* change_passwd*/
1646 yahoo_add_buddy, 1647 yahoo_add_buddy,
1647 NULL, 1648 NULL, /* add_buddies */
1648 yahoo_remove_buddy, 1649 yahoo_remove_buddy,
1649 NULL, 1650 NULL, /*remove_buddies */
1650 NULL, 1651 NULL, /* add_permit */
1651 NULL, 1652 NULL, /* add_dey */
1652 NULL, 1653 NULL, /* rem_permit */
1653 NULL, 1654 NULL, /* rem_deny */
1654 NULL, 1655 NULL, /* set_permit_deny */
1655 NULL, 1656 NULL, /* warn */
1656 NULL, 1657 yahoo_c_join,
1657 NULL, 1658 yahoo_c_invite,
1658 NULL, 1659 yahoo_c_leave,
1659 NULL, 1660 NULL, /* chat whisper */
1660 NULL, 1661 yahoo_c_send,
1661 yahoo_keepalive, 1662 yahoo_keepalive,
1662 NULL, 1663 NULL, /* register_user */
1663 NULL, 1664 NULL, /* get_cb_info */
1664 NULL, 1665 NULL, /* get_cb_away */
1665 NULL, 1666 NULL, /* alias_buddy */
1666 NULL, 1667 NULL, /* change group */
1667 NULL, 1668 NULL, /* rename group */
1668 NULL, 1669 NULL, /* buddy_free */
1669 NULL, 1670 NULL, /* convo_closed */
1670 NULL 1671 NULL, /* normalize */
1672 NULL /* set_buddy_icon */
1671 }; 1673 };
1672 1674
1673 static GaimPluginInfo info = 1675 static GaimPluginInfo info =
1674 { 1676 {
1675 2, /**< api_version */ 1677 2, /**< api_version */