about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/command/command.c8
-rw-r--r--src/command/commands.c10
-rw-r--r--src/muc.c156
-rw-r--r--src/muc.h5
-rw-r--r--src/server_events.c1
-rw-r--r--src/xmpp/presence.c36
-rw-r--r--src/xmpp/stanza.c12
7 files changed, 208 insertions, 20 deletions
diff --git a/src/command/command.c b/src/command/command.c
index bee26eff..b937aea2 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -307,12 +307,13 @@ static struct cmd_t command_defs[] =
 
     { "/room",
         cmd_room, parse_args, 1, 1, NULL,
-        { "/room accept|destroy|config", "Room configuration.",
-        { "/room accept|destroy|config",
-          "---------------------------",
+        { "/room accept|destroy|config|info", "Room configuration.",
+        { "/room accept|destroy|config|info",
+          "--------------------------------",
           "accept  - Accept default room configuration.",
           "destroy - Reject default room configuration.",
           "config  - Edit room configuration.",
+          "info    - Show room details.",
           NULL } } },
 
     { "/form",
@@ -1226,6 +1227,7 @@ cmd_init(void)
     autocomplete_add(room_ac, "accept");
     autocomplete_add(room_ac, "destroy");
     autocomplete_add(room_ac, "config");
+    autocomplete_add(room_ac, "info");
 
     form_ac = autocomplete_new();
     autocomplete_add(form_ac, "submit");
diff --git a/src/command/commands.c b/src/command/commands.c
index 045ad00a..1551f58c 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -2083,7 +2083,8 @@ cmd_room(gchar **args, struct cmd_help_t help)
 
     if ((g_strcmp0(args[0], "accept") != 0) &&
             (g_strcmp0(args[0], "destroy") != 0) &&
-            (g_strcmp0(args[0], "config") != 0)) {
+            (g_strcmp0(args[0], "config") != 0) &&
+            (g_strcmp0(args[0], "info") != 0)) {
         cons_show("Usage: %s", help.usage);
         return TRUE;
     }
@@ -2097,6 +2098,13 @@ cmd_room(gchar **args, struct cmd_help_t help)
         ui_index = 0;
     }
 
+    if (g_strcmp0(args[0], "info") == 0) {
+        char *role = muc_get_role_str(room);
+        char *affiliation = muc_get_affiliation_str(room);
+        ui_current_print_line("Affiliation: %s, Role: %s", affiliation, role);
+        return TRUE;
+    }
+
     if (g_strcmp0(args[0], "accept") == 0) {
         gboolean requires_config = muc_requires_config(room);
         if (!requires_config) {
diff --git a/src/muc.c b/src/muc.c
index c38064e3..e4df43e4 100644
--- a/src/muc.c
+++ b/src/muc.c
@@ -43,9 +43,26 @@
 #include "tools/autocomplete.h"
 #include "ui/ui.h"
 
+typedef enum {
+    MUC_ROLE_NONE,
+    MUC_ROLE_VISITOR,
+    MUC_ROLE_PARTICIPANT,
+    MUC_ROLE_MODERATOR
+} muc_role_t;
+
+typedef enum {
+    MUC_AFFILIATION_NONE,
+    MUC_AFFILIATION_OUTCAST,
+    MUC_AFFILIATION_MEMBER,
+    MUC_AFFILIATION_ADMIN,
+    MUC_AFFILIATION_OWNER
+} muc_affiliation_t;
+
 typedef struct _muc_room_t {
     char *room; // e.g. test@conference.server
     char *nick; // e.g. Some User
+    muc_role_t role;
+    muc_affiliation_t affiliation;
     char *password;
     char *subject;
     char *autocomplete_prefix;
@@ -64,6 +81,10 @@ Autocomplete invite_ac;
 
 static void _free_room(ChatRoom *room);
 static gint _compare_participants(PContact a, PContact b);
+static muc_role_t _role_from_string(const char * const role);
+static muc_affiliation_t _affiliation_from_string(const char * const affiliation);
+static char* _role_to_string(muc_role_t role);
+static char* _affiliation_to_string(muc_affiliation_t affiliation);
 
 void
 muc_init(void)
@@ -147,6 +168,8 @@ muc_join_room(const char * const room, const char * const nick,
     ChatRoom *new_room = malloc(sizeof(ChatRoom));
     new_room->room = strdup(room);
     new_room->nick = strdup(nick);
+    new_room->role = MUC_ROLE_NONE;
+    new_room->affiliation = MUC_AFFILIATION_NONE;
     new_room->autocomplete_prefix = NULL;
     if (password) {
         new_room->password = strdup(password);
@@ -582,6 +605,46 @@ muc_reset_autocomplete(const char * const room)
     }
 }
 
+char *
+muc_get_role_str(const char * const room)
+{
+    ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
+    if (chat_room) {
+        return _role_to_string(chat_room->role);
+    } else {
+        return "none";
+    }
+}
+
+void
+muc_set_role(const char * const room, const char * const role)
+{
+    ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
+    if (chat_room) {
+        chat_room->role = _role_from_string(role);
+    }
+}
+
+char *
+muc_get_affiliation_str(const char * const room)
+{
+    ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
+    if (chat_room) {
+        return _affiliation_to_string(chat_room->affiliation);
+    } else {
+        return "none";
+    }
+}
+
+void
+muc_set_affiliation(const char * const room, const char * const affiliation)
+{
+    ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
+    if (chat_room) {
+        chat_room->affiliation = _affiliation_from_string(affiliation);
+    }
+}
+
 static void
 _free_room(ChatRoom *room)
 {
@@ -621,3 +684,96 @@ gint _compare_participants(PContact a, PContact b)
 
     return result;
 }
+
+static muc_role_t
+_role_from_string(const char * const role)
+{
+    if (role) {
+        if (g_strcmp0(role, "visitor") == 0) {
+            return MUC_ROLE_VISITOR;
+        } else if (g_strcmp0(role, "participant") == 0) {
+            return MUC_ROLE_PARTICIPANT;
+        } else if (g_strcmp0(role, "moderator") == 0) {
+            return MUC_ROLE_MODERATOR;
+        } else {
+            return MUC_ROLE_NONE;
+        }
+    } else {
+        return MUC_ROLE_NONE;
+    }
+}
+
+static char *
+_role_to_string(muc_role_t role)
+{
+    char *result = NULL;
+
+    switch (role) {
+    case MUC_ROLE_NONE:
+        result = "none";
+        break;
+    case MUC_ROLE_VISITOR:
+        result = "visitor";
+        break;
+    case MUC_ROLE_PARTICIPANT:
+        result = "participant";
+        break;
+    case MUC_ROLE_MODERATOR:
+        result = "moderator";
+        break;
+    default:
+        result = "none";
+        break;
+    }
+
+    return result;
+}
+
+static muc_affiliation_t
+_affiliation_from_string(const char * const affiliation)
+{
+    if (affiliation) {
+        if (g_strcmp0(affiliation, "outcast") == 0) {
+            return MUC_AFFILIATION_OUTCAST;
+        } else if (g_strcmp0(affiliation, "member") == 0) {
+            return MUC_AFFILIATION_MEMBER;
+        } else if (g_strcmp0(affiliation, "admin") == 0) {
+            return MUC_AFFILIATION_ADMIN;
+        } else if (g_strcmp0(affiliation, "owner") == 0) {
+            return MUC_AFFILIATION_OWNER;
+        } else {
+            return MUC_AFFILIATION_NONE;
+        }
+    } else {
+        return MUC_AFFILIATION_NONE;
+    }
+}
+
+static char *
+_affiliation_to_string(muc_affiliation_t affiliation)
+{
+    char *result = NULL;
+
+    switch (affiliation) {
+    case MUC_AFFILIATION_NONE:
+        result = "none";
+        break;
+    case MUC_AFFILIATION_OUTCAST:
+        result = "outcast";
+        break;
+    case MUC_AFFILIATION_MEMBER:
+        result = "member";
+        break;
+    case MUC_AFFILIATION_ADMIN:
+        result = "admin";
+        break;
+    case MUC_AFFILIATION_OWNER:
+        result = "owner";
+        break;
+    default:
+        result = "none";
+        break;
+    }
+
+    return result;
+}
diff --git a/src/muc.h b/src/muc.h
index 722e4a17..debe420e 100644
--- a/src/muc.h
+++ b/src/muc.h
@@ -93,4 +93,9 @@ void muc_reset_autocomplete(const char * const room);
 gboolean muc_requires_config(const char * const room);
 void muc_set_requires_config(const char * const room, gboolean val);
 
+void muc_set_role(const char * const room, const char * const role);
+void muc_set_affiliation(const char * const room, const char * const affiliation);
+char *muc_get_role_str(const char * const room);
+char *muc_get_affiliation_str(const char * const room);
+
 #endif
diff --git a/src/server_events.c b/src/server_events.c
index f89385c6..f8815870 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -456,6 +456,7 @@ void
 handle_room_nick_change(const char * const room,
     const char * const nick)
 {
+    muc_complete_room_nick_change(room, nick);
     ui_room_nick_change(room, nick);
 }
 
diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c
index adbb21fb..f63b3349 100644
--- a/src/xmpp/presence.c
+++ b/src/xmpp/presence.c
@@ -697,6 +697,7 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
         char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
         char *new_nick = stanza_get_new_nick(stanza);
 
+        // self unavailable
         if ((type != NULL) && (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0)) {
 
             // leave room if not self nick change
@@ -706,18 +707,33 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
                 handle_leave_room(from_room);
             }
 
-        // handle self nick change
-        } else if (muc_is_room_pending_nick_change(from_room)) {
-            muc_complete_room_nick_change(from_room, from_nick);
-            handle_room_nick_change(from_room, from_nick);
+        // self online
+        } else {
+
+            // handle self nick change
+            if (muc_is_room_pending_nick_change(from_room)) {
+                handle_room_nick_change(from_room, from_nick);
+
+            // handle roster complete
+            } else if (!muc_get_roster_received(from_room)) {
+                handle_room_roster_complete(from_room);
 
-        // handle roster complete
-        } else if (!muc_get_roster_received(from_room)) {
-            handle_room_roster_complete(from_room);
+                // room configuration required
+                if (stanza_muc_requires_config(stanza)) {
+                    handle_room_requires_config(from_room);
+                }
+            }
 
-            // room configuration required
-            if (stanza_muc_requires_config(stanza)) {
-                handle_room_requires_config(from_room);
+            // set own affiliation and role
+            xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
+            if (x) {
+                xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
+                if (item) {
+                    char *role = xmpp_stanza_get_attribute(item, "role");
+                    muc_set_role(from_room, role);
+                    char *affiliation = xmpp_stanza_get_attribute(item, "affiliation");
+                    muc_set_affiliation(from_room, affiliation);
+                }
             }
         }
 
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 2d99c0f0..045fea59 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -822,11 +822,11 @@ stanza_is_muc_self_presence(xmpp_stanza_t * const stanza,
 
     // muc user namespaced x element
     xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
-    if (x != NULL) {
+    if (x) {
 
         // check for status child element with 110 code
         xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
-        while (x_children != NULL) {
+        while (x_children) {
             if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
                 char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
                 if (g_strcmp0(code, "110") == 0) {
@@ -838,9 +838,9 @@ stanza_is_muc_self_presence(xmpp_stanza_t * const stanza,
 
         // check for item child element with jid property
         xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
-        if (item != NULL) {
+        if (item) {
             char *jid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
-            if (jid != NULL) {
+            if (jid) {
                 if (g_str_has_prefix(self_jid, jid)) {
                     return TRUE;
                 }
@@ -849,7 +849,7 @@ stanza_is_muc_self_presence(xmpp_stanza_t * const stanza,
 
         // check if 'from' attribute identifies this user
         char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
-        if (from != NULL) {
+        if (from) {
             Jid *from_jid = jid_create(from);
             if (muc_room_is_active(from_jid->barejid)) {
                 char *nick = muc_get_room_nick(from_jid->barejid);
@@ -861,7 +861,7 @@ stanza_is_muc_self_presence(xmpp_stanza_t * const stanza,
             // check if a new nickname maps to a pending nick change for this user
             if (muc_is_room_pending_nick_change(from_jid->barejid)) {
                 char *new_nick = from_jid->resourcepart;
-                if (new_nick != NULL) {
+                if (new_nick) {
                     char *nick = muc_get_room_nick(from_jid->barejid);
                     char *old_nick = muc_get_old_nick(from_jid->barejid, new_nick);
                     if (g_strcmp0(old_nick, nick) == 0) {