comparison mcabber/src/xmpp_muc.c @ 1598:a087125d8fc8

Replace libjabber with loudmouth
author franky
date Sun, 11 Oct 2009 15:38:32 +0200
parents mcabber/src/jabglue.c@1802b926e3fa
children dcd5d4c75199
comparison
equal deleted inserted replaced
1597:4f59a414217e 1598:a087125d8fc8
1 /* See xmpp.c file for copyright and license details. */
2
3 static void decline_invitation(event_muc_invitation *invitation, char *reason)
4 {
5 // cut and paste from xmpp_room_invite
6 LmMessage *m;
7 LmMessageNode *x, *y;
8
9 if (!invitation) return;
10 if (!invitation->to || !invitation->from) return;
11
12 m = lm_message_new(invitation->to, LM_MESSAGE_TYPE_MESSAGE);
13
14 x = lm_message_node_add_child(m->node, "x", NULL);
15 lm_message_node_set_attribute(x, "xmlns",
16 "http://jabber.org/protocol/muc#user");
17
18 y = lm_message_node_add_child(x, "decline", NULL);
19 lm_message_node_set_attribute(y, "to", invitation->from);
20
21 if (reason)
22 lm_message_node_add_child(y, "reason", reason);
23
24 lm_connection_send(lconnection, m, NULL);
25 lm_message_unref(m);
26 }
27
28 static int evscallback_invitation(eviqs *evp, guint evcontext)
29 {
30 event_muc_invitation *invitation = evp->data;
31
32 // Sanity check
33 if (!invitation) {
34 // Shouldn't happen.
35 scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback.");
36 return 0;
37 }
38
39 if (evcontext == EVS_CONTEXT_TIMEOUT) {
40 scr_LogPrint(LPRINT_LOGNORM, "Event %s timed out, cancelled.", evp->id);
41 goto evscallback_invitation_free;
42 }
43 if (evcontext == EVS_CONTEXT_CANCEL) {
44 scr_LogPrint(LPRINT_LOGNORM, "Event %s cancelled.", evp->id);
45 goto evscallback_invitation_free;
46 }
47 if (!(evcontext & EVS_CONTEXT_USER))
48 goto evscallback_invitation_free;
49 // Ok, let's work now.
50 // evcontext: 0, 1 == reject, accept
51
52 if (evcontext & ~EVS_CONTEXT_USER) {
53 char *nickname = default_muc_nickname(invitation->to);
54 xmpp_room_join(invitation->to, nickname, invitation->passwd);
55 g_free(nickname);
56 } else {
57 scr_LogPrint(LPRINT_LOGNORM, "Invitation to %s refused.", invitation->to);
58 decline_invitation(invitation, NULL);
59 }
60
61 evscallback_invitation_free:
62 g_free(invitation->to);
63 g_free(invitation->from);
64 g_free(invitation->passwd);
65 g_free(invitation->reason);
66 g_free(invitation);
67 evp->data = NULL;
68 return 0;
69 }
70
71 // Join a MUC room
72 void xmpp_room_join(const char *room, const char *nickname, const char *passwd)
73 {
74 LmMessage *x;
75 LmMessageNode *y;
76 gchar *roomid;
77 GSList *room_elt;
78
79 if (!lm_connection_is_authenticated(lconnection) || !room) return;
80 if (!nickname) return;
81
82 roomid = g_strdup_printf("%s/%s", room, nickname);
83 if (check_jid_syntax(roomid)) {
84 scr_LogPrint(LPRINT_NORMAL, "<%s/%s> is not a valid Jabber room", room,
85 nickname);
86 g_free(roomid);
87 return;
88 }
89
90 room_elt = roster_find(room, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM);
91 // Add room if it doesn't already exist
92 if (!room_elt) {
93 room_elt = roster_add_user(room, NULL, NULL, ROSTER_TYPE_ROOM,
94 sub_none, -1);
95 } else {
96 // Make sure this is a room (it can be a conversion user->room)
97 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
98 }
99 // If insideroom is TRUE, this is a nickname change and we don't care here
100 if (!buddy_getinsideroom(room_elt->data)) {
101 // We're trying to enter a room
102 buddy_setnickname(room_elt->data, nickname);
103 }
104
105 // Send the XML request
106 x = lm_message_new(roomid, LM_MESSAGE_TYPE_PRESENCE);
107
108 x = lm_message_new_presence(mystatus, roomid, mystatusmsg);
109 y = lm_message_node_add_child(x->node, "x", NULL);
110 lm_message_node_set_attribute(y, "xmlns", "http://jabber.org/protocol/muc");
111 if (passwd)
112 lm_message_node_add_child(y, "password", passwd);
113
114 lm_connection_send(lconnection, x, NULL);
115 lm_message_unref(x);
116 g_free(roomid);
117 }
118
119 // Invite a user to a MUC room
120 // room syntax: "room@server"
121 // reason can be null.
122 void xmpp_room_invite(const char *room, const char *fjid, const char *reason)
123 {
124 LmMessage *msg;
125 LmMessageNode *x, *y;
126
127 if (!lm_connection_is_authenticated(lconnection) || !room || !fjid) return;
128
129 msg = lm_message_new(room, LM_MESSAGE_TYPE_MESSAGE);
130
131 x = lm_message_node_add_child(msg->node, "x", NULL);
132 lm_message_node_set_attribute(x, "xmlns",
133 "http://jabber.org/protocol/muc#user");
134
135 y = lm_message_node_add_child(x, "invite", NULL);
136 lm_message_node_set_attribute(y, "to", fjid);
137
138 if (reason)
139 lm_message_node_add_child(y, "reason", reason);
140
141 lm_connection_send(lconnection, msg, NULL);
142 lm_message_unref(msg);
143 }
144
145 int xmpp_room_setattrib(const char *roomid, const char *fjid,
146 const char *nick, struct role_affil ra,
147 const char *reason)
148 {
149 LmMessage *iq;
150 LmMessageNode *query, *x;
151
152 if (!lm_connection_is_authenticated(lconnection) || !roomid) return 1;
153 if (!fjid && !nick) return 1;
154
155 if (check_jid_syntax((char*)roomid)) {
156 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", roomid);
157 return 1;
158 }
159 if (fjid && check_jid_syntax((char*)fjid)) {
160 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", fjid);
161 return 1;
162 }
163
164 if (ra.type == type_affil && ra.val.affil == affil_outcast && !fjid)
165 return 1; // Shouldn't happen (jid mandatory when banning)
166
167 iq = lm_message_new_with_sub_type(roomid, LM_MESSAGE_TYPE_IQ,
168 LM_MESSAGE_SUB_TYPE_SET);
169 query = lm_message_node_add_child(iq->node, "query", NULL);
170 lm_message_node_set_attribute(query, "xmlns",
171 "http://jabber.org/protocol/muc#admin");
172 x = lm_message_node_add_child(query, "item", NULL);
173
174 if (fjid) {
175 lm_message_node_set_attribute(x, "jid", fjid);
176 } else { // nickname
177 lm_message_node_set_attribute(x, "nick", nick);
178 }
179
180 if (ra.type == type_affil)
181 lm_message_node_set_attribute(x, "affiliation", straffil[ra.val.affil]);
182 else if (ra.type == type_role)
183 lm_message_node_set_attribute(x, "role", strrole[ra.val.role]);
184
185 if (reason)
186 lm_message_node_add_child(x, "reason", reason);
187
188 lm_connection_send(lconnection, iq, NULL);
189 lm_message_unref(iq);
190
191 return 0;
192 }
193
194 // Unlock a MUC room
195 // room syntax: "room@server"
196 void xmpp_room_unlock(const char *room)
197 {
198 LmMessageNode *y, *z;
199 LmMessage *iq;
200
201 if (!lm_connection_is_authenticated(lconnection) || !room) return;
202
203 iq = lm_message_new_with_sub_type(room, LM_MESSAGE_TYPE_IQ,
204 LM_MESSAGE_SUB_TYPE_SET);
205 lm_message_node_set_attribute(iq->node, "xmlns",
206 "http://jabber.org/protocol/muc#owner");
207
208
209 y = lm_message_node_add_child(iq->node, "query", NULL);
210 z = lm_message_node_add_child(y, "x", NULL);
211 lm_message_node_set_attribute(z, "xmlns", "jabber:x:data");
212 lm_message_node_set_attribute(z, "type", "submit");
213
214 lm_connection_send(lconnection, iq, NULL);
215 lm_message_unref(iq);
216 }
217
218 // Destroy a MUC room
219 // room syntax: "room@server"
220 void xmpp_room_destroy(const char *room, const char *venue, const char *reason)
221 {
222 LmMessage *iq;
223 LmMessageNode *query, *x;
224
225 if (!lm_connection_is_authenticated(lconnection) || !room) return;
226
227 iq = lm_message_new_with_sub_type(room, LM_MESSAGE_TYPE_IQ,
228 LM_MESSAGE_SUB_TYPE_SET);
229 query = lm_message_node_add_child(iq->node, "query", NULL);
230 lm_message_node_set_attribute(query, "xmlns",
231 "http://jabber.org/protocol/muc#owner");
232 x = lm_message_node_add_child(query, "destroy", NULL);
233
234 if (venue && *venue)
235 lm_message_node_set_attribute(x, "jid", venue);
236
237 if (reason)
238 lm_message_node_add_child(x, "reason", reason);
239
240 lm_connection_send(lconnection, iq, NULL);
241 lm_message_unref(iq);
242 }
243
244 // muc_get_item_info(...)
245 // Get room member's information from xmlndata.
246 // The variables must be initialized before calling this function,
247 // because they are not touched if the relevant information is missing.
248 static void muc_get_item_info(const char *from, LmMessageNode *xmldata,
249 enum imrole *mbrole, enum imaffiliation *mbaffil,
250 const char **mbjid, const char **mbnick,
251 const char **actorjid, const char **reason)
252 {
253 LmMessageNode *y, *z;
254 const char *p;
255
256 y = lm_message_node_find_child(xmldata, "item");
257 if (!y)
258 return;
259
260 p = lm_message_node_get_attribute(y, "affiliation");
261 if (p) {
262 if (!strcmp(p, "owner")) *mbaffil = affil_owner;
263 else if (!strcmp(p, "admin")) *mbaffil = affil_admin;
264 else if (!strcmp(p, "member")) *mbaffil = affil_member;
265 else if (!strcmp(p, "outcast")) *mbaffil = affil_outcast;
266 else if (!strcmp(p, "none")) *mbaffil = affil_none;
267 else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown affiliation \"%s\"",
268 from, p);
269 }
270 p = lm_message_node_get_attribute(y, "role");
271 if (p) {
272 if (!strcmp(p, "moderator")) *mbrole = role_moderator;
273 else if (!strcmp(p, "participant")) *mbrole = role_participant;
274 else if (!strcmp(p, "visitor")) *mbrole = role_visitor;
275 else if (!strcmp(p, "none")) *mbrole = role_none;
276 else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown role \"%s\"",
277 from, p);
278 }
279 *mbjid = lm_message_node_get_attribute(y, "jid");
280 *mbnick = lm_message_node_get_attribute(y, "nick");
281 // For kick/ban, there can be actor and reason tags
282 *reason = lm_message_node_get_child_value(y, "reason");
283 z = lm_message_node_find_child(y, "actor");
284 if (z)
285 *actorjid = lm_message_node_get_attribute(z, "jid");
286 }
287
288 // muc_handle_join(...)
289 // Handle a join event in a MUC room.
290 // This function will return the new_member value TRUE if somebody else joins
291 // the room (and FALSE if _we_ are joining the room).
292 static bool muc_handle_join(const GSList *room_elt, const char *rname,
293 const char *roomjid, const char *ournick,
294 enum room_printstatus printstatus,
295 time_t usttime, int log_muc_conf)
296 {
297 bool new_member = FALSE; // True if somebody else joins the room (not us)
298 gchar *mbuf;
299
300 if (!buddy_getinsideroom(room_elt->data)) {
301 // We weren't inside the room yet. Now we are.
302 // However, this could be a presence packet from another room member
303
304 buddy_setinsideroom(room_elt->data, TRUE);
305 // Set the message flag unless we're already in the room buffer window
306 scr_setmsgflag_if_needed(roomjid, FALSE);
307 // Add a message to the tracelog file
308 mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, ournick);
309 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf);
310 g_free(mbuf);
311 mbuf = g_strdup_printf("You have joined as \"%s\"", ournick);
312
313 // The 1st presence message could be for another room member
314 if (strcmp(ournick, rname)) {
315 // Display current mbuf and create a new message for the member
316 // Note: the usttime timestamp is related to the other member,
317 // so we use 0 here.
318 scr_WriteIncomingMessage(roomjid, mbuf, 0,
319 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
320 if (log_muc_conf)
321 hlog_write_message(roomjid, 0, -1, mbuf);
322 g_free(mbuf);
323 if (printstatus != status_none)
324 mbuf = g_strdup_printf("%s has joined", rname);
325 else
326 mbuf = NULL;
327 new_member = TRUE;
328 }
329 } else {
330 mbuf = NULL;
331 if (strcmp(ournick, rname)) {
332 if (printstatus != status_none)
333 mbuf = g_strdup_printf("%s has joined", rname);
334 new_member = TRUE;
335 }
336 }
337
338 if (mbuf) {
339 guint msgflags = HBB_PREFIX_INFO;
340 if (!settings_opt_get_int("muc_flag_joins"))
341 msgflags |= HBB_PREFIX_NOFLAG;
342 scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0);
343 if (log_muc_conf)
344 hlog_write_message(roomjid, 0, -1, mbuf);
345 g_free(mbuf);
346 }
347
348 return new_member;
349 }
350
351 static void handle_muc_presence(const char *from, LmMessageNode *xmldata,
352 const char *roomjid, const char *rname,
353 enum imstatus ust, const char *ustmsg,
354 time_t usttime, char bpprio)
355 {
356 LmMessageNode *y;
357 const char *p;
358 char *mbuf;
359 const char *ournick;
360 enum imrole mbrole = role_none;
361 enum imaffiliation mbaffil = affil_none;
362 enum room_printstatus printstatus;
363 enum room_autowhois autowhois;
364 const char *mbjid = NULL, *mbnick = NULL;
365 const char *actorjid = NULL, *reason = NULL;
366 bool new_member = FALSE; // True if somebody else joins the room (not us)
367 guint statuscode = 0;
368 guint nickchange = 0;
369 GSList *room_elt;
370 int log_muc_conf;
371 guint msgflags;
372
373 log_muc_conf = settings_opt_get_int("log_muc_conf");
374
375 room_elt = roster_find(roomjid, jidsearch, 0);
376 if (!room_elt) {
377 // Add room if it doesn't already exist
378 // It shouldn't happen, there is probably something wrong (server or
379 // network issue?)
380 room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM,
381 sub_none, -1);
382 scr_LogPrint(LPRINT_LOGNORM, "Strange MUC presence message");
383 } else {
384 // Make sure this is a room (it can be a conversion user->room)
385 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
386 }
387
388 // Get room member's information
389 muc_get_item_info(from, xmldata, &mbrole, &mbaffil, &mbjid, &mbnick,
390 &actorjid, &reason);
391
392 // Get our room nickname
393 ournick = buddy_getnickname(room_elt->data);
394
395 if (!ournick) {
396 // It shouldn't happen, probably a server issue
397 mbuf = g_strdup_printf("Unexpected groupchat packet!");
398
399 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf);
400 scr_WriteIncomingMessage(roomjid, mbuf, 0, HBB_PREFIX_INFO, 0);
401 g_free(mbuf);
402 // Send back an unavailable packet
403 xmpp_setstatus(offline, roomjid, "", TRUE);
404 scr_DrawRoster();
405 return;
406 }
407
408 // Get the status code
409 // 201: a room has been created
410 // 301: the user has been banned from the room
411 // 303: new room nickname
412 // 307: the user has been kicked from the room
413 // 321,322,332: the user has been removed from the room
414 y = lm_message_node_find_child(xmldata, "status");
415 if (y) {
416 p = lm_message_node_get_attribute(y, "code");
417 if (p)
418 statuscode = atoi(p);
419 }
420
421 // Get the room's "print_status" settings
422 printstatus = buddy_getprintstatus(room_elt->data);
423 if (printstatus == status_default) {
424 printstatus = (guint) settings_opt_get_int("muc_print_status");
425 if (printstatus > 3)
426 printstatus = status_default;
427 }
428
429 // A new room has been created; accept MUC default config
430 if (statuscode == 201)
431 xmpp_room_unlock(roomjid);
432
433 // Check for nickname change
434 if (statuscode == 303 && mbnick) {
435 mbuf = g_strdup_printf("%s is now known as %s", rname, mbnick);
436 scr_WriteIncomingMessage(roomjid, mbuf, usttime,
437 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
438 if (log_muc_conf)
439 hlog_write_message(roomjid, 0, -1, mbuf);
440 g_free(mbuf);
441 buddy_resource_setname(room_elt->data, rname, mbnick);
442 // Maybe it's _our_ nickname...
443 if (ournick && !strcmp(rname, ournick))
444 buddy_setnickname(room_elt->data, mbnick);
445 nickchange = TRUE;
446 }
447
448 // Check for departure/arrival
449 if (!mbnick && ust == offline) {
450 // Somebody is leaving
451 enum { leave=0, kick, ban } how = leave;
452 bool we_left = FALSE;
453
454 if (statuscode == 307)
455 how = kick;
456 else if (statuscode == 301)
457 how = ban;
458
459 // If this is a leave, check if it is ourself
460 if (ournick && !strcmp(rname, ournick)) {
461 we_left = TRUE; // _We_ have left! (kicked, banned, etc.)
462 buddy_setinsideroom(room_elt->data, FALSE);
463 buddy_setnickname(room_elt->data, NULL);
464 buddy_del_all_resources(room_elt->data);
465 buddy_settopic(room_elt->data, NULL);
466 scr_UpdateChatStatus(FALSE);
467 update_roster = TRUE;
468 }
469
470 // The message depends on _who_ left, and _how_
471 if (how) {
472 gchar *mbuf_end;
473 // Forced leave
474 if (actorjid) {
475 mbuf_end = g_strdup_printf("%s from %s by <%s>.\nReason: %s",
476 (how == ban ? "banned" : "kicked"),
477 roomjid, actorjid, reason);
478 } else {
479 mbuf_end = g_strdup_printf("%s from %s.",
480 (how == ban ? "banned" : "kicked"),
481 roomjid);
482 }
483 if (we_left)
484 mbuf = g_strdup_printf("You have been %s", mbuf_end);
485 else
486 mbuf = g_strdup_printf("%s has been %s", rname, mbuf_end);
487
488 g_free(mbuf_end);
489 } else {
490 // Natural leave
491 if (we_left) {
492 LmMessageNode *destroynode = lm_message_node_find_child(xmldata,
493 "destroy");
494 if (destroynode) {
495 if ((reason = lm_message_node_get_child_value(destroynode,
496 "reason"))) {
497 mbuf = g_strdup_printf("You have left %s, "
498 "the room has been destroyed: %s",
499 roomjid, reason);
500 } else {
501 mbuf = g_strdup_printf("You have left %s, "
502 "the room has been destroyed", roomjid);
503 }
504 } else {
505 mbuf = g_strdup_printf("You have left %s", roomjid);
506 }
507 } else {
508 if (ust != offline) {
509 // This can happen when a network failure occurs,
510 // this isn't an official leave but the user isn't there anymore.
511 mbuf = g_strdup_printf("%s has disappeared!", rname);
512 ust = offline;
513 } else {
514 if (ustmsg)
515 mbuf = g_strdup_printf("%s has left: %s", rname, ustmsg);
516 else
517 mbuf = g_strdup_printf("%s has left", rname);
518 }
519 }
520 }
521
522 // Display the mbuf message if we're concerned
523 // or if the print_status isn't set to none.
524 if (we_left || printstatus != status_none) {
525 msgflags = HBB_PREFIX_INFO;
526 if (!we_left && settings_opt_get_int("muc_flag_joins") != 2)
527 msgflags |= HBB_PREFIX_NOFLAG;
528 scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0);
529 }
530
531 if (log_muc_conf)
532 hlog_write_message(roomjid, 0, -1, mbuf);
533
534 if (we_left) {
535 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf);
536 g_free(mbuf);
537 return;
538 }
539 g_free(mbuf);
540 } else if (buddy_getstatus(room_elt->data, rname) == offline &&
541 ust != offline) {
542 // Somebody is joining
543 new_member = muc_handle_join(room_elt, rname, roomjid, ournick,
544 printstatus, usttime, log_muc_conf);
545 } else {
546 // This is a simple member status change
547
548 if (printstatus == status_all && !nickchange) {
549 mbuf = g_strdup_printf("Member status has changed: %s [%c] %s", rname,
550 imstatus2char[ust], ((ustmsg) ? ustmsg : ""));
551 scr_WriteIncomingMessage(roomjid, mbuf, usttime,
552 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
553 g_free(mbuf);
554 }
555 }
556
557 // Sanity check, shouldn't happen...
558 if (!rname)
559 return;
560
561 // Update room member status
562 roster_setstatus(roomjid, rname, bpprio, ust, ustmsg, usttime,
563 mbrole, mbaffil, mbjid);
564
565 autowhois = buddy_getautowhois(room_elt->data);
566 if (autowhois == autowhois_default)
567 autowhois = (settings_opt_get_int("muc_auto_whois") ?
568 autowhois_on : autowhois_off);
569
570 if (new_member && autowhois == autowhois_on) {
571 // FIXME: This will fail for some UTF-8 nicknames.
572 gchar *joiner_nick = from_utf8(rname);
573 cmd_room_whois(room_elt->data, joiner_nick, FALSE);
574 g_free(joiner_nick);
575 }
576
577 scr_DrawRoster();
578 }
579
580 static void roompresence(gpointer room, void *presencedata)
581 {
582 const char *bjid;
583 const char *nickname;
584 char *to;
585 struct T_presence *pres = presencedata;
586
587 if (!buddy_getinsideroom(room))
588 return;
589
590 bjid = buddy_getjid(room);
591 if (!bjid) return;
592 nickname = buddy_getnickname(room);
593 if (!nickname) return;
594
595 to = g_strdup_printf("%s/%s", bjid, nickname);
596 xmpp_setstatus(pres->st, to, pres->msg, TRUE);
597 g_free(to);
598 }
599
600 // got_invite(from, to, reason, passwd)
601 // This function should be called when receiving an invitation from user
602 // "from", to enter the room "to". Optional reason and room password can
603 // be provided.
604 static void got_invite(const char* from, const char *to, const char* reason,
605 const char* passwd)
606 {
607 eviqs *evn;
608 event_muc_invitation *invitation;
609 GString *sbuf;
610 char *barejid;
611 GSList *room_elt;
612
613 sbuf = g_string_new("");
614 if (reason) {
615 g_string_printf(sbuf,
616 "Received an invitation to <%s>, from <%s>, reason: %s",
617 to, from, reason);
618 } else {
619 g_string_printf(sbuf, "Received an invitation to <%s>, from <%s>",
620 to, from);
621 }
622
623 barejid = jidtodisp(from);
624 scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
625 scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
626
627 evn = evs_new(EVS_TYPE_INVITATION, EVS_MAX_TIMEOUT);
628 if (evn) {
629 evn->callback = &evscallback_invitation;
630 invitation = g_new(event_muc_invitation, 1);
631 invitation->to = g_strdup(to);
632 invitation->from = g_strdup(from);
633 invitation->passwd = g_strdup(passwd);
634 invitation->reason = g_strdup(reason);
635 evn->data = invitation;
636 evn->desc = g_strdup_printf("<%s> invites you to %s ", from, to);
637 g_string_printf(sbuf, "Please use /event %s accept|reject", evn->id);
638 } else {
639 g_string_printf(sbuf, "Unable to create a new event!");
640 }
641 scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
642 scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
643 g_string_free(sbuf, TRUE);
644 g_free(barejid);
645
646 // Make sure the MUC room barejid is a room in the roster
647 barejid = jidtodisp(to);
648 room_elt = roster_find(barejid, jidsearch, 0);
649 if (room_elt)
650 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
651
652 g_free(barejid);
653 }
654
655
656 // Specific MUC message handling (for example invitation processing)
657 static void got_muc_message(const char *from, LmMessageNode *x)
658 {
659 LmMessageNode *invite = lm_message_node_get_child(x, "invite");
660 if (invite)
661 {
662 const char *invite_from;
663 const char *reason = NULL;
664 const char *password = NULL;
665
666 invite_from = lm_message_node_get_attribute(invite, "from");
667 reason = lm_message_node_get_child_value(invite, "reason");
668 password = lm_message_node_get_child_value(invite, "password");
669 if (invite_from)
670 got_invite(invite_from, from, reason, password);
671 }
672 // TODO
673 // handle status code = 100 ( not anonymous )
674 // handle status code = 170 ( changement de config )
675 // 10.2.1 Notification of Configuration Changes
676 // declined invitation
677 }
678