Mercurial > pidgin
annotate src/protocols/jabber/chat.c @ 9173:b6051a2d3bb5
[gaim-migrate @ 9962]
Robert T(something) noticed that we're not being a good jabber citizen, and that his server is not XMPP compliant. This fixes our end of that. Thanks Robert!
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Fri, 04 Jun 2004 00:02:25 +0000 |
parents | f65be7c97812 |
children | 8b2451878e26 |
rev | line source |
---|---|
7014 | 1 /* |
2 * gaim - Jabber Protocol Plugin | |
3 * | |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 #include "internal.h" | |
22 #include "debug.h" | |
23 #include "multi.h" /* for proto_chat_entry */ | |
7310 | 24 #include "notify.h" |
8113 | 25 #include "request.h" |
26 #include "roomlist.h" | |
7971 | 27 #include "util.h" |
7014 | 28 |
29 #include "chat.h" | |
7895 | 30 #include "iq.h" |
7014 | 31 #include "message.h" |
7073 | 32 #include "presence.h" |
7923 | 33 #include "xdata.h" |
7014 | 34 |
35 GList *jabber_chat_info(GaimConnection *gc) | |
36 { | |
37 GList *m = NULL; | |
38 struct proto_chat_entry *pce; | |
39 JabberStream *js = gc->proto_data; | |
40 | |
41 pce = g_new0(struct proto_chat_entry, 1); | |
7841 | 42 pce->label = _("_Room:"); |
7014 | 43 pce->identifier = "room"; |
44 m = g_list_append(m, pce); | |
45 | |
46 pce = g_new0(struct proto_chat_entry, 1); | |
7841 | 47 pce->label = _("_Server:"); |
7014 | 48 pce->identifier = "server"; |
8043 | 49 pce->def = js->chat_servers ? js->chat_servers->data : "conference.jabber.org"; |
7014 | 50 m = g_list_append(m, pce); |
51 | |
52 pce = g_new0(struct proto_chat_entry, 1); | |
7841 | 53 pce->label = _("_Handle:"); |
7014 | 54 pce->identifier = "handle"; |
55 pce->def = js->user->node; | |
56 m = g_list_append(m, pce); | |
57 | |
58 pce = g_new0(struct proto_chat_entry, 1); | |
7841 | 59 pce->label = _("_Password:"); |
7014 | 60 pce->identifier = "password"; |
61 pce->secret = TRUE; | |
62 m = g_list_append(m, pce); | |
63 | |
64 return m; | |
65 } | |
66 | |
67 JabberChat *jabber_chat_find(JabberStream *js, const char *room, | |
68 const char *server) | |
69 { | |
70 JabberChat *chat; | |
71 char *room_jid; | |
72 | |
73 room_jid = g_strdup_printf("%s@%s", room, server); | |
74 | |
7322 | 75 chat = g_hash_table_lookup(js->chats, jabber_normalize(NULL, room_jid)); |
7014 | 76 g_free(room_jid); |
77 | |
78 return chat; | |
79 } | |
80 | |
81 struct _find_by_id_data { | |
82 int id; | |
83 JabberChat *chat; | |
84 }; | |
85 | |
86 void find_by_id_foreach_cb(gpointer key, gpointer value, gpointer user_data) | |
87 { | |
88 JabberChat *chat = value; | |
89 struct _find_by_id_data *fbid = user_data; | |
90 | |
91 if(chat->id == fbid->id) | |
92 fbid->chat = chat; | |
93 } | |
94 | |
95 JabberChat *jabber_chat_find_by_id(JabberStream *js, int id) | |
96 { | |
97 JabberChat *chat; | |
98 struct _find_by_id_data *fbid = g_new0(struct _find_by_id_data, 1); | |
7073 | 99 fbid->id = id; |
7014 | 100 g_hash_table_foreach(js->chats, find_by_id_foreach_cb, fbid); |
101 chat = fbid->chat; | |
102 g_free(fbid); | |
103 return chat; | |
104 } | |
105 | |
9130 | 106 JabberChat *jabber_chat_find_by_conv(GaimConversation *conv) |
107 { | |
108 GaimAccount *account = gaim_conversation_get_account(conv); | |
109 GaimConnection *gc = gaim_account_get_connection(account); | |
110 JabberStream *js = gc->proto_data; | |
111 int id = gaim_conv_chat_get_id(GAIM_CONV_CHAT(conv)); | |
112 | |
113 return jabber_chat_find_by_id(js, id); | |
114 } | |
115 | |
7014 | 116 void jabber_chat_invite(GaimConnection *gc, int id, const char *msg, |
117 const char *name) | |
118 { | |
119 JabberStream *js = gc->proto_data; | |
120 JabberChat *chat; | |
121 xmlnode *message, *body, *x, *invite; | |
122 char *room_jid; | |
123 | |
124 chat = jabber_chat_find_by_id(js, id); | |
125 if(!chat) | |
126 return; | |
127 | |
128 message = xmlnode_new("message"); | |
129 | |
130 room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); | |
131 | |
132 if(chat->muc) { | |
133 xmlnode_set_attrib(message, "to", room_jid); | |
134 x = xmlnode_new_child(message, "x"); | |
135 xmlnode_set_attrib(x, "xmlns", "http://jabber.org/protocol/muc#user"); | |
136 invite = xmlnode_new_child(x, "invite"); | |
137 xmlnode_set_attrib(invite, "to", name); | |
138 body = xmlnode_new_child(invite, "reason"); | |
139 xmlnode_insert_data(body, msg, -1); | |
140 } else { | |
141 xmlnode_set_attrib(message, "to", name); | |
142 body = xmlnode_new_child(message, "body"); | |
143 xmlnode_insert_data(body, msg, -1); | |
144 x = xmlnode_new_child(message, "x"); | |
145 xmlnode_set_attrib(x, "jid", room_jid); | |
146 xmlnode_set_attrib(x, "xmlns", "jabber:x:conference"); | |
147 } | |
148 | |
149 jabber_send(js, message); | |
150 xmlnode_free(message); | |
151 g_free(room_jid); | |
152 } | |
153 | |
9152 | 154 void jabber_chat_member_free(JabberChatMember *jcm); |
155 | |
7014 | 156 void jabber_chat_join(GaimConnection *gc, GHashTable *data) |
157 { | |
158 JabberChat *chat; | |
159 char *room, *server, *handle, *passwd; | |
160 xmlnode *presence, *x; | |
7262 | 161 char *tmp, *room_jid, *full_jid; |
7014 | 162 JabberStream *js = gc->proto_data; |
163 | |
164 room = g_hash_table_lookup(data, "room"); | |
165 server = g_hash_table_lookup(data, "server"); | |
166 handle = g_hash_table_lookup(data, "handle"); | |
167 passwd = g_hash_table_lookup(data, "password"); | |
168 | |
8113 | 169 if(!room || !server) |
7014 | 170 return; |
171 | |
8113 | 172 if(!handle) |
173 handle = js->user->node; | |
174 | |
7310 | 175 if(!jabber_nodeprep_validate(room)) { |
176 char *buf = g_strdup_printf(_("%s is not a valid room name"), room); | |
177 gaim_notify_error(gc, _("Invalid Room Name"), _("Invalid Room Name"), | |
178 buf); | |
179 g_free(buf); | |
180 return; | |
181 } else if(!jabber_nameprep_validate(server)) { | |
182 char *buf = g_strdup_printf(_("%s is not a valid server name"), server); | |
183 gaim_notify_error(gc, _("Invalid Server Name"), | |
184 _("Invalid Server Name"), buf); | |
185 g_free(buf); | |
186 return; | |
187 } else if(!jabber_resourceprep_validate(handle)) { | |
188 char *buf = g_strdup_printf(_("%s is not a valid room handle"), handle); | |
189 gaim_notify_error(gc, _("Invalid Room Handle"), | |
190 _("Invalid Room Handle"), buf); | |
191 } | |
192 | |
7014 | 193 if(jabber_chat_find(js, room, server)) |
194 return; | |
195 | |
7262 | 196 tmp = g_strdup_printf("%s@%s", room, server); |
7322 | 197 room_jid = g_strdup(jabber_normalize(NULL, tmp)); |
7262 | 198 g_free(tmp); |
7014 | 199 |
200 chat = g_new0(JabberChat, 1); | |
201 chat->js = gc->proto_data; | |
202 | |
203 chat->room = g_strdup(room); | |
204 chat->server = g_strdup(server); | |
8400 | 205 chat->handle = g_strdup(handle); |
7014 | 206 |
9152 | 207 chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, |
208 (GDestroyNotify)jabber_chat_member_free); | |
209 | |
7014 | 210 g_hash_table_insert(js->chats, room_jid, chat); |
211 | |
7073 | 212 presence = jabber_presence_create(gc->away_state, gc->away); |
7014 | 213 full_jid = g_strdup_printf("%s/%s", room_jid, handle); |
214 xmlnode_set_attrib(presence, "to", full_jid); | |
215 g_free(full_jid); | |
216 | |
217 x = xmlnode_new_child(presence, "x"); | |
218 xmlnode_set_attrib(x, "xmlns", "http://jabber.org/protocol/muc"); | |
219 | |
220 if(passwd && *passwd) { | |
221 xmlnode *password = xmlnode_new_child(x, "password"); | |
222 xmlnode_insert_data(password, passwd, -1); | |
223 } | |
224 | |
225 jabber_send(js, presence); | |
226 xmlnode_free(presence); | |
227 } | |
228 | |
229 void jabber_chat_leave(GaimConnection *gc, int id) | |
230 { | |
231 JabberStream *js = gc->proto_data; | |
232 JabberChat *chat = jabber_chat_find_by_id(js, id); | |
7974 | 233 |
7014 | 234 |
235 if(!chat) | |
236 return; | |
237 | |
7974 | 238 jabber_chat_part(chat, NULL); |
9152 | 239 |
240 chat->conv = NULL; | |
7014 | 241 } |
242 | |
243 void jabber_chat_destroy(JabberChat *chat) | |
244 { | |
245 JabberStream *js = chat->js; | |
246 char *room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); | |
247 | |
7322 | 248 g_hash_table_remove(js->chats, jabber_normalize(NULL, room_jid)); |
7014 | 249 g_free(room_jid); |
8396 | 250 } |
251 | |
252 void jabber_chat_free(JabberChat *chat) | |
253 { | |
254 if(chat->config_dialog_handle) | |
255 gaim_request_close(chat->config_dialog_type, chat->config_dialog_handle); | |
7014 | 256 |
257 g_free(chat->room); | |
258 g_free(chat->server); | |
259 g_free(chat); | |
260 } | |
261 | |
262 gboolean jabber_chat_find_buddy(GaimConversation *conv, const char *name) | |
263 { | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
7073
diff
changeset
|
264 GList *m = gaim_conv_chat_get_users(GAIM_CONV_CHAT(conv)); |
7014 | 265 |
266 while(m) { | |
267 if(!strcmp(m->data, name)) | |
268 return TRUE; | |
269 m = m->next; | |
270 } | |
271 | |
272 return FALSE; | |
273 } | |
274 | |
7398 | 275 char *jabber_chat_buddy_real_name(GaimConnection *gc, int id, const char *who) |
276 { | |
277 JabberStream *js = gc->proto_data; | |
278 JabberChat *chat; | |
279 | |
280 chat = jabber_chat_find_by_id(js, id); | |
281 | |
282 if(!chat) | |
283 return NULL; | |
284 | |
285 return g_strdup_printf("%s@%s/%s", chat->room, chat->server, who); | |
286 } | |
7895 | 287 |
7923 | 288 static void jabber_chat_room_configure_x_data_cb(JabberStream *js, xmlnode *result, gpointer data) |
289 { | |
290 JabberChat *chat = data; | |
291 xmlnode *query; | |
292 JabberIq *iq; | |
293 char *to = g_strdup_printf("%s@%s", chat->room, chat->server); | |
294 | |
295 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "http://jabber.org/protocol/muc#owner"); | |
296 xmlnode_set_attrib(iq->node, "to", to); | |
297 g_free(to); | |
298 | |
299 query = xmlnode_get_child(iq->node, "query"); | |
300 | |
301 xmlnode_insert_child(query, result); | |
302 | |
303 jabber_iq_send(iq); | |
304 } | |
305 | |
306 static void jabber_chat_room_configure_cb(JabberStream *js, xmlnode *packet, gpointer data) | |
307 { | |
308 xmlnode *query, *x; | |
309 const char *type = xmlnode_get_attrib(packet, "type"); | |
310 const char *from = xmlnode_get_attrib(packet, "from"); | |
7926 | 311 char *msg; |
7923 | 312 JabberChat *chat; |
313 JabberID *jid; | |
314 | |
315 if(!type || !from) | |
316 return; | |
317 | |
318 | |
7926 | 319 |
7923 | 320 if(!strcmp(type, "result")) { |
321 jid = jabber_id_new(from); | |
322 | |
323 if(!jid) | |
324 return; | |
325 | |
326 chat = jabber_chat_find(js, jid->node, jid->domain); | |
327 jabber_id_free(jid); | |
328 | |
329 if(!chat) | |
330 return; | |
331 | |
332 if(!(query = xmlnode_get_child(packet, "query"))) | |
333 return; | |
334 | |
8135 | 335 for(x = xmlnode_get_child(query, "x"); x; x = xmlnode_get_next_twin(x)) { |
7923 | 336 const char *xmlns; |
337 if(!(xmlns = xmlnode_get_attrib(x, "xmlns"))) | |
338 continue; | |
339 | |
340 if(!strcmp(xmlns, "jabber:x:data")) { | |
8396 | 341 chat->config_dialog_type = GAIM_REQUEST_FIELDS; |
342 chat->config_dialog_handle = jabber_x_data_request(js, x, jabber_chat_room_configure_x_data_cb, chat); | |
7923 | 343 return; |
344 } | |
345 } | |
7926 | 346 } else if(!strcmp(type, "error")) { |
8401 | 347 char *msg = jabber_parse_error(js, packet); |
7926 | 348 |
349 gaim_notify_error(js->gc, _("Configuration error"), _("Configuration error"), msg); | |
350 | |
8401 | 351 if(msg) |
352 g_free(msg); | |
7926 | 353 return; |
7923 | 354 } |
355 | |
7926 | 356 msg = g_strdup_printf("Unable to configure room %s", from); |
357 | |
358 gaim_notify_info(js->gc, _("Unable to configure"), _("Unable to configure"), msg); | |
359 g_free(msg); | |
7923 | 360 |
361 } | |
362 | |
363 void jabber_chat_request_room_configure(JabberChat *chat) { | |
364 JabberIq *iq; | |
365 xmlnode *query; | |
366 char *room_jid; | |
367 | |
7895 | 368 if(!chat) |
369 return; | |
370 | |
8396 | 371 chat->config_dialog_handle = NULL; |
372 | |
7955 | 373 if(!chat->muc) { |
374 gaim_notify_error(chat->js->gc, _("Room Configuration Error"), _("Room Configuration Error"), | |
375 _("This room is not capable of being configured")); | |
376 return; | |
377 } | |
378 | |
7923 | 379 iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, |
380 "http://jabber.org/protocol/muc#owner"); | |
381 query = xmlnode_get_child(iq->node, "query"); | |
382 room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); | |
7895 | 383 |
7923 | 384 xmlnode_set_attrib(iq->node, "to", room_jid); |
385 | |
386 jabber_iq_set_callback(iq, jabber_chat_room_configure_cb, NULL); | |
387 | |
388 jabber_iq_send(iq); | |
389 | |
390 g_free(room_jid); | |
7895 | 391 } |
392 | |
393 void jabber_chat_create_instant_room(JabberChat *chat) { | |
394 JabberIq *iq; | |
395 xmlnode *query, *x; | |
396 char *room_jid; | |
397 | |
398 if(!chat) | |
399 return; | |
400 | |
8396 | 401 chat->config_dialog_handle = NULL; |
402 | |
7895 | 403 iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, |
404 "http://jabber.org/protocol/muc#owner"); | |
405 query = xmlnode_get_child(iq->node, "query"); | |
406 x = xmlnode_new_child(query, "x"); | |
407 room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); | |
408 | |
409 xmlnode_set_attrib(iq->node, "to", room_jid); | |
410 xmlnode_set_attrib(x, "xmlns", "jabber:x:data"); | |
411 xmlnode_set_attrib(x, "type", "submit"); | |
412 | |
413 jabber_iq_send(iq); | |
414 | |
415 g_free(room_jid); | |
416 } | |
7955 | 417 |
418 static void jabber_chat_register_x_data_result_cb(JabberStream *js, xmlnode *packet, gpointer data) | |
419 { | |
420 const char *type = xmlnode_get_attrib(packet, "type"); | |
421 | |
422 if(type && !strcmp(type, "error")) { | |
8401 | 423 char *msg = jabber_parse_error(js, packet); |
424 | |
425 gaim_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); | |
426 | |
427 if(msg) | |
428 g_free(msg); | |
429 return; | |
7955 | 430 } |
431 } | |
432 | |
433 static void jabber_chat_register_x_data_cb(JabberStream *js, xmlnode *result, gpointer data) | |
434 { | |
435 JabberChat *chat = data; | |
436 xmlnode *query; | |
437 JabberIq *iq; | |
438 char *to = g_strdup_printf("%s@%s", chat->room, chat->server); | |
439 | |
440 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register"); | |
441 xmlnode_set_attrib(iq->node, "to", to); | |
442 g_free(to); | |
443 | |
444 query = xmlnode_get_child(iq->node, "query"); | |
445 | |
446 xmlnode_insert_child(query, result); | |
447 | |
448 jabber_iq_set_callback(iq, jabber_chat_register_x_data_result_cb, NULL); | |
449 | |
450 jabber_iq_send(iq); | |
451 } | |
452 | |
453 static void jabber_chat_register_cb(JabberStream *js, xmlnode *packet, gpointer data) | |
454 { | |
455 xmlnode *query, *x; | |
456 const char *type = xmlnode_get_attrib(packet, "type"); | |
457 const char *from = xmlnode_get_attrib(packet, "from"); | |
458 char *msg; | |
459 JabberChat *chat; | |
460 JabberID *jid; | |
461 | |
462 if(!type || !from) | |
463 return; | |
464 | |
465 if(!strcmp(type, "result")) { | |
466 jid = jabber_id_new(from); | |
467 | |
468 if(!jid) | |
469 return; | |
470 | |
471 chat = jabber_chat_find(js, jid->node, jid->domain); | |
472 jabber_id_free(jid); | |
473 | |
474 if(!chat) | |
475 return; | |
476 | |
477 if(!(query = xmlnode_get_child(packet, "query"))) | |
478 return; | |
479 | |
8135 | 480 for(x = xmlnode_get_child(query, "x"); x; x = xmlnode_get_next_twin(x)) { |
7955 | 481 const char *xmlns; |
482 | |
483 if(!(xmlns = xmlnode_get_attrib(x, "xmlns"))) | |
484 continue; | |
485 | |
486 if(!strcmp(xmlns, "jabber:x:data")) { | |
487 jabber_x_data_request(js, x, jabber_chat_register_x_data_cb, chat); | |
488 return; | |
489 } | |
490 } | |
491 } else if(!strcmp(type, "error")) { | |
8401 | 492 char *msg = jabber_parse_error(js, packet); |
7955 | 493 |
494 gaim_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); | |
495 | |
8401 | 496 if(msg) |
497 g_free(msg); | |
7955 | 498 return; |
499 } | |
500 | |
501 msg = g_strdup_printf("Unable to configure room %s", from); | |
502 | |
503 gaim_notify_info(js->gc, _("Unable to configure"), _("Unable to configure"), msg); | |
504 g_free(msg); | |
505 | |
506 } | |
507 | |
508 void jabber_chat_register(JabberChat *chat) | |
509 { | |
510 JabberIq *iq; | |
511 char *room_jid; | |
512 | |
513 if(!chat) | |
514 return; | |
515 | |
516 room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); | |
517 | |
518 iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, "jabber:iq:register"); | |
519 xmlnode_set_attrib(iq->node, "to", room_jid); | |
520 g_free(room_jid); | |
521 | |
522 jabber_iq_set_callback(iq, jabber_chat_register_cb, NULL); | |
523 | |
524 jabber_iq_send(iq); | |
525 } | |
526 | |
7971 | 527 /* merge this with the function below when we get everyone on the same page wrt /commands */ |
528 void jabber_chat_change_topic(JabberChat *chat, const char *topic) | |
529 { | |
530 if(topic && *topic) { | |
531 JabberMessage *jm; | |
532 jm = g_new0(JabberMessage, 1); | |
533 jm->js = chat->js; | |
534 jm->type = JABBER_MESSAGE_GROUPCHAT; | |
535 jm->subject = gaim_markup_strip_html(topic); | |
536 jm->to = g_strdup_printf("%s@%s", chat->room, chat->server); | |
537 jabber_message_send(jm); | |
538 jabber_message_free(jm); | |
539 } else { | |
540 const char *cur = gaim_conv_chat_get_topic(GAIM_CONV_CHAT(chat->conv)); | |
541 char *buf; | |
7955 | 542 |
7971 | 543 if(cur) |
8261 | 544 buf = g_strdup_printf(_("current topic is: %s"), cur); |
7971 | 545 else |
546 buf = g_strdup(_("No topic is set")); | |
547 gaim_conv_chat_write(GAIM_CONV_CHAT(chat->conv), "", buf, | |
548 GAIM_MESSAGE_SYSTEM | GAIM_MESSAGE_NO_LOG, time(NULL)); | |
549 g_free(buf); | |
550 } | |
551 | |
552 } | |
553 | |
554 void jabber_chat_set_topic(GaimConnection *gc, int id, const char *topic) | |
555 { | |
556 JabberStream *js = gc->proto_data; | |
557 JabberChat *chat = jabber_chat_find_by_id(js, id); | |
558 | |
559 if(!chat) | |
560 return; | |
561 | |
562 jabber_chat_change_topic(chat, topic); | |
563 } | |
564 | |
565 | |
7972 | 566 void jabber_chat_change_nick(JabberChat *chat, const char *nick) |
567 { | |
568 xmlnode *presence; | |
569 char *full_jid; | |
570 | |
571 if(!chat->muc) { | |
572 gaim_conv_chat_write(GAIM_CONV_CHAT(chat->conv), "", | |
573 _("Nick changing not supported in non-MUC chatrooms"), | |
574 GAIM_MESSAGE_SYSTEM, time(NULL)); | |
575 return; | |
576 } | |
577 | |
578 presence = jabber_presence_create(chat->js->gc->away_state, chat->js->gc->away); | |
579 full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, nick); | |
580 xmlnode_set_attrib(presence, "to", full_jid); | |
581 g_free(full_jid); | |
582 | |
583 jabber_send(chat->js, presence); | |
584 xmlnode_free(presence); | |
585 } | |
586 | |
7974 | 587 void jabber_chat_part(JabberChat *chat, const char *msg) |
588 { | |
589 char *room_jid; | |
590 xmlnode *presence; | |
7972 | 591 |
8537 | 592 room_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, |
593 chat->handle); | |
7974 | 594 presence = xmlnode_new("presence"); |
595 xmlnode_set_attrib(presence, "to", room_jid); | |
596 xmlnode_set_attrib(presence, "type", "unavailable"); | |
597 if(msg) { | |
598 xmlnode *status = xmlnode_new_child(presence, "status"); | |
599 xmlnode_insert_data(status, msg, -1); | |
600 } | |
601 jabber_send(chat->js, presence); | |
602 xmlnode_free(presence); | |
603 g_free(room_jid); | |
604 } | |
605 | |
8113 | 606 static void roomlist_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data) |
607 { | |
608 xmlnode *query; | |
609 xmlnode *item; | |
610 const char *type; | |
7974 | 611 |
8113 | 612 if(!js->roomlist) |
613 return; | |
614 | |
615 if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) { | |
8401 | 616 char *err = jabber_parse_error(js,packet); |
617 gaim_notify_error(js->gc, _("Roomlist Error"), | |
618 _("Error retreiving roomlist"), err); | |
8113 | 619 gaim_roomlist_set_in_progress(js->roomlist, FALSE); |
8120 | 620 gaim_roomlist_unref(js->roomlist); |
621 js->roomlist = NULL; | |
8401 | 622 g_free(err); |
8113 | 623 return; |
624 } | |
625 | |
626 if(!(query = xmlnode_get_child(packet, "query"))) { | |
8401 | 627 char *err = jabber_parse_error(js, packet); |
628 gaim_notify_error(js->gc, _("Roomlist Error"), | |
629 _("Error retreiving roomlist"), err); | |
8113 | 630 gaim_roomlist_set_in_progress(js->roomlist, FALSE); |
8120 | 631 gaim_roomlist_unref(js->roomlist); |
632 js->roomlist = NULL; | |
8401 | 633 g_free(err); |
8113 | 634 return; |
635 } | |
636 | |
8135 | 637 for(item = xmlnode_get_child(query, "item"); item; |
638 item = xmlnode_get_next_twin(item)) { | |
8113 | 639 const char *name; |
640 GaimRoomlistRoom *room; | |
641 JabberID *jid; | |
642 | |
643 if(!(jid = jabber_id_new(xmlnode_get_attrib(item, "jid")))) | |
644 continue; | |
645 name = xmlnode_get_attrib(item, "name"); | |
646 | |
647 | |
648 room = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_ROOM, jid->node, NULL); | |
649 gaim_roomlist_room_add_field(js->roomlist, room, jid->node); | |
650 gaim_roomlist_room_add_field(js->roomlist, room, jid->domain); | |
651 gaim_roomlist_room_add_field(js->roomlist, room, name ? name : ""); | |
652 gaim_roomlist_room_add(js->roomlist, room); | |
653 | |
654 jabber_id_free(jid); | |
655 } | |
656 gaim_roomlist_set_in_progress(js->roomlist, FALSE); | |
657 gaim_roomlist_unref(js->roomlist); | |
658 js->roomlist = NULL; | |
659 } | |
660 | |
661 static void roomlist_ok_cb(JabberStream *js, const char *server) | |
662 { | |
663 JabberIq *iq; | |
664 | |
665 if(!js->roomlist) | |
666 return; | |
667 | |
668 if(!server || !*server) { | |
669 gaim_notify_error(js->gc, _("Invalid Server"), _("Invalid Server"), NULL); | |
670 return; | |
671 } | |
672 | |
673 gaim_roomlist_set_in_progress(js->roomlist, TRUE); | |
674 | |
675 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items"); | |
676 | |
677 xmlnode_set_attrib(iq->node, "to", server); | |
678 | |
679 jabber_iq_set_callback(iq, roomlist_disco_result_cb, NULL); | |
680 | |
681 jabber_iq_send(iq); | |
682 } | |
683 | |
684 GaimRoomlist *jabber_roomlist_get_list(GaimConnection *gc) | |
685 { | |
686 JabberStream *js = gc->proto_data; | |
687 GList *fields = NULL; | |
688 GaimRoomlistField *f; | |
689 | |
690 if(js->roomlist) | |
691 gaim_roomlist_unref(js->roomlist); | |
692 | |
693 js->roomlist = gaim_roomlist_new(gaim_connection_get_account(gc)); | |
694 | |
695 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "room", TRUE); | |
696 fields = g_list_append(fields, f); | |
697 | |
698 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "server", TRUE); | |
699 fields = g_list_append(fields, f); | |
700 | |
701 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, _("Description"), "description", FALSE); | |
702 fields = g_list_append(fields, f); | |
703 | |
704 gaim_roomlist_set_fields(js->roomlist, fields); | |
705 | |
706 gaim_request_input(gc, _("Enter a Conference Server"), _("Enter a Conference Server"), | |
707 _("Select a conference server to query"), | |
708 js->chat_servers ? js->chat_servers->data : "conference.jabber.org", | |
8697 | 709 FALSE, FALSE, NULL, |
710 _("Find Rooms"), G_CALLBACK(roomlist_ok_cb), _("Cancel"), NULL, js); | |
8113 | 711 |
712 return js->roomlist; | |
713 } | |
714 | |
715 void jabber_roomlist_cancel(GaimRoomlist *list) | |
716 { | |
717 GaimConnection *gc; | |
718 JabberStream *js; | |
719 | |
720 gc = gaim_account_get_connection(list->account); | |
721 js = gc->proto_data; | |
722 | |
723 gaim_roomlist_set_in_progress(list, FALSE); | |
724 | |
725 if (js->roomlist == list) { | |
726 js->roomlist = NULL; | |
727 gaim_roomlist_unref(list); | |
728 } | |
729 } | |
730 | |
9152 | 731 void jabber_chat_member_free(JabberChatMember *jcm) |
732 { | |
733 g_free(jcm->handle); | |
734 g_free(jcm->jid); | |
735 g_free(jcm); | |
736 } | |
737 | |
738 void jabber_chat_track_handle(JabberChat *chat, const char *handle, | |
739 const char *jid, const char *affiliation, const char *role) | |
740 { | |
741 JabberChatMember *jcm = g_new0(JabberChatMember, 1); | |
742 | |
743 jcm->handle = g_strdup(handle); | |
744 jcm->jid = g_strdup(jid); | |
745 | |
746 g_hash_table_replace(chat->members, jcm->handle, jcm); | |
747 | |
748 /* XXX: keep track of role and affiliation */ | |
749 } | |
750 | |
751 void jabber_chat_remove_handle(JabberChat *chat, const char *handle) | |
752 { | |
753 g_hash_table_remove(chat->members, handle); | |
754 } | |
755 | |
756 gboolean jabber_chat_ban_user(JabberChat *chat, const char *who, const char *why) | |
757 { | |
758 JabberIq *iq; | |
759 JabberChatMember *jcm = g_hash_table_lookup(chat->members, who); | |
760 char *to; | |
761 xmlnode *query, *item, *reason; | |
762 | |
763 if(!jcm || !jcm->jid) | |
764 return FALSE; | |
765 | |
766 iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, | |
767 "http://jabber.org/protocol/muc#admin"); | |
768 | |
769 to = g_strdup_printf("%s@%s", chat->room, chat->server); | |
770 xmlnode_set_attrib(iq->node, "to", to); | |
771 g_free(to); | |
772 | |
773 query = xmlnode_get_child(iq->node, "query"); | |
774 item = xmlnode_new_child(query, "item"); | |
775 xmlnode_set_attrib(item, "jid", jcm->jid); | |
776 xmlnode_set_attrib(item, "affiliation", "outcast"); | |
777 if(why) { | |
778 reason = xmlnode_new_child(item, "reason"); | |
779 xmlnode_insert_data(reason, why, -1); | |
780 } | |
781 | |
782 jabber_iq_send(iq); | |
783 | |
784 return TRUE; | |
785 } | |
8113 | 786 |
787 | |
9152 | 788 gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, const char *why) |
789 { | |
790 JabberIq *iq; | |
791 JabberChatMember *jcm = g_hash_table_lookup(chat->members, who); | |
792 char *to; | |
793 xmlnode *query, *item, *reason; | |
794 | |
795 if(!jcm || !jcm->jid) | |
796 return FALSE; | |
797 | |
798 iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, | |
799 "http://jabber.org/protocol/muc#admin"); | |
800 | |
801 to = g_strdup_printf("%s@%s", chat->room, chat->server); | |
802 xmlnode_set_attrib(iq->node, "to", to); | |
803 g_free(to); | |
804 | |
805 query = xmlnode_get_child(iq->node, "query"); | |
806 item = xmlnode_new_child(query, "item"); | |
807 xmlnode_set_attrib(item, "jid", jcm->jid); | |
808 xmlnode_set_attrib(item, "role", "none"); | |
809 if(why) { | |
810 reason = xmlnode_new_child(item, "reason"); | |
811 xmlnode_insert_data(reason, why, -1); | |
812 } | |
813 | |
814 jabber_iq_send(iq); | |
815 | |
816 return TRUE; | |
817 } | |
818 | |
819 | |
820 |