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