Improve UI latency and CPU usage
[mcabber.git] / mcabber / src / xmpp_muc.c
blob408ae123f2576eb5a97e3df041102cfcf0134e1a
1 /*
2 * xmpp_muc.c -- Jabber MUC protocol handling
4 * Copyright (C) 2008-2009 Frank Zschockelt <mcabber@freakysoft.de>
5 * Copyright (C) 2005-2009 Mikael Berthe <mikael@lilotux.net>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
23 #include <string.h>
24 #include <stdlib.h>
26 #include "xmpp_helper.h"
27 #include "events.h"
28 #include "hooks.h"
29 #include "screen.h"
30 #include "hbuf.h"
31 #include "roster.h"
32 #include "commands.h"
33 #include "settings.h"
34 #include "utils.h"
35 #include "histolog.h"
37 extern enum imstatus mystatus;
38 extern gchar *mystatusmsg;
40 static void decline_invitation(event_muc_invitation *invitation, char *reason)
42 // cut and paste from xmpp_room_invite
43 LmMessage *m;
44 LmMessageNode *x, *y;
46 if (!invitation) return;
47 if (!invitation->to || !invitation->from) return;
49 m = lm_message_new(invitation->to, LM_MESSAGE_TYPE_MESSAGE);
51 x = lm_message_node_add_child(m->node, "x", NULL);
52 lm_message_node_set_attribute(x, "xmlns",
53 "http://jabber.org/protocol/muc#user");
55 y = lm_message_node_add_child(x, "decline", NULL);
56 lm_message_node_set_attribute(y, "to", invitation->from);
58 if (reason)
59 lm_message_node_add_child(y, "reason", reason);
61 lm_connection_send(lconnection, m, NULL);
62 lm_message_unref(m);
65 static int evscallback_invitation(eviqs *evp, guint evcontext)
67 event_muc_invitation *invitation = evp->data;
69 // Sanity check
70 if (!invitation) {
71 // Shouldn't happen.
72 scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback.");
73 return 0;
76 if (evcontext == EVS_CONTEXT_TIMEOUT) {
77 scr_LogPrint(LPRINT_LOGNORM, "Event %s timed out, cancelled.", evp->id);
78 goto evscallback_invitation_free;
80 if (evcontext == EVS_CONTEXT_CANCEL) {
81 scr_LogPrint(LPRINT_LOGNORM, "Event %s cancelled.", evp->id);
82 goto evscallback_invitation_free;
84 if (!(evcontext & EVS_CONTEXT_USER))
85 goto evscallback_invitation_free;
86 // Ok, let's work now.
87 // evcontext: 0, 1 == reject, accept
89 if (evcontext & ~EVS_CONTEXT_USER) {
90 char *nickname = default_muc_nickname(invitation->to);
91 xmpp_room_join(invitation->to, nickname, invitation->passwd);
92 g_free(nickname);
93 } else {
94 scr_LogPrint(LPRINT_LOGNORM, "Invitation to %s refused.", invitation->to);
95 decline_invitation(invitation, NULL);
98 evscallback_invitation_free:
99 g_free(invitation->to);
100 g_free(invitation->from);
101 g_free(invitation->passwd);
102 g_free(invitation->reason);
103 g_free(invitation);
104 evp->data = NULL;
105 return 0;
108 // Join a MUC room
109 void xmpp_room_join(const char *room, const char *nickname, const char *passwd)
111 LmMessage *x;
112 LmMessageNode *y;
113 gchar *roomid;
114 GSList *room_elt;
116 if (!lm_connection_is_authenticated(lconnection) || !room) return;
117 if (!nickname) return;
119 roomid = g_strdup_printf("%s/%s", room, nickname);
120 if (check_jid_syntax(roomid)) {
121 scr_LogPrint(LPRINT_NORMAL, "<%s/%s> is not a valid Jabber room", room,
122 nickname);
123 g_free(roomid);
124 return;
127 room_elt = roster_find(room, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM);
128 // Add room if it doesn't already exist
129 if (!room_elt) {
130 room_elt = roster_add_user(room, NULL, NULL, ROSTER_TYPE_ROOM,
131 sub_none, -1);
132 } else {
133 // Make sure this is a room (it can be a conversion user->room)
134 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
136 // If insideroom is TRUE, this is a nickname change and we don't care here
137 if (!buddy_getinsideroom(room_elt->data)) {
138 // We're trying to enter a room
139 buddy_setnickname(room_elt->data, nickname);
142 // Send the XML request
143 x = lm_message_new(roomid, LM_MESSAGE_TYPE_PRESENCE);
145 x = lm_message_new_presence(mystatus, roomid, mystatusmsg);
146 y = lm_message_node_add_child(x->node, "x", NULL);
147 lm_message_node_set_attribute(y, "xmlns", "http://jabber.org/protocol/muc");
148 if (passwd)
149 lm_message_node_add_child(y, "password", passwd);
151 lm_connection_send(lconnection, x, NULL);
152 lm_message_unref(x);
153 g_free(roomid);
156 // Invite a user to a MUC room
157 // room syntax: "room@server"
158 // reason can be null.
159 void xmpp_room_invite(const char *room, const char *fjid, const char *reason)
161 LmMessage *msg;
162 LmMessageNode *x, *y;
164 if (!lm_connection_is_authenticated(lconnection) || !room || !fjid) return;
166 msg = lm_message_new(room, LM_MESSAGE_TYPE_MESSAGE);
168 x = lm_message_node_add_child(msg->node, "x", NULL);
169 lm_message_node_set_attribute(x, "xmlns",
170 "http://jabber.org/protocol/muc#user");
172 y = lm_message_node_add_child(x, "invite", NULL);
173 lm_message_node_set_attribute(y, "to", fjid);
175 if (reason)
176 lm_message_node_add_child(y, "reason", reason);
178 lm_connection_send(lconnection, msg, NULL);
179 lm_message_unref(msg);
182 int xmpp_room_setattrib(const char *roomid, const char *fjid,
183 const char *nick, struct role_affil ra,
184 const char *reason)
186 LmMessage *iq;
187 LmMessageNode *query, *x;
189 if (!lm_connection_is_authenticated(lconnection) || !roomid) return 1;
190 if (!fjid && !nick) return 1;
192 if (check_jid_syntax((char*)roomid)) {
193 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", roomid);
194 return 1;
196 if (fjid && check_jid_syntax((char*)fjid)) {
197 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", fjid);
198 return 1;
201 if (ra.type == type_affil && ra.val.affil == affil_outcast && !fjid)
202 return 1; // Shouldn't happen (jid mandatory when banning)
204 iq = lm_message_new_with_sub_type(roomid, LM_MESSAGE_TYPE_IQ,
205 LM_MESSAGE_SUB_TYPE_SET);
206 query = lm_message_node_add_child(iq->node, "query", NULL);
207 lm_message_node_set_attribute(query, "xmlns",
208 "http://jabber.org/protocol/muc#admin");
209 x = lm_message_node_add_child(query, "item", NULL);
211 if (fjid) {
212 lm_message_node_set_attribute(x, "jid", fjid);
213 } else { // nickname
214 lm_message_node_set_attribute(x, "nick", nick);
217 if (ra.type == type_affil)
218 lm_message_node_set_attribute(x, "affiliation", straffil[ra.val.affil]);
219 else if (ra.type == type_role)
220 lm_message_node_set_attribute(x, "role", strrole[ra.val.role]);
222 if (reason)
223 lm_message_node_add_child(x, "reason", reason);
225 lm_connection_send(lconnection, iq, NULL);
226 lm_message_unref(iq);
228 return 0;
231 // Unlock a MUC room
232 // room syntax: "room@server"
233 void xmpp_room_unlock(const char *room)
235 LmMessageNode *y, *z;
236 LmMessage *iq;
238 if (!lm_connection_is_authenticated(lconnection) || !room) return;
240 iq = lm_message_new_with_sub_type(room, LM_MESSAGE_TYPE_IQ,
241 LM_MESSAGE_SUB_TYPE_SET);
242 lm_message_node_set_attribute(iq->node, "xmlns",
243 "http://jabber.org/protocol/muc#owner");
246 y = lm_message_node_add_child(iq->node, "query", NULL);
247 z = lm_message_node_add_child(y, "x", NULL);
248 lm_message_node_set_attribute(z, "xmlns", "jabber:x:data");
249 lm_message_node_set_attribute(z, "type", "submit");
251 lm_connection_send(lconnection, iq, NULL);
252 lm_message_unref(iq);
255 // Destroy a MUC room
256 // room syntax: "room@server"
257 void xmpp_room_destroy(const char *room, const char *venue, const char *reason)
259 LmMessage *iq;
260 LmMessageNode *query, *x;
262 if (!lm_connection_is_authenticated(lconnection) || !room) return;
264 iq = lm_message_new_with_sub_type(room, LM_MESSAGE_TYPE_IQ,
265 LM_MESSAGE_SUB_TYPE_SET);
266 query = lm_message_node_add_child(iq->node, "query", NULL);
267 lm_message_node_set_attribute(query, "xmlns",
268 "http://jabber.org/protocol/muc#owner");
269 x = lm_message_node_add_child(query, "destroy", NULL);
271 if (venue && *venue)
272 lm_message_node_set_attribute(x, "jid", venue);
274 if (reason)
275 lm_message_node_add_child(x, "reason", reason);
277 lm_connection_send(lconnection, iq, NULL);
278 lm_message_unref(iq);
281 // muc_get_item_info(...)
282 // Get room member's information from xmlndata.
283 // The variables must be initialized before calling this function,
284 // because they are not touched if the relevant information is missing.
285 static void muc_get_item_info(const char *from, LmMessageNode *xmldata,
286 enum imrole *mbrole, enum imaffiliation *mbaffil,
287 const char **mbjid, const char **mbnick,
288 const char **actorjid, const char **reason)
290 LmMessageNode *y, *z;
291 const char *p;
293 y = lm_message_node_find_child(xmldata, "item");
294 if (!y)
295 return;
297 p = lm_message_node_get_attribute(y, "affiliation");
298 if (p) {
299 if (!strcmp(p, "owner")) *mbaffil = affil_owner;
300 else if (!strcmp(p, "admin")) *mbaffil = affil_admin;
301 else if (!strcmp(p, "member")) *mbaffil = affil_member;
302 else if (!strcmp(p, "outcast")) *mbaffil = affil_outcast;
303 else if (!strcmp(p, "none")) *mbaffil = affil_none;
304 else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown affiliation \"%s\"",
305 from, p);
307 p = lm_message_node_get_attribute(y, "role");
308 if (p) {
309 if (!strcmp(p, "moderator")) *mbrole = role_moderator;
310 else if (!strcmp(p, "participant")) *mbrole = role_participant;
311 else if (!strcmp(p, "visitor")) *mbrole = role_visitor;
312 else if (!strcmp(p, "none")) *mbrole = role_none;
313 else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown role \"%s\"",
314 from, p);
316 *mbjid = lm_message_node_get_attribute(y, "jid");
317 *mbnick = lm_message_node_get_attribute(y, "nick");
318 // For kick/ban, there can be actor and reason tags
319 *reason = lm_message_node_get_child_value(y, "reason");
320 z = lm_message_node_find_child(y, "actor");
321 if (z)
322 *actorjid = lm_message_node_get_attribute(z, "jid");
325 // muc_handle_join(...)
326 // Handle a join event in a MUC room.
327 // This function will return the new_member value TRUE if somebody else joins
328 // the room (and FALSE if _we_ are joining the room).
329 static bool muc_handle_join(const GSList *room_elt, const char *rname,
330 const char *roomjid, const char *ournick,
331 enum room_printstatus printstatus,
332 time_t usttime, int log_muc_conf)
334 bool new_member = FALSE; // True if somebody else joins the room (not us)
335 gchar *mbuf;
337 if (!buddy_getinsideroom(room_elt->data)) {
338 // We weren't inside the room yet. Now we are.
339 // However, this could be a presence packet from another room member
341 buddy_setinsideroom(room_elt->data, TRUE);
342 // Set the message flag unless we're already in the room buffer window
343 scr_setmsgflag_if_needed(roomjid, FALSE);
344 // Add a message to the tracelog file
345 mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, ournick);
346 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf);
347 g_free(mbuf);
348 mbuf = g_strdup_printf("You have joined as \"%s\"", ournick);
350 // The 1st presence message could be for another room member
351 if (strcmp(ournick, rname)) {
352 // Display current mbuf and create a new message for the member
353 // Note: the usttime timestamp is related to the other member,
354 // so we use 0 here.
355 scr_WriteIncomingMessage(roomjid, mbuf, 0,
356 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
357 if (log_muc_conf)
358 hlog_write_message(roomjid, 0, -1, mbuf);
359 g_free(mbuf);
360 if (printstatus != status_none)
361 mbuf = g_strdup_printf("%s has joined", rname);
362 else
363 mbuf = NULL;
364 new_member = TRUE;
366 } else {
367 mbuf = NULL;
368 if (strcmp(ournick, rname)) {
369 if (printstatus != status_none)
370 mbuf = g_strdup_printf("%s has joined", rname);
371 new_member = TRUE;
375 if (mbuf) {
376 guint msgflags = HBB_PREFIX_INFO;
377 if (!settings_opt_get_int("muc_flag_joins"))
378 msgflags |= HBB_PREFIX_NOFLAG;
379 scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0);
380 if (log_muc_conf)
381 hlog_write_message(roomjid, 0, -1, mbuf);
382 g_free(mbuf);
385 return new_member;
388 void handle_muc_presence(const char *from, LmMessageNode *xmldata,
389 const char *roomjid, const char *rname,
390 enum imstatus ust, const char *ustmsg,
391 time_t usttime, char bpprio)
393 LmMessageNode *y;
394 const char *p;
395 char *mbuf;
396 const char *ournick;
397 enum imrole mbrole = role_none;
398 enum imaffiliation mbaffil = affil_none;
399 enum room_printstatus printstatus;
400 enum room_autowhois autowhois;
401 const char *mbjid = NULL, *mbnick = NULL;
402 const char *actorjid = NULL, *reason = NULL;
403 bool new_member = FALSE; // True if somebody else joins the room (not us)
404 guint statuscode = 0;
405 guint nickchange = 0;
406 GSList *room_elt;
407 int log_muc_conf;
408 guint msgflags;
410 log_muc_conf = settings_opt_get_int("log_muc_conf");
412 room_elt = roster_find(roomjid, jidsearch, 0);
413 if (!room_elt) {
414 // Add room if it doesn't already exist
415 // It shouldn't happen, there is probably something wrong (server or
416 // network issue?)
417 room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM,
418 sub_none, -1);
419 scr_LogPrint(LPRINT_LOGNORM, "Strange MUC presence message");
420 } else {
421 // Make sure this is a room (it can be a conversion user->room)
422 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
425 // Get room member's information
426 muc_get_item_info(from, xmldata, &mbrole, &mbaffil, &mbjid, &mbnick,
427 &actorjid, &reason);
429 // Get our room nickname
430 ournick = buddy_getnickname(room_elt->data);
432 if (!ournick) {
433 // It shouldn't happen, probably a server issue
434 mbuf = g_strdup_printf("Unexpected groupchat packet!");
436 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf);
437 scr_WriteIncomingMessage(roomjid, mbuf, 0, HBB_PREFIX_INFO, 0);
438 g_free(mbuf);
439 // Send back an unavailable packet
440 xmpp_setstatus(offline, roomjid, "", TRUE);
441 scr_DrawRoster();
442 return;
445 // Get the status code
446 // 201: a room has been created
447 // 301: the user has been banned from the room
448 // 303: new room nickname
449 // 307: the user has been kicked from the room
450 // 321,322,332: the user has been removed from the room
451 y = lm_message_node_find_child(xmldata, "status");
452 if (y) {
453 p = lm_message_node_get_attribute(y, "code");
454 if (p)
455 statuscode = atoi(p);
458 // Get the room's "print_status" settings
459 printstatus = buddy_getprintstatus(room_elt->data);
460 if (printstatus == status_default) {
461 printstatus = (guint) settings_opt_get_int("muc_print_status");
462 if (printstatus > 3)
463 printstatus = status_default;
466 // A new room has been created; accept MUC default config
467 if (statuscode == 201)
468 xmpp_room_unlock(roomjid);
470 // Check for nickname change
471 if (statuscode == 303 && mbnick) {
472 mbuf = g_strdup_printf("%s is now known as %s", rname, mbnick);
473 scr_WriteIncomingMessage(roomjid, mbuf, usttime,
474 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
475 if (log_muc_conf)
476 hlog_write_message(roomjid, 0, -1, mbuf);
477 g_free(mbuf);
478 buddy_resource_setname(room_elt->data, rname, mbnick);
479 // Maybe it's _our_ nickname...
480 if (ournick && !strcmp(rname, ournick))
481 buddy_setnickname(room_elt->data, mbnick);
482 nickchange = TRUE;
485 // Check for departure/arrival
486 if (!mbnick && ust == offline) {
487 // Somebody is leaving
488 enum { leave=0, kick, ban } how = leave;
489 bool we_left = FALSE;
491 if (statuscode == 307)
492 how = kick;
493 else if (statuscode == 301)
494 how = ban;
496 // If this is a leave, check if it is ourself
497 if (ournick && !strcmp(rname, ournick)) {
498 we_left = TRUE; // _We_ have left! (kicked, banned, etc.)
499 buddy_setinsideroom(room_elt->data, FALSE);
500 buddy_setnickname(room_elt->data, NULL);
501 buddy_del_all_resources(room_elt->data);
502 buddy_settopic(room_elt->data, NULL);
503 scr_UpdateChatStatus(FALSE);
504 update_roster = TRUE;
507 // The message depends on _who_ left, and _how_
508 if (how) {
509 gchar *mbuf_end;
510 // Forced leave
511 if (actorjid) {
512 mbuf_end = g_strdup_printf("%s from %s by <%s>.\nReason: %s",
513 (how == ban ? "banned" : "kicked"),
514 roomjid, actorjid, reason);
515 } else {
516 mbuf_end = g_strdup_printf("%s from %s.",
517 (how == ban ? "banned" : "kicked"),
518 roomjid);
520 if (we_left)
521 mbuf = g_strdup_printf("You have been %s", mbuf_end);
522 else
523 mbuf = g_strdup_printf("%s has been %s", rname, mbuf_end);
525 g_free(mbuf_end);
526 } else {
527 // Natural leave
528 if (we_left) {
529 LmMessageNode *destroynode = lm_message_node_find_child(xmldata,
530 "destroy");
531 if (destroynode) {
532 if ((reason = lm_message_node_get_child_value(destroynode,
533 "reason"))) {
534 mbuf = g_strdup_printf("You have left %s, "
535 "the room has been destroyed: %s",
536 roomjid, reason);
537 } else {
538 mbuf = g_strdup_printf("You have left %s, "
539 "the room has been destroyed", roomjid);
541 } else {
542 mbuf = g_strdup_printf("You have left %s", roomjid);
544 } else {
545 if (ust != offline) {
546 // This can happen when a network failure occurs,
547 // this isn't an official leave but the user isn't there anymore.
548 mbuf = g_strdup_printf("%s has disappeared!", rname);
549 ust = offline;
550 } else {
551 if (ustmsg)
552 mbuf = g_strdup_printf("%s has left: %s", rname, ustmsg);
553 else
554 mbuf = g_strdup_printf("%s has left", rname);
559 // Display the mbuf message if we're concerned
560 // or if the print_status isn't set to none.
561 if (we_left || printstatus != status_none) {
562 msgflags = HBB_PREFIX_INFO;
563 if (!we_left && settings_opt_get_int("muc_flag_joins") != 2)
564 msgflags |= HBB_PREFIX_NOFLAG;
565 scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0);
568 if (log_muc_conf)
569 hlog_write_message(roomjid, 0, -1, mbuf);
571 if (we_left) {
572 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf);
573 g_free(mbuf);
574 return;
576 g_free(mbuf);
577 } else if (buddy_getstatus(room_elt->data, rname) == offline &&
578 ust != offline) {
579 // Somebody is joining
580 new_member = muc_handle_join(room_elt, rname, roomjid, ournick,
581 printstatus, usttime, log_muc_conf);
582 } else {
583 // This is a simple member status change
585 if (printstatus == status_all && !nickchange) {
586 mbuf = g_strdup_printf("Member status has changed: %s [%c] %s", rname,
587 imstatus2char[ust], ((ustmsg) ? ustmsg : ""));
588 scr_WriteIncomingMessage(roomjid, mbuf, usttime,
589 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
590 g_free(mbuf);
594 // Sanity check, shouldn't happen...
595 if (!rname)
596 return;
598 // Update room member status
599 roster_setstatus(roomjid, rname, bpprio, ust, ustmsg, usttime,
600 mbrole, mbaffil, mbjid);
602 autowhois = buddy_getautowhois(room_elt->data);
603 if (autowhois == autowhois_default)
604 autowhois = (settings_opt_get_int("muc_auto_whois") ?
605 autowhois_on : autowhois_off);
607 if (new_member && autowhois == autowhois_on) {
608 // FIXME: This will fail for some UTF-8 nicknames.
609 gchar *joiner_nick = from_utf8(rname);
610 cmd_room_whois(room_elt->data, joiner_nick, FALSE);
611 g_free(joiner_nick);
614 scr_DrawRoster();
617 void roompresence(gpointer room, void *presencedata)
619 const char *bjid;
620 const char *nickname;
621 char *to;
622 struct T_presence *pres = presencedata;
624 if (!buddy_getinsideroom(room))
625 return;
627 bjid = buddy_getjid(room);
628 if (!bjid) return;
629 nickname = buddy_getnickname(room);
630 if (!nickname) return;
632 to = g_strdup_printf("%s/%s", bjid, nickname);
633 xmpp_setstatus(pres->st, to, pres->msg, TRUE);
634 g_free(to);
637 // got_invite(from, to, reason, passwd)
638 // This function should be called when receiving an invitation from user
639 // "from", to enter the room "to". Optional reason and room password can
640 // be provided.
641 static void got_invite(const char* from, const char *to, const char* reason,
642 const char* passwd)
644 eviqs *evn;
645 event_muc_invitation *invitation;
646 GString *sbuf;
647 char *barejid;
648 GSList *room_elt;
650 sbuf = g_string_new("");
651 if (reason) {
652 g_string_printf(sbuf,
653 "Received an invitation to <%s>, from <%s>, reason: %s",
654 to, from, reason);
655 } else {
656 g_string_printf(sbuf, "Received an invitation to <%s>, from <%s>",
657 to, from);
660 barejid = jidtodisp(from);
661 scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
662 scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
664 evn = evs_new(EVS_TYPE_INVITATION, EVS_MAX_TIMEOUT);
665 if (evn) {
666 evn->callback = &evscallback_invitation;
667 invitation = g_new(event_muc_invitation, 1);
668 invitation->to = g_strdup(to);
669 invitation->from = g_strdup(from);
670 invitation->passwd = g_strdup(passwd);
671 invitation->reason = g_strdup(reason);
672 evn->data = invitation;
673 evn->desc = g_strdup_printf("<%s> invites you to %s ", from, to);
674 g_string_printf(sbuf, "Please use /event %s accept|reject", evn->id);
675 } else {
676 g_string_printf(sbuf, "Unable to create a new event!");
678 scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
679 scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
680 g_string_free(sbuf, TRUE);
681 g_free(barejid);
683 // Make sure the MUC room barejid is a room in the roster
684 barejid = jidtodisp(to);
685 room_elt = roster_find(barejid, jidsearch, 0);
686 if (room_elt)
687 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
689 g_free(barejid);
693 // Specific MUC message handling (for example invitation processing)
694 void got_muc_message(const char *from, LmMessageNode *x)
696 LmMessageNode *invite = lm_message_node_get_child(x, "invite");
697 if (invite)
699 const char *invite_from;
700 const char *reason = NULL;
701 const char *password = NULL;
703 invite_from = lm_message_node_get_attribute(invite, "from");
704 reason = lm_message_node_get_child_value(invite, "reason");
705 password = lm_message_node_get_child_value(invite, "password");
706 if (invite_from)
707 got_invite(invite_from, from, reason, password);
709 // TODO
710 // handle status code = 100 ( not anonymous )
711 // handle status code = 170 ( changement de config )
712 // 10.2.1 Notification of Configuration Changes
713 // declined invitation
716 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */