Add support for XEP-0249 / Direct MUC Invitations (Myhailo Danylenko)
Patch merged from isbear's mcabber-experimental repository.
--- a/mcabber/mcabber/xmpp.c Mon Mar 14 12:50:18 2011 +0100
+++ b/mcabber/mcabber/xmpp.c Mon Mar 14 12:53:27 2011 +0100
@@ -1295,6 +1295,18 @@
x = lm_message_node_find_xmlns(m->node, NS_MUC_USER);
if (x && !strcmp(x->name, "x"))
got_muc_message(from, x);
+
+ x = lm_message_node_find_xmlns(m->node, NS_X_CONFERENCE);
+
+ if (x && !strcmp(x->name, "x")) {
+ const char *jid = lm_message_node_get_attribute(x, "jid");
+ if (jid) {
+ const char *reason = lm_message_node_get_attribute(x, "reason");
+ const char *password = lm_message_node_get_attribute(x, "password");
+ // FIXME we shouldn't send decline stanzas in this case
+ got_invite(from, jid, reason, password, FALSE);
+ }
+ }
}
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
--- a/mcabber/mcabber/xmpp_defines.h Mon Mar 14 12:50:18 2011 +0100
+++ b/mcabber/mcabber/xmpp_defines.h Mon Mar 14 12:53:27 2011 +0100
@@ -27,6 +27,8 @@
#define NS_BROWSE "jabber:iq:browse"
#define NS_EVENT "jabber:x:event"
#define NS_CONFERENCE "jabber:iq:conference"
+// direct muc invitation (xep-0249)
+#define NS_X_CONFERENCE "jabber:x:conference"
#define NS_SIGNED "jabber:x:signed"
#define NS_ENCRYPTED "jabber:x:encrypted"
#define NS_GATEWAY "jabber:iq:gateway"
--- a/mcabber/mcabber/xmpp_helper.c Mon Mar 14 12:50:18 2011 +0100
+++ b/mcabber/mcabber/xmpp_helper.c Mon Mar 14 12:53:27 2011 +0100
@@ -234,6 +234,7 @@
caps_add_feature("", NS_PING);
caps_add_feature("", NS_COMMANDS);
caps_add_feature("", NS_RECEIPTS);
+ caps_add_feature("", NS_X_CONFERENCE);
if (!settings_opt_get_int("iq_last_disable") &&
(!settings_opt_get_int("iq_last_disable_when_notavail") ||
status != notavail))
--- a/mcabber/mcabber/xmpp_muc.c Mon Mar 14 12:50:18 2011 +0100
+++ b/mcabber/mcabber/xmpp_muc.c Mon Mar 14 12:53:27 2011 +0100
@@ -39,6 +39,8 @@
extern enum imstatus mystatus;
extern gchar *mystatusmsg;
+static GSList *invitations = NULL;
+
static void decline_invitation(event_muc_invitation *invitation, const char *reason)
{
// cut and paste from xmpp_room_invite
@@ -65,10 +67,12 @@
void destroy_event_muc_invitation(event_muc_invitation *invitation)
{
+ invitations = g_slist_remove(invitations, invitation);
g_free(invitation->to);
g_free(invitation->from);
g_free(invitation->passwd);
g_free(invitation->reason);
+ g_free(invitation->evid);
g_free(invitation);
}
@@ -104,7 +108,8 @@
g_free(nickname);
} else {
scr_LogPrint(LPRINT_LOGNORM, "Invitation to %s refused.", invitation->to);
- decline_invitation(invitation, arg);
+ if (invitation->reply)
+ decline_invitation(invitation, arg);
}
return FALSE;
@@ -643,14 +648,12 @@
g_free(to);
}
-// got_invite(from, to, reason, passwd)
+// got_invite(from, to, reason, passwd, reply)
// This function should be called when receiving an invitation from user
// "from", to enter the room "to". Optional reason and room password can
// be provided.
-// TODO: check for duplicate invites (need an existing invitation registry
-// for that).
-static void got_invite(const char* from, const char *to, const char* reason,
- const char* passwd)
+void got_invite(const char* from, const char *to, const char* reason,
+ const char* passwd, gboolean reply)
{
GString *sbuf;
char *barejid;
@@ -670,7 +673,21 @@
scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
- {
+ { // remove any equal older invites
+ GSList *iel = invitations;
+ while (iel) {
+ event_muc_invitation *invitation = iel->data;
+ iel = iel -> next;
+ if (!g_strcmp0(to, invitation->to) &&
+ !g_strcmp0(passwd, invitation->passwd)) {
+ scr_LogPrint(LPRINT_DEBUG, "Destroying previous invitation event %s.",
+ invitation->evid);
+ evs_del(invitation->evid);
+ }
+ }
+ }
+
+ { // create event
const char *id;
char *desc = g_strdup_printf("<%s> invites you to %s", from, to);
event_muc_invitation *invitation;
@@ -680,13 +697,18 @@
invitation->from = g_strdup(from);
invitation->passwd = g_strdup(passwd);
invitation->reason = g_strdup(reason);
+ invitation->reply = reply;
+ invitation->evid = NULL;
+
+ invitations = g_slist_append(invitations, invitation);
id = evs_new(desc, NULL, 0, evscallback_invitation, invitation,
(GDestroyNotify)destroy_event_muc_invitation);
g_free(desc);
- if (id)
+ if (id) {
+ invitation->evid = g_strdup(id);
g_string_printf(sbuf, "Please use /event %s accept|reject", id);
- else
+ } else
g_string_printf(sbuf, "Unable to create a new event!");
}
scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
@@ -718,7 +740,7 @@
reason = lm_message_node_get_child_value(invite, "reason");
password = lm_message_node_get_child_value(invite, "password");
if (invite_from)
- got_invite(invite_from, from, reason, password);
+ got_invite(invite_from, from, reason, password, TRUE);
}
// TODO
// handle status code = 100 ( not anonymous )
--- a/mcabber/mcabber/xmpp_muc.h Mon Mar 14 12:50:18 2011 +0100
+++ b/mcabber/mcabber/xmpp_muc.h Mon Mar 14 12:53:27 2011 +0100
@@ -6,10 +6,14 @@
char *from;
char *passwd;
char *reason;
+ char *evid;
+ gboolean reply;
} event_muc_invitation;
void destroy_event_muc_invitation(event_muc_invitation *invitation);
void roompresence(gpointer room, void *presencedata);
+void got_invite(const char* from, const char *to, const char* reason,
+ const char* passwd, gboolean reply);
void got_muc_message(const char *from, LmMessageNode *x);
void handle_muc_presence(const char *from, LmMessageNode * xmldata,
const char *roomjid, const char *rname,