Improve MUC presence messages handling
- Display messages when someone joins, leaves, or changes his nickname
- Update occupants roles and real jid (if available)
- Fix some memory leaks
--- a/mcabber/src/hooks.c Sat Oct 01 16:00:17 2005 +0200
+++ b/mcabber/src/hooks.c Sat Oct 01 18:53:14 2005 +0200
@@ -114,7 +114,7 @@
imstatus2char[roster_getstatus(jid, resname)],
imstatus2char[status], jid, rn,
((status_msg) ? status_msg : ""));
- roster_setstatus(jid, rn, prio, status, status_msg);
+ roster_setstatus(jid, rn, prio, status, status_msg, role_none, NULL);
buddylist_build();
scr_DrawRoster();
hlog_write_status(jid, 0, status, status_msg);
--- a/mcabber/src/jabglue.c Sat Oct 01 16:00:17 2005 +0200
+++ b/mcabber/src/jabglue.c Sat Oct 01 18:53:14 2005 +0200
@@ -1017,17 +1017,70 @@
for ( ; x; x = xmlnode_get_nextsibling(x)) {
if ((p = xmlnode_get_name(x)) && !strcmp(p, "x"))
if ((p = xmlnode_get_attrib(x, "xmlns")) &&
- !strncasecmp(p, "http://jabber.org/protocol/muc", 30))
+ !strcasecmp(p, "http://jabber.org/protocol/muc#user"))
break;
}
if (x) { // This is a MUC presence message
- roster_add_user(r, NULL, NULL, ROSTER_TYPE_ROOM);
+ enum imrole mbrole = role_none;
+ const char *mbrjid = NULL;
+ const char *mbnewnick = NULL;
+ GSList *room_elt;
+
+ // Add room if it doesn't already exist
+ room_elt = roster_add_user(r, NULL, NULL, ROSTER_TYPE_ROOM);
+
+ // Get room member's information
+ y = xmlnode_get_tag(x, "item");
+ if (y) {
+ p = xmlnode_get_attrib(y, "role");
+ if (p) {
+ if (!strcmp(p, "moderator")) mbrole = role_moderator;
+ else if (!strcmp(p, "participant")) mbrole = role_participant;
+ else if (!strcmp(p, "visitor")) mbrole = role_visitor;
+ else if (!strcmp(p, "none")) mbrole = role_none;
+ else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown role \"%s\"",
+ from, p);
+ }
+ p = xmlnode_get_attrib(y, "jid");
+ if (p) mbrjid = p;
+ p = xmlnode_get_attrib(y, "nick");
+ if (p) mbnewnick = p;
+ }
+ // Check for nickname change
+ y = xmlnode_get_tag(x, "status");
+ if (y && mbnewnick) {
+ p = xmlnode_get_attrib(y, "code");
+ if (p && !strcmp(p, "303")) {
+ gchar *mbuf;
+ mbuf = g_strdup_printf("%s is now known as %s", rname, mbnewnick);
+ scr_WriteIncomingMessage(r, mbuf, 0, HBB_PREFIX_INFO);
+ g_free(mbuf);
+ buddy_resource_setname(room_elt->data, rname, mbnewnick);
+ }
+ }
+
+ // Check for departure/arrival
+ if (!mbnewnick && mbrole == role_none) {
+ gchar *mbuf = g_strdup_printf("%s has left", rname);
+ scr_WriteIncomingMessage(r, mbuf, 0, HBB_PREFIX_INFO);
+ g_free(mbuf);
+ } else if (buddy_getstatus(room_elt->data, rname) == offline &&
+ ust != offline) {
+ gchar *mbuf = g_strdup_printf("%s has joined", rname);
+ scr_WriteIncomingMessage(r, mbuf, 0, HBB_PREFIX_INFO);
+ g_free(mbuf);
+ }
+
+ // Update room member status
if (rname)
- roster_setstatus(r, rname, bpprio, ust, NULL);
+ roster_setstatus(r, rname, bpprio, ust, NULL, mbrole, mbrjid);
else
scr_LogPrint(LPRINT_LOGNORM, "MUC DBG: no rname!"); /* DBG */
+ g_free(r);
+ if (s) g_free(s);
+
buddylist_build();
scr_DrawRoster();
break;
--- a/mcabber/src/roster.c Sat Oct 01 16:00:17 2005 +0200
+++ b/mcabber/src/roster.c Sat Oct 01 18:53:14 2005 +0200
@@ -370,8 +370,11 @@
}
}
+// roster_setstatus()
+// Note: resname, role and realjid are for room members only
void roster_setstatus(const char *jid, const char *resname, gchar prio,
- enum imstatus bstat, const char *status_msg)
+ enum imstatus bstat, const char *status_msg,
+ enum imrole role, const char *realjid)
{
GSList *sl_user;
roster *roster_usr;
@@ -403,6 +406,15 @@
}
if (status_msg)
p_res->status_msg = g_strdup(status_msg);
+
+ p_res->role = role;
+
+ if (p_res->realjid) {
+ g_free((gchar*)p_res->realjid);
+ p_res->realjid = NULL;
+ }
+ if (realjid)
+ p_res->realjid = g_strdup(realjid);
}
// roster_setflags()
@@ -835,6 +847,23 @@
return reslist;
}
+// buddy_resource_setname(roster_data, oldname, newname)
+// Useful for nickname change in a MUC room
+void buddy_resource_setname(gpointer rosterdata, const char *resname,
+ const char *newname)
+{
+ roster *roster_usr = rosterdata;
+ res *p_res = get_resource(roster_usr, resname);
+ if (p_res) {
+ if (p_res->name) {
+ g_free((gchar*)p_res->name);
+ p_res->name = NULL;
+ }
+ if (newname)
+ p_res->name = g_strdup(newname);
+ }
+}
+
// buddy_del_all_resources()
// Remove all resources from the specified buddy
void buddy_del_all_resources(gpointer rosterdata)
--- a/mcabber/src/roster.h Sat Oct 01 16:00:17 2005 +0200
+++ b/mcabber/src/roster.h Sat Oct 01 18:53:14 2005 +0200
@@ -53,7 +53,8 @@
void roster_del_user(const char *jid);
void roster_free(void);
void roster_setstatus(const char *jid, const char *resname, gchar prio,
- enum imstatus bstat, const char *status_msg);
+ enum imstatus bstat, const char *status_msg,
+ enum imrole role, const char *realjid);
void roster_setflags(const char *jid, guint flags, guint value);
void roster_msg_setflag(const char *jid, guint value);
void roster_settype(const char *jid, guint type);
@@ -78,6 +79,8 @@
const char *buddy_getstatusmsg(gpointer rosterdata, const char *resname);
gchar buddy_getresourceprio(gpointer rosterdata, const char *resname);
GSList *buddy_getresources(gpointer rosterdata);
+void buddy_resource_setname(gpointer rosterdata, const char *resname,
+ const char *newname);
void buddy_del_all_resources(gpointer rosterdata);
void buddy_setflags(gpointer rosterdata, guint flags, guint value);
guint buddy_getflags(gpointer rosterdata);