# HG changeset patch # User Mikael Berthe # Date 1300105037 -3600 # Node ID 9f443617e96ba75742c21fd0e13a96486d3d96c9 # Parent 975f6f26b0520006f3d7ea9f5b37fab8292fc4b0 Improve MUC support (Myhailo Danylenko) This patch should allow handling of multiple statuses in MUC rooms. Patch merged from isbear's mcabber-experimental repository. diff -r 975f6f26b052 -r 9f443617e96b mcabber/mcabber/xmpp.c --- a/mcabber/mcabber/xmpp.c Mon Mar 14 13:07:55 2011 +0100 +++ b/mcabber/mcabber/xmpp.c Mon Mar 14 13:17:17 2011 +0100 @@ -1294,7 +1294,7 @@ if (from) { x = lm_message_node_find_xmlns(m->node, NS_MUC_USER); if (x && !strcmp(x->name, "x")) - got_muc_message(from, x); + got_muc_message(from, x, timestamp); x = lm_message_node_find_xmlns(m->node, NS_X_CONFERENCE); diff -r 975f6f26b052 -r 9f443617e96b mcabber/mcabber/xmpp_muc.c --- a/mcabber/mcabber/xmpp_muc.c Mon Mar 14 13:07:55 2011 +0100 +++ b/mcabber/mcabber/xmpp_muc.c Mon Mar 14 13:17:17 2011 +0100 @@ -401,8 +401,6 @@ enum imstatus ust, const char *ustmsg, time_t usttime, char bpprio) { - LmMessageNode *y; - const char *p; char *mbuf; const char *ournick; enum imrole mbrole = role_none; @@ -412,6 +410,8 @@ const char *mbjid = NULL, *mbnick = NULL; const char *actorjid = NULL, *reason = NULL; bool new_member = FALSE; // True if somebody else joins the room (not us) + bool our_presence = FALSE; // True if this presence is from us (i.e. bears + // code 110) guint statuscode = 0; guint nickchange = 0; GSList *room_elt; @@ -442,30 +442,95 @@ if (!ournick) { // It shouldn't happen, probably a server issue - mbuf = g_strdup_printf("Unexpected groupchat packet!"); - - scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); - scr_WriteIncomingMessage(roomjid, mbuf, 0, HBB_PREFIX_INFO, 0); - g_free(mbuf); + const gchar msg[] = "Unexpected groupchat packet!"; + scr_LogPrint(LPRINT_LOGNORM, msg); + scr_WriteIncomingMessage(roomjid, msg, 0, HBB_PREFIX_INFO, 0); // Send back an unavailable packet xmpp_setstatus(offline, roomjid, "", TRUE); scr_draw_roster(); return; } - // Get the status code - // 201: a room has been created - // 301: the user has been banned from the room - // 303: new room nickname - // 307: the user has been kicked from the room - // 321,322,332: the user has been removed from the room - y = lm_message_node_find_child(xmldata, "status"); - if (y) { - p = lm_message_node_get_attribute(y, "code"); - if (p) - statuscode = atoi(p); +#define SETSTATUSCODE(VALUE) \ +{ \ + if (G_UNLIKELY(statuscode)) \ + scr_LogPrint(LPRINT_DEBUG, "handle_muc_presence: WARNING: " \ + "replacing status code %u with %u.", statuscode, VALUE); \ + statuscode = VALUE; \ +} + + { // Get the status code + LmMessageNode *node; + for (node = xmldata -> children; node; node = node -> next) { + if (!g_strcmp0(node -> name, "status")) { + const char *codestr = lm_message_node_get_attribute(node, "code"); + if (codestr) { + const char *mesg = NULL; + switch (atoi(codestr)) { + // initial + case 100: + mesg = "The room is not anonymous."; + break; + case 110: // It is our presence + our_presence = TRUE; + break; + // initial + case 170: + mesg = "The room is logged."; + break; + // initial + case 201: // Room created + SETSTATUSCODE(201); + break; + // initial + case 210: // Your nick change (on join) + // FIXME: print nick + mesg = "The room has changed your nick!"; + buddy_setnickname(room_elt->data, rname); + ournick = rname; + break; + case 301: // User banned + SETSTATUSCODE(301); + break; + case 303: // Nick change + SETSTATUSCODE(303); + break; + case 307: // User kicked + SETSTATUSCODE(307); + break; + // XXX (next three) + case 321: + mesg = "User leaves room due to affilation change."; + break; + case 322: + mesg = "User leaves room, as room is only for members now."; + break; + case 332: + mesg = "User leaves room due to system shutdown."; + break; + default: + scr_LogPrint(LPRINT_DEBUG, + "handle_muc_presence: Unknown MUC status code: %s.", + codestr); + break; + } + if (mesg) { + scr_WriteIncomingMessage(roomjid, mesg, usttime, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); + if (log_muc_conf) + hlog_write_message(roomjid, 0, -1, mesg); + } + } + } + } } +#undef SETSTATUSCODE + + if (!our_presence) + if (ournick && !strcmp(ournick, rname)) + our_presence = TRUE; + // Get the room's "print_status" settings printstatus = buddy_getprintstatus(room_elt->data); if (printstatus == status_default) { @@ -488,7 +553,7 @@ g_free(mbuf); buddy_resource_setname(room_elt->data, rname, mbnick); // Maybe it's _our_ nickname... - if (ournick && !strcmp(rname, ournick)) + if (our_presence) buddy_setnickname(room_elt->data, mbnick); nickchange = TRUE; } @@ -497,7 +562,6 @@ if (statuscode != 303 && ust == offline) { // Somebody is leaving enum { leave=0, kick, ban } how = leave; - bool we_left = FALSE; if (statuscode == 307) how = kick; @@ -505,8 +569,7 @@ how = ban; // If this is a leave, check if it is ourself - if (ournick && !strcmp(rname, ournick)) { - we_left = TRUE; // _We_ have left! (kicked, banned, etc.) + if (our_presence) { buddy_setinsideroom(room_elt->data, FALSE); buddy_setnickname(room_elt->data, NULL); buddy_del_all_resources(room_elt->data); @@ -531,7 +594,7 @@ } if (reason) reason_msg = g_strdup_printf("\nReason: %s", reason); - if (we_left) + if (our_presence) mbuf = g_strdup_printf("You have been %s%s", mbuf_end, reason_msg ? reason_msg : ""); else @@ -542,7 +605,7 @@ g_free(mbuf_end); } else { // Natural leave - if (we_left) { + if (our_presence) { LmMessageNode *destroynode = lm_message_node_find_child(xmldata, "destroy"); if (destroynode) { @@ -575,9 +638,9 @@ // Display the mbuf message if we're concerned // or if the print_status isn't set to none. - if (we_left || printstatus != status_none) { + if (our_presence || printstatus != status_none) { msgflags = HBB_PREFIX_INFO; - if (!we_left && settings_opt_get_int("muc_flag_joins") != 2) + if (!our_presence && settings_opt_get_int("muc_flag_joins") != 2) msgflags |= HBB_PREFIX_NOFLAG; scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0); } @@ -585,26 +648,31 @@ if (log_muc_conf) hlog_write_message(roomjid, 0, -1, mbuf); - if (we_left) { + if (our_presence) { scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); g_free(mbuf); return; } g_free(mbuf); - } else if (buddy_getstatus(room_elt->data, rname) == offline && - ust != offline) { - // Somebody is joining - new_member = muc_handle_join(room_elt, rname, roomjid, ournick, - printstatus, usttime, log_muc_conf); } else { - // This is a simple member status change + enum imstatus old_ust = buddy_getstatus(room_elt->data, rname); + if (old_ust == offline && ust != offline) { + // Somebody is joining + new_member = muc_handle_join(room_elt, rname, roomjid, ournick, + printstatus, usttime, log_muc_conf); + } else { + // This is a simple member status change - if (printstatus == status_all && !nickchange) { - mbuf = g_strdup_printf("Member status has changed: %s [%c] %s", rname, - imstatus2char[ust], ((ustmsg) ? ustmsg : "")); - scr_WriteIncomingMessage(roomjid, mbuf, usttime, - HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); - g_free(mbuf); + if (printstatus == status_all && !nickchange) { + const char *old_ustmsg = buddy_getstatusmsg(room_elt->data, rname); + if (old_ust != ust || g_strcmp0(old_ustmsg, ustmsg)) { + mbuf = g_strdup_printf("Member status has changed: %s [%c] %s", rname, + imstatus2char[ust], ((ustmsg) ? ustmsg : "")); + scr_WriteIncomingMessage(roomjid, mbuf, usttime, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); + g_free(mbuf); + } + } } } @@ -727,26 +795,90 @@ // Specific MUC message handling (for example invitation processing) -void got_muc_message(const char *from, LmMessageNode *x) +void got_muc_message(const char *from, LmMessageNode *x, time_t timestamp) { - LmMessageNode *invite = lm_message_node_get_child(x, "invite"); - if (invite) - { + LmMessageNode *node; + // invitation + node = lm_message_node_get_child(x, "invite"); + if (node) { const char *invite_from; const char *reason = NULL; const char *password = NULL; - invite_from = lm_message_node_get_attribute(invite, "from"); - reason = lm_message_node_get_child_value(invite, "reason"); - password = lm_message_node_get_child_value(invite, "password"); + invite_from = lm_message_node_get_attribute(node, "from"); + reason = lm_message_node_get_child_value(node, "reason"); + password = lm_message_node_get_child_value(node, "password"); if (invite_from) got_invite(invite_from, from, reason, password, TRUE); } - // TODO - // handle status code = 100 ( not anonymous ) - // handle status code = 170 ( changement de config ) - // 10.2.1 Notification of Configuration Changes + // declined invitation + node = lm_message_node_get_child(x, "decline"); + if (node) { + const char *decline_from = lm_message_node_get_attribute(node, "from"); + const char *reason = lm_message_node_get_child_value(node, "reason"); + if (decline_from) { + if (reason) + scr_LogPrint(LPRINT_LOGNORM, "<%s> declines your invitation: %s.", + from, reason); + else + scr_LogPrint(LPRINT_LOGNORM, "<%s> declines your invitation.", from); + } + } + + // status codes + for (node = x -> children; node; node = node -> next) { + if (!g_strcmp0(node -> name, "status")) { + const char *codestr = lm_message_node_get_attribute(node, "code"); + if (codestr) { + const char *mesg = NULL; + switch (atoi(codestr)) { + // initial + case 100: + mesg = "The room is not anonymous."; + break; + case 101: + mesg = "Your affilation has changed while absent."; + break; + case 102: + mesg = "The room shows unavailable members."; + break; + case 103: + mesg = "The room does not show unavailable members."; + break; + case 104: + mesg = "The room configuration has changed."; + break; + case 170: + mesg = "The room is logged."; + break; + case 171: + mesg = "The room is not logged."; + break; + case 172: + mesg = "The room is not anonymous."; + break; + case 173: + mesg = "The room is semi-anonymous."; + break; + case 174: + mesg = "The room is anonymous."; + break; + default: + scr_LogPrint(LPRINT_DEBUG, + "got_muc_message: Unknown MUC status code: %s.", + codestr); + break; + } + if (mesg) { + scr_WriteIncomingMessage(from, mesg, timestamp, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); + if (settings_opt_get_int("log_muc_conf")) + hlog_write_message(from, 0, -1, mesg); + } + } + } + } } /* vim: set et cindent cinoptions=>2\:2(0 ts=2 sw=2: For Vim users... */ diff -r 975f6f26b052 -r 9f443617e96b mcabber/mcabber/xmpp_muc.h --- a/mcabber/mcabber/xmpp_muc.h Mon Mar 14 13:07:55 2011 +0100 +++ b/mcabber/mcabber/xmpp_muc.h Mon Mar 14 13:17:17 2011 +0100 @@ -14,7 +14,8 @@ 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 got_muc_message(const char *from, LmMessageNode *x, + time_t timestamp); void handle_muc_presence(const char *from, LmMessageNode * xmldata, const char *roomjid, const char *rname, enum imstatus ust, const char *ustmsg,