# HG changeset patch # User Mikael Berthe # Date 1136488857 -3600 # Node ID 68fb0c1dfb1592244a4b17be6de2358f0ceef4e2 # Parent dd73c3dad815eebe96a49e9758d72293bf67f08d MUC: better nickname check when entering a room diff -r dd73c3dad815 -r 68fb0c1dfb15 mcabber/src/commands.c --- a/mcabber/src/commands.c Mon Jan 02 22:07:15 2006 +0100 +++ b/mcabber/src/commands.c Thu Jan 05 20:20:57 2006 +0100 @@ -1483,7 +1483,7 @@ if (nick) scr_LogPrint(LPRINT_NORMAL, "Your nickname is: %s", nick); else - scr_LogPrint(LPRINT_NORMAL, "You have no nickname"); + scr_LogPrint(LPRINT_NORMAL, "You have no nickname in this room"); } else { gchar *cmd; cmd = g_strdup_printf("%s %s", buddy_getjid(bud), arg); diff -r dd73c3dad815 -r 68fb0c1dfb15 mcabber/src/jabglue.c --- a/mcabber/src/jabglue.c Mon Jan 02 22:07:15 2006 +0100 +++ b/mcabber/src/jabglue.c Thu Jan 05 20:20:57 2006 +0100 @@ -576,6 +576,7 @@ { xmlnode x, y; gchar *roomid; + GSList *room_elt; if (!online || !room) return; if (!nickname) return; @@ -588,6 +589,16 @@ return; } + room_elt = roster_find(room, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); + // Add room if it doesn't already exist + if (!room_elt) + room_elt = roster_add_user(room, NULL, NULL, ROSTER_TYPE_ROOM, sub_none); + // If insideroom is TRUE, this is a nickname change and we don't care here + if (!buddy_getinsideroom(room_elt->data)) { + // We're trying to enter a room + buddy_setnickname(room_elt->data, nickname); + } + // Send the XML request x = presnew(mystatus, roomid, mystatusmsg); y = xmlnode_insert_tag(x, "x"); @@ -902,7 +913,7 @@ previous_state = state; } -static time_t xml_get_timestamp(xmlnode xmldata) +inline static xmlnode xml_get_xmlns(xmlnode xmldata, const char *xmlns) { xmlnode x; char *p; @@ -910,10 +921,19 @@ x = xmlnode_get_firstchild(xmldata); for ( ; x; x = xmlnode_get_nextsibling(x)) { if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) - if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, NS_DELAY)) { + if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, xmlns)) { break; } } + return x; +} + +static time_t xml_get_timestamp(xmlnode xmldata) +{ + xmlnode x; + char *p; + + x = xml_get_xmlns(xmldata, NS_DELAY); if ((p = xmlnode_get_attrib(x, "stamp")) != NULL) return from_iso8601(p, 1); return 0; @@ -939,7 +959,7 @@ room_elt = roster_find(roomjid, jidsearch, 0); if (!room_elt) { - // Add room if it doesn't already exist + // Add room if it doesn't already exist FIXME shouldn't happen! room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM, sub_none); } else { // Make sure this is a room (it can be a conversion user->room) @@ -1029,6 +1049,7 @@ if (m && !strcmp(rname, m)) { we_left = TRUE; // _We_ have left! (kicked, banned, etc.) + buddy_setinsideroom(room_elt->data, FALSE); buddy_setnickname(room_elt->data, NULL); buddy_del_all_resources(room_elt->data); buddy_settopic(room_elt->data, NULL); @@ -1105,13 +1126,37 @@ } else if (buddy_getstatus(room_elt->data, rname) == offline && ust != offline) { gchar *mbuf; - if (buddy_getnickname(room_elt->data) == NULL) { - buddy_setnickname(room_elt->data, rname); + if (!buddy_getinsideroom(room_elt->data)) { + const char *ournick = buddy_getnickname(room_elt->data); + // We weren't inside the room yet. Now we are. + // However, this could be a presence packet from another room member + + if (!ournick) { + // I think it shouldn't happen, but let's put a warning for a while... + scr_LogPrint(LPRINT_LOGNORM, "MUC ERR: you have no nickname, " + "please send a bug report!"); + ournick = ""; + buddylist_build(); + scr_DrawRoster(); + return; + } + + buddy_setinsideroom(room_elt->data, TRUE); // Add a message to the tracelog file - mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, rname); + mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, ournick); scr_LogPrint(LPRINT_LOG, "%s", mbuf); g_free(mbuf); - mbuf = g_strdup_printf("You have joined as \"%s\"", rname); + mbuf = g_strdup_printf("You have joined as \"%s\"", ournick); + + // The 1st presence message could be for another room member + if (strcmp(ournick, rname)) { + // Display current mbuf and create a new message for the member + scr_WriteIncomingMessage(roomjid, mbuf, usttime, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG); + if (log_muc_conf) hlog_write_message(roomjid, 0, FALSE, mbuf); + g_free(mbuf); + mbuf = g_strdup_printf("%s has joined", rname); + } } else { mbuf = g_strdup_printf("%s has joined", rname); } @@ -1140,17 +1185,38 @@ { char *p, *r; char *ustmsg; - xmlnode x; const char *rname; enum imstatus ust; char bpprio; time_t timestamp = 0; + xmlnode muc_packet; + + rname = strchr(from, '/'); + if (rname) rname++; r = jidtodisp(from); + + // Check for MUC presence packet + muc_packet = xml_get_xmlns(xmldata, "http://jabber.org/protocol/muc#user"); + if (type && !strcmp(type, TMSG_ERROR)) { + xmlnode x; scr_LogPrint(LPRINT_LOGNORM, "Error presence packet from <%s>", r); if ((x = xmlnode_get_tag(xmldata, TMSG_ERROR)) != NULL) display_server_error(x); + + // Let's check it isn't a nickname conflict. + // XXX Note: We should handle the string condition. + if ((p = xmlnode_get_attrib(x, "code")) != NULL) { + if (atoi(p) == 409) { + // 409 = conlict (nickname is in use or registered by another user) + // If we are not inside this room, we should reset the nickname + GSList *room_elt = roster_find(r, jidsearch, 0); + if (room_elt && !buddy_getinsideroom(room_elt->data)) + buddy_setnickname(room_elt->data, NULL); + } + } + g_free(r); return; } @@ -1181,24 +1247,13 @@ from, p); } - rname = strchr(from, '/'); - if (rname) rname++; - // Timestamp? timestamp = xml_get_timestamp(xmldata); - // Check for MUC presence packet - // There can be multiple tags!! - x = xmlnode_get_firstchild(xmldata); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) - if ((p = xmlnode_get_attrib(x, "xmlns")) && - !strcmp(p, "http://jabber.org/protocol/muc#user")) - break; - } - if (x) { + if (muc_packet) { // This is a MUC presence message - handle_presence_muc(from, x, r, rname, ust, ustmsg, timestamp, bpprio); + handle_presence_muc(from, muc_packet, r, rname, + ust, ustmsg, timestamp, bpprio); } else { // Not a MUC message, so this is a regular buddy... // Call hk_statuschange() if status has changed or if the @@ -1269,17 +1324,10 @@ } } - /* there can be multiple tags. we're looking for one with - xmlns = jabber:x:encrypted */ - - x = xmlnode_get_firstchild(xmldata); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) - if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, NS_ENCRYPTED)) - if ((p = xmlnode_get_data(x)) != NULL) { - enc = p; - break; - } + // Not used yet... + x = xml_get_xmlns(xmldata, NS_ENCRYPTED); + if (x && (p = xmlnode_get_data(x)) != NULL) { + enc = p; } // Timestamp? diff -r dd73c3dad815 -r 68fb0c1dfb15 mcabber/src/roster.c --- a/mcabber/src/roster.c Mon Jan 02 22:07:15 2006 +0100 +++ b/mcabber/src/roster.c Thu Jan 05 20:20:57 2006 +0100 @@ -61,9 +61,15 @@ guint type; enum subscr subscription; GSList *resource; - gchar *nickname; // For groupchats - gchar *topic; // For groupchats + + /* For groupchats */ + gchar *nickname; + gchar *topic; + guint8 inside_room; + + /* Flag used for the UI */ guint flags; + // list: user -> points to his group; group -> points to its users list GSList *list; } roster; @@ -833,6 +839,23 @@ return roster_usr->nickname; } +// buddy_setinsideroom(buddy, inside) +// Only for chatrooms +void buddy_setinsideroom(gpointer rosterdata, guint8 inside) +{ + roster *roster_usr = rosterdata; + + if (!(roster_usr->type & ROSTER_TYPE_ROOM)) return; + + roster_usr->inside_room = inside; +} + +guint8 buddy_getinsideroom(gpointer rosterdata) +{ + roster *roster_usr = rosterdata; + return roster_usr->inside_room; +} + // buddy_settopic(buddy, newtopic) // Only for chatrooms void buddy_settopic(gpointer rosterdata, const char *newtopic) diff -r dd73c3dad815 -r 68fb0c1dfb15 mcabber/src/roster.h --- a/mcabber/src/roster.h Mon Jan 02 22:07:15 2006 +0100 +++ b/mcabber/src/roster.h Thu Jan 05 20:20:57 2006 +0100 @@ -109,6 +109,8 @@ const char *buddy_getname(gpointer rosterdata); void buddy_setnickname(gpointer rosterdata, const char *newname); const char *buddy_getnickname(gpointer rosterdata); +void buddy_setinsideroom(gpointer rosterdata, guint8 inside); +guint8 buddy_getinsideroom(gpointer rosterdata); void buddy_settopic(gpointer rosterdata, const char *newtopic); const char *buddy_gettopic(gpointer rosterdata); void buddy_settype(gpointer rosterdata, guint type);