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