Mercurial > pidgin
annotate src/protocols/yahoo/yahoochat.c @ 11454:201617d49573
[gaim-migrate @ 13693]
This commit includes a number of changes:
1. Aliases are now used consistently in chats. If the prpl uses unique screen names for chats (e.g. Jabber), then aliases are not used at all.
2. The chat list is now colorized to match the colors used in the chat itself.
3. Buddies are bolded in the chat user list.
4. Buddies are sorted above non-buddies in the chat user list.
5. The chat user list is ellipsized when possible (i.e. on GTK+ 2.6.0 or above).
6. I've accepted patch #1178248, by Matt Amato to add "buddy-added" and "buddy-removed" signals. These were used in my implementation of #3 and #4, to update the GUI when users are added or removed from the buddy list.
7. I've added a "blist-node-aliased" signal that is emitted when a buddy, contact, or chat is aliased.
8. Since it was hard to separate and I need it at some point, I'm letting it slip in... I've changed GaimConversation.log to be a GList named logs. This way, we can have multiple logs for a single conversation. This will be necessary to implement unnamed chat logging in some reasonable fasion (see my notes in the TODO file).
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Tue, 06 Sep 2005 03:04:07 +0000 |
parents | 519dc2186438 |
children | b1f8151e6ae5 |
rev | line source |
---|---|
6729 | 1 /* |
2 * gaim | |
3 * | |
8046 | 4 * Gaim is the legal property of its developers, whose names are too numerous |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
6729 | 8 * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com> |
9 * (marv on irc.freenode.net) | |
10 * Some code borrowed from libyahoo2, copyright (C) 2002, Philip | |
11 * S Tellis <philip . tellis AT gmx . net> | |
12 * | |
13 * This program is free software; you can redistribute it and/or modify | |
14 * it under the terms of the GNU General Public License as published by | |
15 * the Free Software Foundation; either version 2 of the License, or | |
16 * (at your option) any later version. | |
17 * | |
18 * This program is distributed in the hope that it will be useful, | |
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 * GNU General Public License for more details. | |
22 * | |
23 * You should have received a copy of the GNU General Public License | |
24 * along with this program; if not, write to the Free Software | |
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
26 * | |
27 */ | |
28 | |
29 #ifdef HAVE_CONFIG_H | |
30 #include "config.h" | |
31 #endif | |
32 | |
33 #include "debug.h" | |
10937 | 34 #include "privacy.h" |
6729 | 35 #include "prpl.h" |
36 | |
37 #include "conversation.h" | |
38 #include "notify.h" | |
39 #include "util.h" | |
40 #include "internal.h" | |
41 | |
42 #include "yahoo.h" | |
10392 | 43 #include "yahoo_packet.h" |
6729 | 44 #include "yahoochat.h" |
9376 | 45 #include "ycht.h" |
6729 | 46 |
47 #define YAHOO_CHAT_ID (1) | |
48 | |
7186 | 49 /* prototype(s) */ |
50 static void yahoo_chat_leave(GaimConnection *gc, const char *room, const char *dn, gboolean logout); | |
51 | |
6729 | 52 /* special function to log us on to the yahoo chat service */ |
53 static void yahoo_chat_online(GaimConnection *gc) | |
54 { | |
55 struct yahoo_data *yd = gc->proto_data; | |
56 struct yahoo_packet *pkt; | |
57 | |
9376 | 58 if (yd->wm) { |
59 ycht_connection_open(gc); | |
60 return; | |
61 } | |
6729 | 62 |
63 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE,0); | |
10394 | 64 yahoo_packet_hash(pkt, "sss", 1, gaim_connection_get_display_name(gc), |
65 109, gaim_connection_get_display_name(gc), 6, "abcde"); | |
10392 | 66 yahoo_packet_send_and_free(pkt, yd); |
6729 | 67 } |
68 | |
69 /* this is slow, and different from the gaim_* version in that it (hopefully) won't add a user twice */ | |
9376 | 70 void yahoo_chat_add_users(GaimConvChat *chat, GList *newusers) |
6729 | 71 { |
9554 | 72 GList *i; |
6729 | 73 |
74 for (i = newusers; i; i = i->next) { | |
9554 | 75 if (gaim_conv_chat_find_user(chat, i->data)) |
6729 | 76 continue; |
9846 | 77 gaim_conv_chat_add_user(chat, i->data, NULL, GAIM_CBFLAGS_NONE, TRUE); |
6729 | 78 } |
79 } | |
80 | |
9376 | 81 void yahoo_chat_add_user(GaimConvChat *chat, const char *user, const char *reason) |
6729 | 82 { |
9554 | 83 if (gaim_conv_chat_find_user(chat, user)) |
6729 | 84 return; |
85 | |
9846 | 86 gaim_conv_chat_add_user(chat, user, reason, GAIM_CBFLAGS_NONE, TRUE); |
6729 | 87 } |
88 | |
89 static GaimConversation *yahoo_find_conference(GaimConnection *gc, const char *name) | |
90 { | |
91 struct yahoo_data *yd; | |
92 GSList *l; | |
93 | |
94 yd = gc->proto_data; | |
95 | |
96 for (l = yd->confs; l; l = l->next) { | |
97 GaimConversation *c = l->data; | |
98 if (!gaim_utf8_strcasecmp(gaim_conversation_get_name(c), name)) | |
99 return c; | |
100 } | |
101 return NULL; | |
102 } | |
103 | |
104 | |
105 void yahoo_process_conference_invite(GaimConnection *gc, struct yahoo_packet *pkt) | |
106 { | |
107 GSList *l; | |
108 char *room = NULL; | |
109 char *who = NULL; | |
110 char *msg = NULL; | |
111 GString *members = NULL; | |
112 GHashTable *components; | |
113 | |
114 | |
115 if (pkt->status == 2) | |
116 return; /* XXX */ | |
117 | |
118 members = g_string_sized_new(512); | |
119 | |
120 for (l = pkt->hash; l; l = l->next) { | |
121 struct yahoo_pair *pair = l->data; | |
122 | |
123 switch (pair->key) { | |
124 case 1: /* us, but we already know who we are */ | |
125 break; | |
126 case 57: | |
7827 | 127 room = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 128 break; |
129 case 50: /* inviter */ | |
130 who = pair->value; | |
131 g_string_append_printf(members, "%s\n", who); | |
132 break; | |
9780 | 133 case 52: /* invitee (me) */ |
134 case 53: /* members */ | |
6729 | 135 g_string_append_printf(members, "%s\n", pair->value); |
136 break; | |
137 case 58: | |
7827 | 138 msg = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 139 break; |
140 case 13: /* ? */ | |
141 break; | |
142 } | |
143 } | |
144 | |
145 if (!room) { | |
146 g_string_free(members, TRUE); | |
147 return; | |
148 } | |
149 | |
150 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
7827 | 151 g_hash_table_replace(components, g_strdup("room"), room); |
6729 | 152 if (msg) |
7827 | 153 g_hash_table_replace(components, g_strdup("topic"), msg); |
6729 | 154 g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference")); |
155 if (members) { | |
156 g_hash_table_replace(components, g_strdup("members"), g_strdup(members->str)); | |
157 } | |
10937 | 158 if (!yahoo_privacy_check(gc, who)) { |
159 gaim_debug_info("yahoo", | |
160 "Invite to conference %s from %s has been dropped.\n", room, who); | |
11044
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
161 g_string_free(members, TRUE); |
10937 | 162 return; |
163 } | |
6729 | 164 serv_got_chat_invite(gc, room, who, msg, components); |
165 | |
166 g_string_free(members, TRUE); | |
167 } | |
168 | |
169 void yahoo_process_conference_decline(GaimConnection *gc, struct yahoo_packet *pkt) | |
170 { | |
171 GSList *l; | |
172 char *room = NULL; | |
173 char *who = NULL; | |
174 char *msg = NULL; | |
175 | |
176 for (l = pkt->hash; l; l = l->next) { | |
177 struct yahoo_pair *pair = l->data; | |
178 | |
179 switch (pair->key) { | |
180 case 57: | |
7827 | 181 room = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 182 break; |
183 case 54: | |
184 who = pair->value; | |
185 break; | |
186 case 14: | |
7827 | 187 msg = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 188 break; |
189 } | |
190 } | |
11044
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
191 if (!yahoo_privacy_check(gc, who)) { |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
192 g_free(room); |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
193 if (msg != NULL) |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
194 g_free(msg); |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
195 return; |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
196 } |
6729 | 197 |
198 if (who && room) { | |
9575 | 199 /* make sure we're in the room before we process a decline message for it */ |
9576 | 200 if(yahoo_find_conference(gc, room)) { |
9575 | 201 char *tmp; |
6729 | 202 |
9575 | 203 tmp = g_strdup_printf(_("%s declined your conference invitation to room \"%s\" because \"%s\"."), |
204 who, room, msg?msg:""); | |
205 gaim_notify_info(gc, NULL, _("Invitation Rejected"), tmp); | |
206 g_free(tmp); | |
207 } | |
208 | |
7827 | 209 g_free(room); |
210 if (msg) | |
211 g_free(msg); | |
6729 | 212 } |
213 } | |
214 | |
215 void yahoo_process_conference_logon(GaimConnection *gc, struct yahoo_packet *pkt) | |
216 { | |
217 GSList *l; | |
218 char *room = NULL; | |
219 char *who = NULL; | |
220 GaimConversation *c; | |
221 | |
222 for (l = pkt->hash; l; l = l->next) { | |
223 struct yahoo_pair *pair = l->data; | |
224 | |
225 switch (pair->key) { | |
226 case 57: | |
7827 | 227 room = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 228 break; |
229 case 53: | |
230 who = pair->value; | |
231 break; | |
232 } | |
233 } | |
234 | |
235 if (who && room) { | |
236 c = yahoo_find_conference(gc, room); | |
237 if (c) | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
238 yahoo_chat_add_user(GAIM_CONV_CHAT(c), who, NULL); |
7827 | 239 g_free(room); |
6729 | 240 } |
241 } | |
242 | |
243 void yahoo_process_conference_logoff(GaimConnection *gc, struct yahoo_packet *pkt) | |
244 { | |
245 GSList *l; | |
246 char *room = NULL; | |
247 char *who = NULL; | |
248 GaimConversation *c; | |
249 | |
250 for (l = pkt->hash; l; l = l->next) { | |
251 struct yahoo_pair *pair = l->data; | |
252 | |
253 switch (pair->key) { | |
254 case 57: | |
7827 | 255 room = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 256 break; |
257 case 56: | |
258 who = pair->value; | |
259 break; | |
260 } | |
261 } | |
262 | |
263 if (who && room) { | |
264 c = yahoo_find_conference(gc, room); | |
265 if (c) | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
266 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c), who, NULL); |
7827 | 267 g_free(room); |
6729 | 268 } |
269 } | |
270 | |
271 void yahoo_process_conference_message(GaimConnection *gc, struct yahoo_packet *pkt) | |
272 { | |
273 GSList *l; | |
274 char *room = NULL; | |
275 char *who = NULL; | |
276 char *msg = NULL; | |
7827 | 277 char *msg2; |
278 int utf8 = 0; | |
6729 | 279 GaimConversation *c; |
280 | |
281 for (l = pkt->hash; l; l = l->next) { | |
282 struct yahoo_pair *pair = l->data; | |
283 | |
284 switch (pair->key) { | |
285 case 57: | |
7827 | 286 room = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 287 break; |
288 case 3: | |
289 who = pair->value; | |
290 break; | |
291 case 14: | |
292 msg = pair->value; | |
293 break; | |
7827 | 294 case 97: |
295 utf8 = strtol(pair->value, NULL, 10); | |
296 break; | |
6729 | 297 } |
298 } | |
299 | |
300 if (room && who && msg) { | |
7827 | 301 msg2 = yahoo_string_decode(gc, msg, utf8); |
6729 | 302 c = yahoo_find_conference(gc, room); |
303 if (!c) | |
304 return; | |
7827 | 305 msg = yahoo_codes_to_html(msg2); |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
306 serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(c)), who, 0, msg, time(NULL)); |
6729 | 307 g_free(msg); |
7827 | 308 g_free(msg2); |
6729 | 309 } |
7827 | 310 if (room) |
311 g_free(room); | |
6729 | 312 } |
313 | |
314 | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8584
diff
changeset
|
315 /* this is a confirmation of yahoo_chat_online(); */ |
6729 | 316 void yahoo_process_chat_online(GaimConnection *gc, struct yahoo_packet *pkt) |
317 { | |
318 struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data; | |
319 | |
320 if (pkt->status == 1) | |
321 yd->chat_online = 1; | |
322 } | |
323 | |
324 /* this is basicly the opposite of chat_online */ | |
325 void yahoo_process_chat_logout(GaimConnection *gc, struct yahoo_packet *pkt) | |
326 { | |
327 struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data; | |
7186 | 328 GSList *l; |
7827 | 329 |
7186 | 330 for (l = pkt->hash; l; l = l->next) { |
331 struct yahoo_pair *pair = l->data; | |
6729 | 332 |
7186 | 333 if (pair->key == 1) |
334 if (g_ascii_strcasecmp(pair->value, | |
335 gaim_connection_get_display_name(gc))) | |
336 return; | |
337 } | |
7827 | 338 |
7186 | 339 if (pkt->status == 1) { |
6729 | 340 yd->chat_online = 0; |
7186 | 341 if (yd->in_chat) |
342 yahoo_c_leave(gc, YAHOO_CHAT_ID); | |
343 } | |
6729 | 344 } |
345 | |
346 void yahoo_process_chat_join(GaimConnection *gc, struct yahoo_packet *pkt) | |
347 { | |
10937 | 348 GaimAccount *account = gaim_connection_get_account(gc); |
6729 | 349 struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data; |
350 GaimConversation *c = NULL; | |
351 GSList *l; | |
352 GList *members = NULL; | |
10937 | 353 GList *roomies = NULL; |
354 GaimConversationUiOps *ops; | |
6729 | 355 char *room = NULL; |
356 char *topic = NULL; | |
357 char *someid, *someotherid, *somebase64orhashosomething, *somenegativenumber; | |
358 | |
359 if (pkt->status == -1) { | |
360 gaim_notify_error(gc, NULL, _("Failed to join chat"), _("Maybe the room is full?")); | |
361 return; | |
362 } | |
363 | |
364 for (l = pkt->hash; l; l = l->next) { | |
365 struct yahoo_pair *pair = l->data; | |
366 | |
367 switch (pair->key) { | |
368 | |
369 case 104: | |
8410 | 370 room = yahoo_string_decode(gc, pair->value, TRUE); |
6729 | 371 break; |
372 case 105: | |
8410 | 373 topic = yahoo_string_decode(gc, pair->value, TRUE); |
6729 | 374 break; |
375 case 128: | |
376 someid = pair->value; | |
377 break; | |
378 case 108: /* number of joiners */ | |
379 break; | |
380 case 129: | |
381 someotherid = pair->value; | |
382 break; | |
383 case 130: | |
384 somebase64orhashosomething = pair->value; | |
385 break; | |
386 case 126: | |
387 somenegativenumber = pair->value; | |
388 break; | |
389 case 13: /* this is 1. maybe its the type of room? (normal, user created, private, etc?) */ | |
390 break; | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8584
diff
changeset
|
391 case 61: /*this looks similar to 130 */ |
6729 | 392 break; |
393 | |
394 /* the previous section was just room info. this next section is | |
395 info about individual room members, (including us) */ | |
396 | |
397 case 109: /* the yahoo id */ | |
398 members = g_list_append(members, pair->value); | |
399 break; | |
400 case 110: /* age */ | |
401 break; | |
402 case 141: /* nickname */ | |
403 break; | |
404 case 142: /* location */ | |
405 break; | |
406 case 113: /* bitmask */ | |
407 break; | |
408 } | |
409 } | |
410 | |
411 | |
9329 | 412 if (room && yd->chat_name && gaim_utf8_strcasecmp(room, yd->chat_name)) |
7186 | 413 yahoo_chat_leave(gc, room, |
414 gaim_connection_get_display_name(gc), FALSE); | |
6729 | 415 |
416 c = gaim_find_chat(gc, YAHOO_CHAT_ID); | |
417 | |
9329 | 418 if (room && (!c || gaim_conv_chat_has_left(GAIM_CONV_CHAT(c))) && members && |
8357 | 419 ((g_list_length(members) > 1) || |
420 !g_ascii_strcasecmp(members->data, gaim_connection_get_display_name(gc)))) { | |
9554 | 421 int i; |
422 GList *flags = NULL; | |
423 for (i = 0; i < g_list_length(members); i++) | |
424 flags = g_list_append(flags, GINT_TO_POINTER(GAIM_CBFLAGS_NONE)); | |
8357 | 425 if (c && gaim_conv_chat_has_left(GAIM_CONV_CHAT(c))) { |
426 /* this might be a hack, but oh well, it should nicely */ | |
427 char *tmpmsg; | |
428 | |
429 gaim_conversation_set_name(c, room); | |
430 | |
431 c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room); | |
432 if (topic) | |
433 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(c), NULL, topic); | |
434 yd->in_chat = 1; | |
435 yd->chat_name = g_strdup(room); | |
11454
201617d49573
[gaim-migrate @ 13693]
Richard Laager <rlaager@wiktel.com>
parents:
11318
diff
changeset
|
436 gaim_conv_chat_add_users(GAIM_CONV_CHAT(c), members, NULL, flags, FALSE); |
8357 | 437 |
438 tmpmsg = g_strdup_printf(_("You are now chatting in %s."), room); | |
439 gaim_conv_chat_write(GAIM_CONV_CHAT(c), "", tmpmsg, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
440 g_free(tmpmsg); | |
441 } else { | |
442 c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room); | |
443 if (topic) | |
444 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(c), NULL, topic); | |
445 yd->in_chat = 1; | |
446 yd->chat_name = g_strdup(room); | |
11454
201617d49573
[gaim-migrate @ 13693]
Richard Laager <rlaager@wiktel.com>
parents:
11318
diff
changeset
|
447 gaim_conv_chat_add_users(GAIM_CONV_CHAT(c), members, NULL, flags, FALSE); |
8357 | 448 } |
7186 | 449 } else if (c) { |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
450 yahoo_chat_add_users(GAIM_CONV_CHAT(c), members); |
6729 | 451 } |
452 | |
10937 | 453 ops = gaim_conversation_get_ui_ops(c); |
454 | |
455 for (l = account->deny; l != NULL; l = l->next) { | |
456 for (roomies = members; roomies; roomies = roomies->next) { | |
457 if (!gaim_utf8_strcasecmp((char *)l->data, roomies->data)) { | |
458 gaim_debug_info("yahoo", "Ignoring room member %s in room %s\n" ,roomies->data, room); | |
459 gaim_conv_chat_ignore(GAIM_CONV_CHAT(c),roomies->data); | |
460 ops->chat_update_user((c), roomies->data); | |
461 } | |
462 } | |
463 } | |
464 g_list_free(roomies); | |
6729 | 465 g_list_free(members); |
7827 | 466 g_free(room); |
467 if (topic) | |
468 g_free(topic); | |
6729 | 469 } |
470 | |
471 void yahoo_process_chat_exit(GaimConnection *gc, struct yahoo_packet *pkt) | |
472 { | |
473 char *who = NULL; | |
7186 | 474 char *room = NULL; |
6729 | 475 GSList *l; |
476 struct yahoo_data *yd; | |
477 | |
478 yd = gc->proto_data; | |
479 | |
480 for (l = pkt->hash; l; l = l->next) { | |
481 struct yahoo_pair *pair = l->data; | |
482 | |
7186 | 483 if (pair->key == 104) |
8410 | 484 room = yahoo_string_decode(gc, pair->value, TRUE); |
6729 | 485 if (pair->key == 109) |
486 who = pair->value; | |
487 } | |
488 | |
489 | |
7186 | 490 if (who && room) { |
6729 | 491 GaimConversation *c = gaim_find_chat(gc, YAHOO_CHAT_ID); |
7186 | 492 if (c && !gaim_utf8_strcasecmp(gaim_conversation_get_name(c), room)) |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
493 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c), who, NULL); |
6729 | 494 |
495 } | |
7827 | 496 if (room) |
497 g_free(room); | |
6729 | 498 } |
499 | |
500 void yahoo_process_chat_message(GaimConnection *gc, struct yahoo_packet *pkt) | |
501 { | |
7827 | 502 char *room = NULL, *who = NULL, *msg = NULL, *msg2; |
8410 | 503 int msgtype = 1, utf8 = 1; /* default to utf8 */ |
6729 | 504 GaimConversation *c = NULL; |
505 GSList *l; | |
506 | |
507 for (l = pkt->hash; l; l = l->next) { | |
508 struct yahoo_pair *pair = l->data; | |
509 | |
510 switch (pair->key) { | |
511 | |
7827 | 512 case 97: |
513 utf8 = strtol(pair->value, NULL, 10); | |
514 break; | |
6729 | 515 case 104: |
8410 | 516 room = yahoo_string_decode(gc, pair->value, TRUE); |
6729 | 517 break; |
518 case 109: | |
519 who = pair->value; | |
520 break; | |
521 case 117: | |
522 msg = pair->value; | |
523 break; | |
524 case 124: | |
525 msgtype = strtol(pair->value, NULL, 10); | |
526 break; | |
527 } | |
528 } | |
529 | |
530 | |
531 c = gaim_find_chat(gc, YAHOO_CHAT_ID); | |
7827 | 532 if (!who || !c) { |
533 if (room) | |
534 g_free(room); | |
6729 | 535 /* we still get messages after we part, funny that */ |
536 return; | |
537 } | |
538 | |
539 if (!msg) { | |
540 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "Got a message packet with no message.\nThis probably means something important, but we're ignoring it.\n"); | |
541 return; | |
542 } | |
7827 | 543 msg2 = yahoo_string_decode(gc, msg, utf8); |
544 msg = yahoo_codes_to_html(msg2); | |
545 g_free(msg2); | |
6729 | 546 |
547 if (msgtype == 2 || msgtype == 3) { | |
548 char *tmp; | |
549 tmp = g_strdup_printf("/me %s", msg); | |
550 g_free(msg); | |
551 msg = tmp; | |
552 } | |
553 | |
554 serv_got_chat_in(gc, YAHOO_CHAT_ID, who, 0, msg, time(NULL)); | |
555 g_free(msg); | |
556 } | |
557 | |
558 void yahoo_process_chat_addinvite(GaimConnection *gc, struct yahoo_packet *pkt) | |
559 { | |
560 GSList *l; | |
561 char *room = NULL; | |
562 char *msg = NULL; | |
563 char *who = NULL; | |
564 | |
565 | |
566 for (l = pkt->hash; l; l = l->next) { | |
567 struct yahoo_pair *pair = l->data; | |
568 | |
569 switch (pair->key) { | |
570 case 104: | |
8410 | 571 room = yahoo_string_decode(gc, pair->value, TRUE); |
6729 | 572 break; |
573 case 129: /* room id? */ | |
574 break; | |
575 case 126: /* ??? */ | |
576 break; | |
577 case 117: | |
7827 | 578 msg = yahoo_string_decode(gc, pair->value, FALSE); |
6729 | 579 break; |
580 case 119: | |
581 who = pair->value; | |
582 break; | |
583 case 118: /* us */ | |
584 break; | |
585 } | |
586 } | |
587 | |
588 if (room && who) { | |
589 GHashTable *components; | |
590 | |
591 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
592 g_hash_table_replace(components, g_strdup("room"), g_strdup(room)); | |
10937 | 593 if (!yahoo_privacy_check(gc, who)) { |
594 gaim_debug_info("yahoo", | |
595 "Invite to room %s from %s has been dropped.\n", room, who); | |
11044
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
596 if (room != NULL) |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
597 g_free(room); |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
598 if (msg != NULL) |
8bf376579177
[gaim-migrate @ 12958]
Richard Laager <rlaager@wiktel.com>
parents:
11043
diff
changeset
|
599 g_free(msg); |
10937 | 600 return; |
601 } | |
6729 | 602 serv_got_chat_invite(gc, room, who, msg, components); |
603 } | |
7827 | 604 if (room) |
605 g_free(room); | |
606 if (msg) | |
607 g_free(msg); | |
6729 | 608 } |
609 | |
610 void yahoo_process_chat_goto(GaimConnection *gc, struct yahoo_packet *pkt) | |
611 { | |
612 if (pkt->status == -1) | |
613 gaim_notify_error(gc, NULL, _("Failed to join buddy in chat"), | |
614 _("Maybe they're not in a chat?")); | |
615 } | |
616 | |
617 | |
618 /* | |
619 * Functions dealing with conferences | |
7827 | 620 * I think conference names are always ascii. |
6729 | 621 */ |
622 | |
9782 | 623 void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who) |
6729 | 624 { |
625 struct yahoo_packet *pkt; | |
626 GList *w; | |
627 | |
9782 | 628 gaim_debug_misc("yahoo", "leaving conference %s\n", room); |
629 | |
6729 | 630 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, 0); |
631 | |
10394 | 632 yahoo_packet_hash_str(pkt, 1, dn); |
6729 | 633 for (w = who; w; w = w->next) { |
9554 | 634 const char *name = gaim_conv_chat_cb_get_name(w->data); |
10394 | 635 yahoo_packet_hash_str(pkt, 3, name); |
6729 | 636 } |
637 | |
10394 | 638 yahoo_packet_hash_str(pkt, 57, room); |
6729 | 639 |
10392 | 640 yahoo_packet_send_and_free(pkt, yd); |
6729 | 641 } |
642 | |
7827 | 643 static int yahoo_conf_send(GaimConnection *gc, const char *dn, const char *room, |
6729 | 644 GList *members, const char *what) |
645 { | |
7827 | 646 struct yahoo_data *yd = gc->proto_data; |
6729 | 647 struct yahoo_packet *pkt; |
648 GList *who; | |
7827 | 649 char *msg, *msg2; |
650 int utf8 = 1; | |
6804 | 651 |
652 msg = yahoo_html_to_codes(what); | |
7827 | 653 msg2 = yahoo_string_encode(gc, msg, &utf8); |
654 | |
6729 | 655 |
656 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YAHOO_STATUS_AVAILABLE, 0); | |
657 | |
10394 | 658 yahoo_packet_hash_str(pkt, 1, dn); |
9554 | 659 for (who = members; who; who = who->next) { |
660 const char *name = gaim_conv_chat_cb_get_name(who->data); | |
10394 | 661 yahoo_packet_hash_str(pkt, 53, name); |
9554 | 662 } |
10394 | 663 yahoo_packet_hash(pkt, "ss", 57, room, 14, msg2); |
7827 | 664 if (utf8) |
10394 | 665 yahoo_packet_hash_str(pkt, 97, "1"); /* utf-8 */ |
6729 | 666 |
10392 | 667 yahoo_packet_send_and_free(pkt, yd); |
6804 | 668 g_free(msg); |
7827 | 669 g_free(msg2); |
6729 | 670 |
671 return 0; | |
672 } | |
673 | |
674 static void yahoo_conf_join(struct yahoo_data *yd, GaimConversation *c, const char *dn, const char *room, | |
675 const char *topic, const char *members) | |
676 { | |
677 struct yahoo_packet *pkt; | |
678 char **memarr = NULL; | |
679 int i; | |
680 | |
681 if (members) | |
682 memarr = g_strsplit(members, "\n", 0); | |
683 | |
684 | |
685 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YAHOO_STATUS_AVAILABLE, 0); | |
686 | |
10394 | 687 yahoo_packet_hash(pkt, "sss", 1, dn, 3, dn, 57, room); |
6729 | 688 if (memarr) { |
689 for(i = 0 ; memarr[i]; i++) { | |
690 if (!strcmp(memarr[i], "") || !strcmp(memarr[i], dn)) | |
691 continue; | |
10394 | 692 yahoo_packet_hash_str(pkt, 3, memarr[i]); |
9846 | 693 gaim_conv_chat_add_user(GAIM_CONV_CHAT(c), memarr[i], NULL, GAIM_CBFLAGS_NONE, TRUE); |
6729 | 694 } |
695 } | |
10392 | 696 yahoo_packet_send_and_free(pkt, yd); |
6729 | 697 |
698 if (memarr) | |
699 g_strfreev(memarr); | |
700 } | |
701 | |
7827 | 702 static void yahoo_conf_invite(GaimConnection *gc, GaimConversation *c, |
6729 | 703 const char *dn, const char *buddy, const char *room, const char *msg) |
704 { | |
7827 | 705 struct yahoo_data *yd = gc->proto_data; |
6729 | 706 struct yahoo_packet *pkt; |
707 GList *members; | |
7827 | 708 char *msg2 = NULL; |
709 | |
710 if (msg) | |
711 msg2 = yahoo_string_encode(gc, msg, NULL); | |
6729 | 712 |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
713 members = gaim_conv_chat_get_users(GAIM_CONV_CHAT(c)); |
6729 | 714 |
715 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, YAHOO_STATUS_AVAILABLE, 0); | |
716 | |
10394 | 717 yahoo_packet_hash(pkt, "sssss", 1, dn, 51, buddy, 57, room, 58, msg?msg2:"", 13, "0"); |
6729 | 718 for(; members; members = members->next) { |
9554 | 719 const char *name = gaim_conv_chat_cb_get_name(members->data); |
720 if (!strcmp(name, dn)) | |
6729 | 721 continue; |
10394 | 722 yahoo_packet_hash(pkt, "ss", 52, name, 53, name); |
6729 | 723 } |
10392 | 724 |
725 yahoo_packet_send_and_free(pkt, yd); | |
726 g_free(msg2); | |
6729 | 727 } |
728 | |
729 /* | |
730 * Functions dealing with chats | |
731 */ | |
732 | |
7186 | 733 static void yahoo_chat_leave(GaimConnection *gc, const char *room, const char *dn, gboolean logout) |
6729 | 734 { |
7186 | 735 struct yahoo_data *yd = gc->proto_data; |
6729 | 736 struct yahoo_packet *pkt; |
7186 | 737 GaimConversation *c; |
7827 | 738 char *eroom; |
8410 | 739 gboolean utf8 = 1; |
7827 | 740 |
9376 | 741 if (yd->wm) { |
742 g_return_if_fail(yd->ycht != NULL); | |
743 | |
744 ycht_chat_leave(yd->ycht, room, logout); | |
745 return; | |
746 } | |
747 | |
8410 | 748 eroom = yahoo_string_encode(gc, room, &utf8); |
6729 | 749 |
750 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATEXIT, YAHOO_STATUS_AVAILABLE, 0); | |
751 | |
10394 | 752 yahoo_packet_hash(pkt, "sss", 104, eroom, 109, dn, 108, "1"); |
753 yahoo_packet_hash_str(pkt, 112, "0"); /* what does this one mean? */ | |
6729 | 754 |
10392 | 755 yahoo_packet_send_and_free(pkt, yd); |
6729 | 756 |
757 yd->in_chat = 0; | |
758 if (yd->chat_name) { | |
759 g_free(yd->chat_name); | |
760 yd->chat_name = NULL; | |
761 } | |
762 | |
7186 | 763 if ((c = gaim_find_chat(gc, YAHOO_CHAT_ID))) |
764 serv_got_chat_left(gc, YAHOO_CHAT_ID); | |
765 | |
766 if (!logout) | |
767 return; | |
768 | |
769 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT, | |
770 YAHOO_STATUS_AVAILABLE, 0); | |
10394 | 771 yahoo_packet_hash_str(pkt, 1, dn); |
10392 | 772 yahoo_packet_send_and_free(pkt, yd); |
7186 | 773 |
774 yd->chat_online = 0; | |
7827 | 775 g_free(eroom); |
6729 | 776 } |
777 | |
6804 | 778 /* borrowed from gtkconv.c */ |
779 static gboolean | |
780 meify(char *message, size_t len) | |
781 { | |
782 /* | |
783 * Read /me-ify: If the message (post-HTML) starts with /me, | |
784 * remove the "/me " part of it (including that space) and return TRUE. | |
785 */ | |
786 char *c; | |
787 gboolean inside_html = 0; | |
788 | |
789 /* Umm.. this would be very bad if this happens. */ | |
790 g_return_val_if_fail(message != NULL, FALSE); | |
791 | |
792 if (len == -1) | |
793 len = strlen(message); | |
794 | |
795 for (c = message; *c != '\0'; c++, len--) { | |
796 if (inside_html) { | |
797 if (*c == '>') | |
798 inside_html = FALSE; | |
799 } | |
800 else { | |
801 if (*c == '<') | |
802 inside_html = TRUE; | |
803 else | |
804 break; | |
805 } | |
806 } | |
807 | |
808 if (*c != '\0' && !g_ascii_strncasecmp(c, "/me ", 4)) { | |
809 memmove(c, c + 4, len - 3); | |
810 | |
811 return TRUE; | |
812 } | |
813 | |
814 return FALSE; | |
815 } | |
816 | |
7827 | 817 static int yahoo_chat_send(GaimConnection *gc, const char *dn, const char *room, const char *what) |
6729 | 818 { |
7827 | 819 struct yahoo_data *yd = gc->proto_data; |
6729 | 820 struct yahoo_packet *pkt; |
821 int me = 0; | |
7827 | 822 char *msg1, *msg2, *room2; |
823 gboolean utf8 = TRUE; | |
6804 | 824 |
9376 | 825 if (yd->wm) { |
826 g_return_val_if_fail(yd->ycht != NULL, 1); | |
827 | |
828 return ycht_chat_send(yd->ycht, room, what); | |
829 } | |
830 | |
6804 | 831 msg1 = g_strdup(what); |
6729 | 832 |
6804 | 833 if (meify(msg1, -1)) |
6729 | 834 me = 1; |
6804 | 835 |
836 msg2 = yahoo_html_to_codes(msg1); | |
837 g_free(msg1); | |
7827 | 838 msg1 = yahoo_string_encode(gc, msg2, &utf8); |
839 g_free(msg2); | |
840 room2 = yahoo_string_encode(gc, room, NULL); | |
6729 | 841 |
842 pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, 0); | |
843 | |
10394 | 844 yahoo_packet_hash(pkt, "sss", 1, dn, 104, room2, 117, msg1); |
6729 | 845 if (me) |
10394 | 846 yahoo_packet_hash_str(pkt, 124, "2"); |
6729 | 847 else |
10394 | 848 yahoo_packet_hash_str(pkt, 124, "1"); |
6729 | 849 /* fixme: what about /think? (124=3) */ |
7827 | 850 if (utf8) |
10394 | 851 yahoo_packet_hash_str(pkt, 97, "1"); |
6729 | 852 |
10392 | 853 yahoo_packet_send_and_free(pkt, yd); |
7827 | 854 g_free(msg1); |
855 g_free(room2); | |
6729 | 856 |
857 return 0; | |
858 } | |
859 | |
7827 | 860 static void yahoo_chat_join(GaimConnection *gc, const char *dn, const char *room, const char *topic) |
6729 | 861 { |
7827 | 862 struct yahoo_data *yd = gc->proto_data; |
6729 | 863 struct yahoo_packet *pkt; |
7827 | 864 char *room2; |
8410 | 865 gboolean utf8 = TRUE; |
7827 | 866 |
9376 | 867 if (yd->wm) { |
868 g_return_if_fail(yd->ycht != NULL); | |
869 | |
870 ycht_chat_join(yd->ycht, room); | |
871 return; | |
872 } | |
873 | |
8410 | 874 /* apparently room names are always utf8, or else always not utf8, |
875 * so we don't have to actually pass the flag in the packet. Or something. */ | |
876 room2 = yahoo_string_encode(gc, room, &utf8); | |
6729 | 877 |
878 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, 0); | |
10394 | 879 yahoo_packet_hash(pkt, "ssss", 1, gaim_connection_get_display_name(gc), |
880 62, "2", 104, room2, 129, "0"); | |
10392 | 881 yahoo_packet_send_and_free(pkt, yd); |
7827 | 882 g_free(room2); |
6729 | 883 } |
884 | |
7827 | 885 static void yahoo_chat_invite(GaimConnection *gc, const char *dn, const char *buddy, |
6729 | 886 const char *room, const char *msg) |
887 { | |
7827 | 888 struct yahoo_data *yd = gc->proto_data; |
6729 | 889 struct yahoo_packet *pkt; |
7827 | 890 char *room2, *msg2 = NULL; |
8410 | 891 gboolean utf8 = TRUE; |
6729 | 892 |
9376 | 893 if (yd->wm) { |
894 g_return_if_fail(yd->ycht != NULL); | |
895 | |
896 ycht_chat_send_invite(yd->ycht, room, buddy, msg); | |
897 return; | |
898 } | |
899 | |
8410 | 900 room2 = yahoo_string_encode(gc, room, &utf8); |
7827 | 901 if (msg) |
902 msg2 = yahoo_string_encode(gc, msg, NULL); | |
10394 | 903 |
6729 | 904 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATADDINVITE, YAHOO_STATUS_AVAILABLE, 0); |
10394 | 905 yahoo_packet_hash(pkt, "sssss", 1, dn, 118, buddy, 104, room2, 117, (msg2?msg2:""), 129, "0"); |
10392 | 906 yahoo_packet_send_and_free(pkt, yd); |
7827 | 907 |
908 g_free(room2); | |
10392 | 909 g_free(msg2); |
6729 | 910 } |
911 | |
912 void yahoo_chat_goto(GaimConnection *gc, const char *name) | |
913 { | |
914 struct yahoo_data *yd; | |
915 struct yahoo_packet *pkt; | |
916 | |
917 yd = gc->proto_data; | |
918 | |
9376 | 919 if (yd->wm) { |
920 g_return_if_fail(yd->ycht != NULL); | |
921 | |
922 ycht_chat_goto_user(yd->ycht, name); | |
923 return; | |
924 } | |
925 | |
6729 | 926 if (!yd->chat_online) |
927 yahoo_chat_online(gc); | |
928 | |
929 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, 0); | |
10394 | 930 yahoo_packet_hash(pkt, "sss", 109, name, 1, gaim_connection_get_display_name(gc), 62, "2"); |
10392 | 931 yahoo_packet_send_and_free(pkt, yd); |
6729 | 932 } |
933 /* | |
934 * These are the functions registered with the core | |
935 * which get called for both chats and conferences. | |
936 */ | |
937 | |
938 void yahoo_c_leave(GaimConnection *gc, int id) | |
939 { | |
940 struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data; | |
941 GaimConversation *c; | |
942 | |
943 if (!yd) | |
944 return; | |
945 | |
946 | |
947 c = gaim_find_chat(gc, id); | |
948 if (!c) | |
949 return; | |
950 | |
951 if (id != YAHOO_CHAT_ID) { | |
952 yahoo_conf_leave(yd, gaim_conversation_get_name(c), | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
953 gaim_connection_get_display_name(gc), gaim_conv_chat_get_users(GAIM_CONV_CHAT(c))); |
6729 | 954 yd->confs = g_slist_remove(yd->confs, c); |
955 } else { | |
7186 | 956 yahoo_chat_leave(gc, gaim_conversation_get_name(c), gaim_connection_get_display_name(gc), TRUE); |
6729 | 957 } |
958 | |
959 serv_got_chat_left(gc, id); | |
960 } | |
961 | |
962 int yahoo_c_send(GaimConnection *gc, int id, const char *what) | |
963 { | |
964 GaimConversation *c; | |
965 int ret; | |
966 struct yahoo_data *yd; | |
967 | |
968 yd = (struct yahoo_data *) gc->proto_data; | |
969 if (!yd) | |
970 return -1; | |
971 | |
972 c = gaim_find_chat(gc, id); | |
973 if (!c) | |
974 return -1; | |
975 | |
976 if (id != YAHOO_CHAT_ID) { | |
7827 | 977 ret = yahoo_conf_send(gc, gaim_connection_get_display_name(gc), |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
978 gaim_conversation_get_name(c), gaim_conv_chat_get_users(GAIM_CONV_CHAT(c)), what); |
6729 | 979 } else { |
7827 | 980 ret = yahoo_chat_send(gc, gaim_connection_get_display_name(gc), |
6804 | 981 gaim_conversation_get_name(c), what); |
6729 | 982 if (!ret) |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
983 serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(c)), |
6729 | 984 gaim_connection_get_display_name(gc), 0, what, time(NULL)); |
985 } | |
986 return ret; | |
987 } | |
988 | |
989 GList *yahoo_c_info(GaimConnection *gc) | |
990 { | |
991 GList *m = NULL; | |
992 struct proto_chat_entry *pce; | |
993 | |
994 pce = g_new0(struct proto_chat_entry, 1); | |
7841 | 995 pce->label = _("_Room:"); |
6729 | 996 pce->identifier = "room"; |
10954 | 997 pce->required = TRUE; |
6729 | 998 m = g_list_append(m, pce); |
999 | |
1000 return m; | |
1001 } | |
1002 | |
9768 | 1003 GHashTable *yahoo_c_info_defaults(GaimConnection *gc, const char *chat_name) |
1004 { | |
1005 GHashTable *defaults; | |
1006 | |
1007 defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); | |
1008 | |
1009 if (chat_name != NULL) | |
1010 g_hash_table_insert(defaults, "room", g_strdup(chat_name)); | |
1011 | |
1012 return defaults; | |
1013 } | |
1014 | |
9917 | 1015 char *yahoo_get_chat_name(GHashTable *data) |
1016 { | |
1017 return g_strdup(g_hash_table_lookup(data, "room")); | |
1018 } | |
1019 | |
6729 | 1020 void yahoo_c_join(GaimConnection *gc, GHashTable *data) |
1021 { | |
1022 struct yahoo_data *yd; | |
1023 char *room, *topic, *members, *type; | |
1024 int id; | |
1025 GaimConversation *c; | |
1026 | |
1027 yd = (struct yahoo_data *) gc->proto_data; | |
1028 if (!yd) | |
1029 return; | |
1030 | |
1031 room = g_hash_table_lookup(data, "room"); | |
1032 if (!room) | |
1033 return; | |
1034 | |
1035 topic = g_hash_table_lookup(data, "topic"); | |
1036 if (!topic) | |
1037 topic = ""; | |
1038 | |
1039 members = g_hash_table_lookup(data, "members"); | |
1040 | |
1041 | |
1042 if ((type = g_hash_table_lookup(data, "type")) && !strcmp(type, "Conference")) { | |
1043 id = yd->conf_id++; | |
1044 c = serv_got_joined_chat(gc, id, room); | |
1045 yd->confs = g_slist_prepend(yd->confs, c); | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6804
diff
changeset
|
1046 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(c), gaim_connection_get_display_name(gc), topic); |
6729 | 1047 yahoo_conf_join(yd, c, gaim_connection_get_display_name(gc), room, topic, members); |
1048 return; | |
1049 } else { | |
1050 if (yd->in_chat) | |
7186 | 1051 yahoo_chat_leave(gc, room, |
1052 gaim_connection_get_display_name(gc), | |
1053 FALSE); | |
6729 | 1054 if (!yd->chat_online) |
1055 yahoo_chat_online(gc); | |
7827 | 1056 yahoo_chat_join(gc, gaim_connection_get_display_name(gc), room, topic); |
6729 | 1057 return; |
1058 } | |
1059 } | |
1060 | |
1061 void yahoo_c_invite(GaimConnection *gc, int id, const char *msg, const char *name) | |
1062 { | |
1063 GaimConversation *c; | |
1064 | |
1065 c = gaim_find_chat(gc, id); | |
1066 if (!c || !c->name) | |
1067 return; | |
1068 | |
1069 if (id != YAHOO_CHAT_ID) { | |
7827 | 1070 yahoo_conf_invite(gc, c, gaim_connection_get_display_name(gc), name, |
6729 | 1071 gaim_conversation_get_name(c), msg); |
1072 } else { | |
7827 | 1073 yahoo_chat_invite(gc, gaim_connection_get_display_name(gc), name, |
6729 | 1074 gaim_conversation_get_name(c), msg); |
1075 } | |
1076 } | |
1077 | |
8113 | 1078 |
1079 struct yahoo_roomlist { | |
1080 int fd; | |
1081 int inpa; | |
1082 guchar *rxqueue; | |
1083 int rxlen; | |
1084 gboolean started; | |
1085 char *path; | |
1086 char *host; | |
1087 GaimRoomlist *list; | |
1088 GaimRoomlistRoom *cat; | |
1089 GaimRoomlistRoom *ucat; | |
1090 GMarkupParseContext *parse; | |
1091 | |
1092 }; | |
1093 | |
1094 static void yahoo_roomlist_destroy(struct yahoo_roomlist *yrl) | |
1095 { | |
1096 if (yrl->inpa) | |
1097 gaim_input_remove(yrl->inpa); | |
1098 if (yrl->rxqueue) | |
1099 g_free(yrl->rxqueue); | |
1100 if (yrl->path) | |
1101 g_free(yrl->path); | |
1102 if (yrl->host) | |
1103 g_free(yrl->host); | |
1104 if (yrl->parse) | |
1105 g_markup_parse_context_free(yrl->parse); | |
10504 | 1106 g_free(yrl); |
8113 | 1107 } |
1108 | |
1109 enum yahoo_room_type { | |
1110 yrt_yahoo, | |
1111 yrt_user, | |
1112 }; | |
1113 | |
1114 struct yahoo_chatxml_state { | |
1115 GaimRoomlist *list; | |
1116 struct yahoo_roomlist *yrl; | |
1117 GQueue *q; | |
1118 struct { | |
1119 enum yahoo_room_type type; | |
1120 char *name; | |
1121 char *topic; | |
1122 char *id; | |
1123 int users, voices, webcams; | |
1124 } room; | |
1125 }; | |
1126 | |
1127 struct yahoo_lobby { | |
1128 int count, users, voices, webcams; | |
1129 }; | |
1130 | |
1131 static struct yahoo_chatxml_state *yahoo_chatxml_state_new(GaimRoomlist *list, struct yahoo_roomlist *yrl) | |
1132 { | |
1133 struct yahoo_chatxml_state *s; | |
1134 | |
1135 s = g_new0(struct yahoo_chatxml_state, 1); | |
1136 | |
1137 s->list = list; | |
1138 s->yrl = yrl; | |
1139 s->q = g_queue_new(); | |
1140 | |
1141 return s; | |
1142 } | |
1143 | |
1144 static void yahoo_chatxml_state_destroy(struct yahoo_chatxml_state *s) | |
1145 { | |
1146 g_queue_free(s->q); | |
1147 if (s->room.name) | |
1148 g_free(s->room.name); | |
1149 if (s->room.topic) | |
1150 g_free(s->room.topic); | |
1151 if (s->room.id) | |
1152 g_free(s->room.id); | |
1153 g_free(s); | |
1154 } | |
1155 | |
1156 static void yahoo_chatlist_start_element(GMarkupParseContext *context, const gchar *ename, | |
1157 const gchar **anames, const gchar **avalues, | |
1158 gpointer user_data, GError **error) | |
1159 { | |
1160 struct yahoo_chatxml_state *s = user_data; | |
1161 GaimRoomlist *list = s->list; | |
1162 GaimRoomlistRoom *r; | |
1163 GaimRoomlistRoom *parent; | |
1164 int i; | |
1165 | |
1166 if (!strcmp(ename, "category")) { | |
1167 const gchar *name = NULL, *id = NULL; | |
1168 | |
1169 for (i = 0; anames[i]; i++) { | |
1170 if (!strcmp(anames[i], "id")) | |
1171 id = avalues[i]; | |
1172 if (!strcmp(anames[i], "name")) | |
1173 name = avalues[i]; | |
1174 } | |
1175 if (!name || !id) | |
1176 return; | |
1177 | |
1178 parent = g_queue_peek_head(s->q); | |
8584 | 1179 r = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATEGORY, name, parent); |
8113 | 1180 gaim_roomlist_room_add_field(list, r, (gpointer)name); |
1181 gaim_roomlist_room_add_field(list, r, (gpointer)id); | |
1182 gaim_roomlist_room_add(list, r); | |
1183 g_queue_push_head(s->q, r); | |
1184 } else if (!strcmp(ename, "room")) { | |
1185 s->room.users = s->room.voices = s->room.webcams = 0; | |
1186 | |
1187 for (i = 0; anames[i]; i++) { | |
1188 if (!strcmp(anames[i], "id")) { | |
1189 if (s->room.id) | |
1190 g_free(s->room.id); | |
1191 s->room.id = g_strdup(avalues[i]); | |
1192 } else if (!strcmp(anames[i], "name")) { | |
1193 if (s->room.name) | |
1194 g_free(s->room.name); | |
1195 s->room.name = g_strdup(avalues[i]); | |
1196 } else if (!strcmp(anames[i], "topic")) { | |
1197 if (s->room.topic) | |
1198 g_free(s->room.topic); | |
1199 s->room.topic = g_strdup(avalues[i]); | |
1200 } else if (!strcmp(anames[i], "type")) { | |
1201 if (!strcmp("yahoo", avalues[i])) | |
1202 s->room.type = yrt_yahoo; | |
1203 else | |
1204 s->room.type = yrt_user; | |
1205 } | |
1206 } | |
1207 | |
1208 } else if (!strcmp(ename, "lobby")) { | |
1209 struct yahoo_lobby *lob = g_new0(struct yahoo_lobby, 1); | |
1210 | |
1211 for (i = 0; anames[i]; i++) { | |
1212 if (!strcmp(anames[i], "count")) { | |
1213 lob->count = strtol(avalues[i], NULL, 10); | |
1214 } else if (!strcmp(anames[i], "users")) { | |
1215 s->room.users += lob->users = strtol(avalues[i], NULL, 10); | |
1216 } else if (!strcmp(anames[i], "voices")) { | |
1217 s->room.voices += lob->voices = strtol(avalues[i], NULL, 10); | |
1218 } else if (!strcmp(anames[i], "webcams")) { | |
1219 s->room.webcams += lob->webcams = strtol(avalues[i], NULL, 10); | |
1220 } | |
1221 } | |
1222 | |
1223 g_queue_push_head(s->q, lob); | |
1224 } | |
1225 | |
1226 } | |
1227 | |
1228 static void yahoo_chatlist_end_element(GMarkupParseContext *context, const gchar *ename, | |
1229 gpointer user_data, GError **error) | |
1230 { | |
1231 struct yahoo_chatxml_state *s = user_data; | |
1232 | |
1233 if (!strcmp(ename, "category")) { | |
1234 g_queue_pop_head(s->q); | |
1235 } else if (!strcmp(ename, "room")) { | |
1236 struct yahoo_lobby *lob; | |
1237 GaimRoomlistRoom *r, *l; | |
1238 | |
1239 if (s->room.type == yrt_yahoo) | |
8584 | 1240 r = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATEGORY|GAIM_ROOMLIST_ROOMTYPE_ROOM, |
8113 | 1241 s->room.name, s->yrl->cat); |
1242 else | |
8584 | 1243 r = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATEGORY|GAIM_ROOMLIST_ROOMTYPE_ROOM, |
8113 | 1244 s->room.name, s->yrl->ucat); |
1245 | |
1246 gaim_roomlist_room_add_field(s->list, r, s->room.name); | |
1247 gaim_roomlist_room_add_field(s->list, r, s->room.id); | |
1248 gaim_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.users)); | |
1249 gaim_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.voices)); | |
1250 gaim_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.webcams)); | |
1251 gaim_roomlist_room_add_field(s->list, r, s->room.topic); | |
1252 gaim_roomlist_room_add(s->list, r); | |
1253 | |
1254 while ((lob = g_queue_pop_head(s->q))) { | |
1255 char *name = g_strdup_printf("%s:%d", s->room.name, lob->count); | |
1256 l = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_ROOM, name, r); | |
1257 | |
1258 gaim_roomlist_room_add_field(s->list, l, name); | |
1259 gaim_roomlist_room_add_field(s->list, l, s->room.id); | |
1260 gaim_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->users)); | |
1261 gaim_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->voices)); | |
1262 gaim_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->webcams)); | |
1263 gaim_roomlist_room_add_field(s->list, l, s->room.topic); | |
1264 gaim_roomlist_room_add(s->list, l); | |
1265 | |
1266 g_free(name); | |
1267 g_free(lob); | |
1268 } | |
1269 | |
1270 } | |
1271 | |
1272 } | |
1273 | |
1274 static GMarkupParser parser = { | |
1275 yahoo_chatlist_start_element, | |
1276 yahoo_chatlist_end_element, | |
1277 NULL, | |
1278 NULL, | |
1279 NULL | |
1280 }; | |
1281 | |
1282 static void yahoo_roomlist_cleanup(GaimRoomlist *list, struct yahoo_roomlist *yrl) | |
1283 { | |
1284 gaim_roomlist_set_in_progress(list, FALSE); | |
1285 | |
1286 if (yrl) { | |
1287 list->proto_data = g_list_remove(list->proto_data, yrl); | |
1288 yahoo_roomlist_destroy(yrl); | |
1289 } | |
1290 | |
1291 gaim_roomlist_unref(list); | |
1292 } | |
1293 | |
1294 static void yahoo_roomlist_pending(gpointer data, gint source, GaimInputCondition cond) | |
1295 { | |
1296 struct yahoo_roomlist *yrl = data; | |
1297 GaimRoomlist *list = yrl->list; | |
1298 char buf[1024]; | |
1299 int len; | |
1300 guchar *start; | |
1301 struct yahoo_chatxml_state *s; | |
1302 | |
1303 len = read(yrl->fd, buf, sizeof(buf)); | |
1304 | |
1305 if (len <= 0) { | |
1306 if (yrl->parse) | |
1307 g_markup_parse_context_end_parse(yrl->parse, NULL); | |
1308 yahoo_roomlist_cleanup(list, yrl); | |
1309 return; | |
1310 } | |
1311 | |
1312 | |
1313 yrl->rxqueue = g_realloc(yrl->rxqueue, len + yrl->rxlen); | |
1314 memcpy(yrl->rxqueue + yrl->rxlen, buf, len); | |
1315 yrl->rxlen += len; | |
1316 | |
1317 if (!yrl->started) { | |
1318 yrl->started = TRUE; | |
11318 | 1319 start = (guchar *)g_strstr_len((char *)yrl->rxqueue, yrl->rxlen, "\r\n\r\n"); |
8113 | 1320 if (!start || (start - yrl->rxqueue + 4) >= yrl->rxlen) |
1321 return; | |
1322 start += 4; | |
1323 } else { | |
1324 start = yrl->rxqueue; | |
1325 } | |
1326 | |
1327 if (yrl->parse == NULL) { | |
1328 s = yahoo_chatxml_state_new(list, yrl); | |
1329 yrl->parse = g_markup_parse_context_new(&parser, 0, s, | |
1330 (GDestroyNotify)yahoo_chatxml_state_destroy); | |
1331 } | |
1332 | |
11318 | 1333 if (!g_markup_parse_context_parse(yrl->parse, (char *)start, (yrl->rxlen - (start - yrl->rxqueue)), NULL)) { |
8113 | 1334 |
1335 yahoo_roomlist_cleanup(list, yrl); | |
1336 return; | |
1337 } | |
1338 | |
1339 yrl->rxlen = 0; | |
1340 } | |
1341 | |
1342 static void yahoo_roomlist_got_connected(gpointer data, gint source, GaimInputCondition cond) | |
1343 { | |
1344 struct yahoo_roomlist *yrl = data; | |
1345 GaimRoomlist *list = yrl->list; | |
1346 char *buf, *cookie; | |
1347 struct yahoo_data *yd = gaim_account_get_connection(list->account)->proto_data; | |
1348 | |
1349 if (source < 0) { | |
1350 gaim_notify_error(gaim_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed.")); | |
1351 yahoo_roomlist_cleanup(list, yrl); | |
1352 return; | |
1353 } | |
1354 | |
1355 yrl->fd = source; | |
1356 | |
1357 cookie = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t); | |
10575 | 1358 buf = g_strdup_printf("GET http://%s/%s HTTP/1.0\r\nHost: %s\r\nCookie: %s\r\n\r\n", |
1359 yrl->host, yrl->path, yrl->host, cookie); | |
8113 | 1360 write(yrl->fd, buf, strlen(buf)); |
1361 g_free(cookie); | |
1362 g_free(buf); | |
1363 yrl->inpa = gaim_input_add(yrl->fd, GAIM_INPUT_READ, yahoo_roomlist_pending, yrl); | |
1364 | |
1365 } | |
1366 | |
1367 GaimRoomlist *yahoo_roomlist_get_list(GaimConnection *gc) | |
1368 { | |
1369 struct yahoo_roomlist *yrl; | |
1370 GaimRoomlist *rl; | |
1371 char *url; | |
1372 GList *fields = NULL; | |
1373 GaimRoomlistField *f; | |
1374 | |
11043
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1375 if (YAHOO_ROOMLIST_LOCALE) { |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1376 url = g_strdup_printf("%s?chatcat=0&intl=%s", |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1377 gaim_account_get_string(gaim_connection_get_account(gc), |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1378 "room_list", YAHOO_ROOMLIST_URL), |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1379 gaim_account_get_string(gaim_connection_get_account(gc), |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1380 "room_list_locale", YAHOO_ROOMLIST_LOCALE)); |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1381 } else { |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1382 url = g_strdup_printf("%s?chatcat=0", |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1383 gaim_account_get_string(gaim_connection_get_account(gc), |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1384 "room_list", YAHOO_ROOMLIST_URL)); |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1385 } |
8113 | 1386 |
1387 yrl = g_new0(struct yahoo_roomlist, 1); | |
1388 rl = gaim_roomlist_new(gaim_connection_get_account(gc)); | |
1389 yrl->list = rl; | |
1390 | |
9227
9171e528d7e5
[gaim-migrate @ 10023]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1391 gaim_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL); |
8113 | 1392 g_free(url); |
1393 | |
1394 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "room", TRUE); | |
1395 fields = g_list_append(fields, f); | |
1396 | |
1397 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "id", TRUE); | |
1398 fields = g_list_append(fields, f); | |
1399 | |
1400 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, _("Users"), "users", FALSE); | |
1401 fields = g_list_append(fields, f); | |
1402 | |
1403 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, _("Voices"), "voices", FALSE); | |
1404 fields = g_list_append(fields, f); | |
1405 | |
1406 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, _("Webcams"), "webcams", FALSE); | |
1407 fields = g_list_append(fields, f); | |
1408 | |
1409 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, _("Topic"), "topic", FALSE); | |
1410 fields = g_list_append(fields, f); | |
1411 | |
1412 gaim_roomlist_set_fields(rl, fields); | |
1413 | |
1414 if (gaim_proxy_connect(gaim_connection_get_account(gc), | |
1415 yrl->host, 80, yahoo_roomlist_got_connected, yrl) != 0) | |
1416 { | |
1417 gaim_notify_error(gc, NULL, _("Connection problem"), _("Unable to fetch room list.")); | |
1418 yahoo_roomlist_cleanup(rl, yrl); | |
1419 return NULL; | |
1420 } | |
1421 | |
1422 rl->proto_data = g_list_append(rl->proto_data, yrl); | |
1423 | |
1424 gaim_roomlist_set_in_progress(rl, TRUE); | |
1425 return rl; | |
1426 } | |
1427 | |
1428 void yahoo_roomlist_cancel(GaimRoomlist *list) | |
1429 { | |
1430 GList *l, *k; | |
1431 | |
1432 k = l = list->proto_data; | |
1433 list->proto_data = NULL; | |
1434 | |
1435 gaim_roomlist_set_in_progress(list, FALSE); | |
1436 | |
1437 for (; l; l = l->next) { | |
1438 yahoo_roomlist_destroy(l->data); | |
10647
7d13c04387ad
[gaim-migrate @ 12163]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10575
diff
changeset
|
1439 gaim_roomlist_unref(list); |
8113 | 1440 } |
1441 g_list_free(k); | |
1442 } | |
1443 | |
8584 | 1444 void yahoo_roomlist_expand_category(GaimRoomlist *list, GaimRoomlistRoom *category) |
8113 | 1445 { |
1446 struct yahoo_roomlist *yrl; | |
1447 char *url; | |
1448 char *id; | |
1449 | |
8584 | 1450 if (category->type != GAIM_ROOMLIST_ROOMTYPE_CATEGORY) |
8113 | 1451 return; |
1452 | |
8584 | 1453 if (!(id = g_list_nth_data(category->fields, 1))) { |
8113 | 1454 gaim_roomlist_set_in_progress(list, FALSE); |
1455 return; | |
1456 } | |
1457 | |
11043
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1458 if (YAHOO_ROOMLIST_LOCALE) { |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1459 url = g_strdup_printf("%s?chatroom_%s=0&intl=%s", |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1460 gaim_account_get_string(list->account,"room_list", |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1461 YAHOO_ROOMLIST_URL), id, gaim_account_get_string(list->account, |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1462 "room_list_locale", YAHOO_ROOMLIST_LOCALE)); |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1463 } else { |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1464 url = g_strdup_printf("%s?chatroom_%s=0", |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1465 gaim_account_get_string(list->account,"room_list", |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1466 YAHOO_ROOMLIST_URL), id); |
629cbfd1ed6d
[gaim-migrate @ 12957]
Richard Laager <rlaager@wiktel.com>
parents:
10954
diff
changeset
|
1467 } |
8113 | 1468 |
1469 yrl = g_new0(struct yahoo_roomlist, 1); | |
1470 yrl->list = list; | |
8584 | 1471 yrl->cat = category; |
8113 | 1472 list->proto_data = g_list_append(list->proto_data, yrl); |
1473 | |
9227
9171e528d7e5
[gaim-migrate @ 10023]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1474 gaim_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL); |
8113 | 1475 g_free(url); |
1476 | |
8584 | 1477 yrl->ucat = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat); |
8113 | 1478 gaim_roomlist_room_add(list, yrl->ucat); |
1479 | |
1480 if (gaim_proxy_connect(list->account, | |
1481 yrl->host, 80, yahoo_roomlist_got_connected, yrl) != 0) | |
1482 { | |
1483 gaim_notify_error(gaim_account_get_connection(list->account), | |
1484 NULL, _("Connection problem"), _("Unable to fetch room list.")); | |
10647
7d13c04387ad
[gaim-migrate @ 12163]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10575
diff
changeset
|
1485 gaim_roomlist_ref(list); |
8113 | 1486 yahoo_roomlist_cleanup(list, yrl); |
1487 return; | |
1488 } | |
1489 | |
1490 gaim_roomlist_set_in_progress(list, TRUE); | |
1491 gaim_roomlist_ref(list); | |
1492 } |