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