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