about summary refs log tree commit diff stats
path: root/src/xmpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmpp')
-rw-r--r--src/xmpp/blocking.c2
-rw-r--r--src/xmpp/blocking.h2
-rw-r--r--src/xmpp/bookmark.c14
-rw-r--r--src/xmpp/bookmark.h2
-rw-r--r--src/xmpp/capabilities.c2
-rw-r--r--src/xmpp/capabilities.h2
-rw-r--r--src/xmpp/chat_session.c2
-rw-r--r--src/xmpp/chat_session.h2
-rw-r--r--src/xmpp/chat_state.c2
-rw-r--r--src/xmpp/chat_state.h2
-rw-r--r--src/xmpp/connection.c2
-rw-r--r--src/xmpp/connection.h2
-rw-r--r--src/xmpp/contact.c2
-rw-r--r--src/xmpp/contact.h2
-rw-r--r--src/xmpp/form.c2
-rw-r--r--src/xmpp/form.h2
-rw-r--r--src/xmpp/iq.c134
-rw-r--r--src/xmpp/iq.h2
-rw-r--r--src/xmpp/jid.c2
-rw-r--r--src/xmpp/jid.h2
-rw-r--r--src/xmpp/message.c2
-rw-r--r--src/xmpp/message.h2
-rw-r--r--src/xmpp/muc.c95
-rw-r--r--src/xmpp/muc.h7
-rw-r--r--src/xmpp/presence.c2
-rw-r--r--src/xmpp/presence.h2
-rw-r--r--src/xmpp/resource.c2
-rw-r--r--src/xmpp/resource.h2
-rw-r--r--src/xmpp/roster.c2
-rw-r--r--src/xmpp/roster.h2
-rw-r--r--src/xmpp/roster_list.c2
-rw-r--r--src/xmpp/roster_list.h2
-rw-r--r--src/xmpp/session.c4
-rw-r--r--src/xmpp/session.h2
-rw-r--r--src/xmpp/stanza.c2
-rw-r--r--src/xmpp/stanza.h2
-rw-r--r--src/xmpp/xmpp.h5
37 files changed, 245 insertions, 76 deletions
diff --git a/src/xmpp/blocking.c b/src/xmpp/blocking.c
index 2a8fb316..5d1c52b2 100644
--- a/src/xmpp/blocking.c
+++ b/src/xmpp/blocking.c
@@ -1,7 +1,7 @@
 /*
  * blocking.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/blocking.h b/src/xmpp/blocking.h
index 1e3b6961..61acb631 100644
--- a/src/xmpp/blocking.h
+++ b/src/xmpp/blocking.h
@@ -1,7 +1,7 @@
 /*
  * blocking.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c
index 99b2e20d..65009224 100644
--- a/src/xmpp/bookmark.c
+++ b/src/xmpp/bookmark.c
@@ -1,7 +1,7 @@
 /*
  * bookmark.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -98,6 +98,12 @@ bookmark_add(const char *jid, const char *nick, const char *password, const char
 {
     assert(jid != NULL);
 
+    Jid *jidp = jid_create(jid);
+    if (jidp->domainpart) {
+        muc_confserver_add(jidp->domainpart);
+    }
+    jid_destroy(jidp);
+
     if (g_hash_table_contains(bookmarks, jid)) {
         return FALSE;
     }
@@ -297,6 +303,12 @@ _bookmark_result_id_handler(xmpp_stanza_t *const stanza, void *const userdata)
             sv_ev_bookmark_autojoin(bookmark);
         }
 
+        Jid *jidp = jid_create(barejid);
+        if (jidp->domainpart) {
+            muc_confserver_add(jidp->domainpart);
+        }
+        jid_destroy(jidp);
+
         child = xmpp_stanza_get_next(child);
     }
 
diff --git a/src/xmpp/bookmark.h b/src/xmpp/bookmark.h
index c9dfa214..f6c72c27 100644
--- a/src/xmpp/bookmark.h
+++ b/src/xmpp/bookmark.h
@@ -1,7 +1,7 @@
 /*
  * bookmark.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c
index 263680a6..2152f869 100644
--- a/src/xmpp/capabilities.c
+++ b/src/xmpp/capabilities.c
@@ -1,7 +1,7 @@
 /*
  * capabilities.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/capabilities.h b/src/xmpp/capabilities.h
index c1b820fb..21ffe0b4 100644
--- a/src/xmpp/capabilities.h
+++ b/src/xmpp/capabilities.h
@@ -1,7 +1,7 @@
 /*
  * capabilities.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/chat_session.c b/src/xmpp/chat_session.c
index 6e6d871a..799a9c47 100644
--- a/src/xmpp/chat_session.c
+++ b/src/xmpp/chat_session.c
@@ -1,7 +1,7 @@
 /*
  * chat_session.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/chat_session.h b/src/xmpp/chat_session.h
index be3b1ce6..d8de0330 100644
--- a/src/xmpp/chat_session.h
+++ b/src/xmpp/chat_session.h
@@ -1,7 +1,7 @@
 /*
  * chat_session.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/chat_state.c b/src/xmpp/chat_state.c
index cb1b9f69..9659eb8b 100644
--- a/src/xmpp/chat_state.c
+++ b/src/xmpp/chat_state.c
@@ -1,7 +1,7 @@
 /*
  * chat_state.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/chat_state.h b/src/xmpp/chat_state.h
index 9255cb04..51698cd1 100644
--- a/src/xmpp/chat_state.h
+++ b/src/xmpp/chat_state.h
@@ -1,7 +1,7 @@
 /*
  * chat_state.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c
index 34b53f44..6c5e7323 100644
--- a/src/xmpp/connection.c
+++ b/src/xmpp/connection.c
@@ -1,7 +1,7 @@
 /*
  * connection.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h
index ea3d08e7..b0ff7cec 100644
--- a/src/xmpp/connection.h
+++ b/src/xmpp/connection.h
@@ -1,7 +1,7 @@
 /*
  * connection.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/contact.c b/src/xmpp/contact.c
index 0fbff9d5..a43372f3 100644
--- a/src/xmpp/contact.c
+++ b/src/xmpp/contact.c
@@ -1,7 +1,7 @@
 /*
  * contact.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/contact.h b/src/xmpp/contact.h
index 73849351..170df2ca 100644
--- a/src/xmpp/contact.h
+++ b/src/xmpp/contact.h
@@ -1,7 +1,7 @@
 /*
  * contact.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/form.c b/src/xmpp/form.c
index e1bd4a93..6e26411a 100644
--- a/src/xmpp/form.c
+++ b/src/xmpp/form.c
@@ -1,7 +1,7 @@
 /*
  * form.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/form.h b/src/xmpp/form.h
index aa446017..21314ce2 100644
--- a/src/xmpp/form.h
+++ b/src/xmpp/form.h
@@ -1,7 +1,7 @@
 /*
  * form.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index 7f6b8de0..9bceb859 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -1,7 +1,7 @@
 /*
  * iq.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -119,6 +119,7 @@ static int _caps_response_id_handler(xmpp_stanza_t *const stanza, void *const us
 static int _caps_response_for_jid_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
 static int _caps_response_legacy_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
 static int _auto_pong_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
+static int _room_list_id_handler(xmpp_stanza_t *const stanza, void *const userdata);
 
 static void _iq_free_room_data(ProfRoomInfoData *roominfo);
 static void _iq_free_affiliation_set(ProfPrivilegeSet *affiliation_set);
@@ -126,9 +127,13 @@ static void _iq_free_affiliation_set(ProfPrivilegeSet *affiliation_set);
 // scheduled
 static int _autoping_timed_send(xmpp_conn_t *const conn, void *const userdata);
 
+static void _identity_destroy(DiscoIdentity *identity);
+static void _item_destroy(DiscoItem *item);
+
 static gboolean autoping_wait = FALSE;
 static GTimer *autoping_time = NULL;
 static GHashTable *id_handlers;
+static GHashTable *rooms_cache = NULL;
 
 static int
 _iq_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
@@ -232,6 +237,7 @@ iq_handlers_init(void)
         g_hash_table_destroy(id_handlers);
     }
     id_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
+    rooms_cache = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)xmpp_stanza_release);
 }
 
 void
@@ -293,10 +299,30 @@ iq_set_autoping(const int seconds)
 }
 
 void
-iq_room_list_request(gchar *conferencejid)
+iq_rooms_cache_clear(void)
+{
+    if (rooms_cache) {
+        g_hash_table_remove_all(rooms_cache);
+    }
+}
+
+void
+iq_room_list_request(gchar *conferencejid, gchar *filter)
 {
+    if (g_hash_table_contains(rooms_cache, conferencejid)) {
+        log_debug("Rooms request cached for: %s", conferencejid);
+        _room_list_id_handler(g_hash_table_lookup(rooms_cache, conferencejid), filter);
+        return;
+    }
+
+    log_debug("Rooms request not cached for: %s", conferencejid);
+
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, "confreq", conferencejid);
+    char *id = create_unique_id("confreq");
+    xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, id, conferencejid);
+
+    iq_id_handler_add(id, _room_list_id_handler, NULL, filter);
+
     iq_send_stanza(iq);
     xmpp_stanza_release(iq);
 }
@@ -891,6 +917,101 @@ _caps_response_legacy_id_handler(xmpp_stanza_t *const stanza, void *const userda
 }
 
 static int
+_room_list_id_handler(xmpp_stanza_t *const stanza, void *const userdata)
+{
+    gchar *filter = (gchar*)userdata;
+    const char *id = xmpp_stanza_get_id(stanza);
+    const char *from = xmpp_stanza_get_from(stanza);
+
+    if (prefs_get_boolean(PREF_ROOM_LIST_CACHE) && !g_hash_table_contains(rooms_cache, from)) {
+        g_hash_table_insert(rooms_cache, strdup(from), xmpp_stanza_copy(stanza));
+    }
+
+    log_debug("Response to query: %s", id);
+
+    xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
+    if (query == NULL) {
+        g_free(filter);
+        return 0;
+    }
+
+    cons_show("");
+    if (filter) {
+        cons_show("Rooms list response received: %s, filter: %s", from, filter);
+    } else {
+        cons_show("Rooms list response received: %s", from);
+    }
+    xmpp_stanza_t *child = xmpp_stanza_get_children(query);
+    if (child == NULL) {
+        cons_show("  No rooms found.");
+        g_free(filter);
+        return 0;
+    }
+
+    GPatternSpec *glob = NULL;
+    if (filter != NULL) {
+        gchar *filter_lower = g_utf8_strdown(filter, -1);
+        GString *glob_str = g_string_new("*");
+        g_string_append(glob_str, filter_lower);
+        g_free(filter_lower);
+        g_string_append(glob_str, "*");
+        glob = g_pattern_spec_new(glob_str->str);
+        g_string_free(glob_str, TRUE);
+    }
+
+    gboolean matched = FALSE;
+    while (child) {
+        const char *stanza_name = xmpp_stanza_get_name(child);
+        if (stanza_name && (g_strcmp0(stanza_name, STANZA_NAME_ITEM) == 0)) {
+            const char *item_jid = xmpp_stanza_get_attribute(child, STANZA_ATTR_JID);
+            gchar *item_jid_lower = NULL;
+            if (item_jid) {
+                Jid *jidp = jid_create(item_jid);
+                if (jidp && jidp->localpart) {
+                    item_jid_lower = g_utf8_strdown(jidp->localpart, -1);
+                }
+                jid_destroy(jidp);
+            }
+            const char *item_name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
+            gchar *item_name_lower = NULL;
+            if (item_name) {
+                item_name_lower = g_utf8_strdown(item_name, -1);
+            }
+            if ((item_jid_lower) && ((glob == NULL) ||
+                ((g_pattern_match(glob, strlen(item_jid_lower), item_jid_lower, NULL)) ||
+                (item_name_lower && g_pattern_match(glob, strlen(item_name_lower), item_name_lower, NULL))))) {
+
+                if (glob) {
+                    matched = TRUE;
+                }
+                GString *item = g_string_new(item_jid);
+                if (item_name) {
+                    g_string_append(item, " (");
+                    g_string_append(item, item_name);
+                    g_string_append(item, ")");
+                }
+                cons_show("  %s", item->str);
+                g_string_free(item, TRUE);
+            }
+            g_free(item_jid_lower);
+            g_free(item_name_lower);
+        }
+        child = xmpp_stanza_get_next(child);
+    }
+
+    if (glob && matched == FALSE) {
+        cons_show("  No rooms found matching filter: %s", filter);
+    }
+
+    if (glob) {
+        g_pattern_spec_free(glob);
+    }
+    g_free(filter);
+
+    return 0;
+}
+
+static int
 _enable_carbons_id_handler(xmpp_stanza_t *const stanza, void *const userdata)
 {
     const char *type = xmpp_stanza_get_type(stanza);
@@ -1992,8 +2113,7 @@ _disco_items_result_handler(xmpp_stanza_t *const stanza)
     const char *from = xmpp_stanza_get_from(stanza);
     GSList *items = NULL;
 
-    if ((g_strcmp0(id, "confreq") != 0) &&
-            (g_strcmp0(id, "discoitemsreq") != 0) &&
+    if ((g_strcmp0(id, "discoitemsreq") != 0) &&
             (g_strcmp0(id, "discoitemsreq_onconnect") != 0)) {
         return;
     }
@@ -2030,9 +2150,7 @@ _disco_items_result_handler(xmpp_stanza_t *const stanza)
         child = xmpp_stanza_get_next(child);
     }
 
-    if (g_strcmp0(id, "confreq") == 0) {
-        cons_show_room_list(items, from);
-    } else if (g_strcmp0(id, "discoitemsreq") == 0) {
+    if (g_strcmp0(id, "discoitemsreq") == 0) {
         cons_show_disco_items(items, from);
     } else if (g_strcmp0(id, "discoitemsreq_onconnect") == 0) {
         connection_set_disco_items(items);
diff --git a/src/xmpp/iq.h b/src/xmpp/iq.h
index e56d2f59..b06568b6 100644
--- a/src/xmpp/iq.h
+++ b/src/xmpp/iq.h
@@ -1,7 +1,7 @@
 /*
  * iq.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/jid.c b/src/xmpp/jid.c
index ac4cdcdb..0af54c72 100644
--- a/src/xmpp/jid.c
+++ b/src/xmpp/jid.c
@@ -1,7 +1,7 @@
 /*
  * jid.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/jid.h b/src/xmpp/jid.h
index 0ce0ec5b..e4e4d272 100644
--- a/src/xmpp/jid.h
+++ b/src/xmpp/jid.h
@@ -1,7 +1,7 @@
 /*
  * jid.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index 4afbe4b1..9f665892 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -1,7 +1,7 @@
 /*
  * message.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/message.h b/src/xmpp/message.h
index b8ba039e..47bb17ed 100644
--- a/src/xmpp/message.h
+++ b/src/xmpp/message.h
@@ -1,7 +1,7 @@
 /*
  * message.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/muc.c b/src/xmpp/muc.c
index 69cacba1..9f2f9f61 100644
--- a/src/xmpp/muc.c
+++ b/src/xmpp/muc.c
@@ -1,7 +1,7 @@
 /*
  * muc.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -69,6 +69,7 @@ typedef struct _muc_room_t {
 GHashTable *rooms = NULL;
 GHashTable *invite_passwords = NULL;
 Autocomplete invite_ac;
+Autocomplete confservers_ac;
 
 static void _free_room(ChatRoom *room);
 static gint _compare_occupants(Occupant *a, Occupant *b);
@@ -84,6 +85,7 @@ void
 muc_init(void)
 {
     invite_ac = autocomplete_new();
+    confservers_ac = autocomplete_new();
     rooms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_free_room);
     invite_passwords = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 }
@@ -92,6 +94,7 @@ void
 muc_close(void)
 {
     autocomplete_free(invite_ac);
+    autocomplete_free(confservers_ac);
     g_hash_table_destroy(rooms);
     g_hash_table_destroy(invite_passwords);
     rooms = NULL;
@@ -99,6 +102,12 @@ muc_close(void)
 }
 
 void
+muc_confserver_add(const char *const server)
+{
+    autocomplete_add(confservers_ac, server);
+}
+
+void
 muc_invites_add(const char *const room, const char *const password)
 {
     autocomplete_add(invite_ac, room);
@@ -156,12 +165,24 @@ muc_invites_reset_ac(void)
     autocomplete_reset(invite_ac);
 }
 
+void
+muc_confserver_reset_ac(void)
+{
+    autocomplete_reset(confservers_ac);
+}
+
 char*
 muc_invites_find(const char *const search_str, gboolean previous)
 {
     return autocomplete_complete(invite_ac, search_str, TRUE, previous);
 }
 
+char*
+muc_confserver_find(const char *const search_str, gboolean previous)
+{
+    return autocomplete_complete(confservers_ac, search_str, TRUE, previous);
+}
+
 void
 muc_invites_clear(void)
 {
@@ -172,6 +193,12 @@ muc_invites_clear(void)
 }
 
 void
+muc_confserver_clear(void)
+{
+    autocomplete_clear(confservers_ac);
+}
+
+void
 muc_join(const char *const room, const char *const nick, const char *const password, gboolean autojoin)
 {
     ChatRoom *new_room = malloc(sizeof(ChatRoom));
@@ -665,43 +692,47 @@ muc_roster_nick_change_complete(const char *const room, const char *const nick)
 char*
 muc_autocomplete(ProfWin *window, const char *const input, gboolean previous)
 {
-    if (window->type == WIN_MUC) {
-        ProfMucWin *mucwin = (ProfMucWin*)window;
-        assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
-        ChatRoom *chat_room = g_hash_table_lookup(rooms, mucwin->roomjid);
+    if (window->type != WIN_MUC) {
+        return NULL;
+    }
 
-        if (chat_room && chat_room->nick_ac) {
-            const char * search_str = NULL;
+    ProfMucWin *mucwin = (ProfMucWin*)window;
+    assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+    ChatRoom *chat_room = g_hash_table_lookup(rooms, mucwin->roomjid);
+    if (chat_room == NULL || chat_room->nick_ac == NULL) {
+        return NULL;
+    }
 
-            gchar *last_space = g_strrstr(input, " ");
-            if (!last_space) {
-                search_str = input;
-                if (!chat_room->autocomplete_prefix) {
-                    chat_room->autocomplete_prefix = strdup("");
-                }
-            } else {
-                search_str = last_space+1;
-                if (!chat_room->autocomplete_prefix) {
-                    chat_room->autocomplete_prefix = g_strndup(input, search_str - input);
-                }
-            }
+    const char * search_str = NULL;
 
-            char *result = autocomplete_complete(chat_room->nick_ac, search_str, FALSE, previous);
-            if (result) {
-                GString *replace_with = g_string_new(chat_room->autocomplete_prefix);
-                g_string_append(replace_with, result);
-                if (!last_space || (*(last_space+1) == '\0')) {
-                    g_string_append(replace_with, ": ");
-                }
-                g_free(result);
-                result = replace_with->str;
-                g_string_free(replace_with, FALSE);
-                return result;
-            }
+    gchar *last_space = g_strrstr(input, " ");
+    if (!last_space) {
+        search_str = input;
+        if (!chat_room->autocomplete_prefix) {
+            chat_room->autocomplete_prefix = strdup("");
+        }
+    } else {
+        search_str = last_space+1;
+        if (!chat_room->autocomplete_prefix) {
+            chat_room->autocomplete_prefix = g_strndup(input, search_str - input);
         }
     }
 
-    return NULL;
+    char *result = autocomplete_complete(chat_room->nick_ac, search_str, FALSE, previous);
+    if (result == NULL) {
+        return NULL;
+    }
+
+    GString *replace_with = g_string_new(chat_room->autocomplete_prefix);
+    g_string_append(replace_with, result);
+
+    if (strlen(chat_room->autocomplete_prefix) == 0) {
+        g_string_append(replace_with, ": ");
+    }
+    g_free(result);
+    result = replace_with->str;
+    g_string_free(replace_with, FALSE);
+    return result;
 }
 
 void
diff --git a/src/xmpp/muc.h b/src/xmpp/muc.h
index 6c6408f3..e50e2a87 100644
--- a/src/xmpp/muc.h
+++ b/src/xmpp/muc.h
@@ -1,7 +1,7 @@
 /*
  * muc.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -117,6 +117,11 @@ GSList* muc_occupants_by_affiliation(const char *const room, muc_affiliation_t a
 void muc_occupant_nick_change_start(const char *const room, const char *const new_nick, const char *const old_nick);
 char* muc_roster_nick_change_complete(const char *const room, const char *const nick);
 
+void muc_confserver_add(const char *const server);
+void muc_confserver_reset_ac(void);
+char* muc_confserver_find(const char *const search_str, gboolean previous);
+void muc_confserver_clear(void);
+
 void muc_invites_add(const char *const room, const char *const password);
 void muc_invites_remove(const char *const room);
 gint muc_invites_count(void);
diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c
index 97e3d461..8efb60e0 100644
--- a/src/xmpp/presence.c
+++ b/src/xmpp/presence.c
@@ -1,7 +1,7 @@
 /*
  * presence.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/presence.h b/src/xmpp/presence.h
index 4415be1b..6045f72c 100644
--- a/src/xmpp/presence.h
+++ b/src/xmpp/presence.h
@@ -1,7 +1,7 @@
 /*
  * presence.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/resource.c b/src/xmpp/resource.c
index 154f8490..734de3a0 100644
--- a/src/xmpp/resource.c
+++ b/src/xmpp/resource.c
@@ -1,7 +1,7 @@
 /*
  * resource.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/resource.h b/src/xmpp/resource.h
index 8acc5207..9376a51c 100644
--- a/src/xmpp/resource.h
+++ b/src/xmpp/resource.h
@@ -1,7 +1,7 @@
 /*
  * resource.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c
index ba152410..e7d9cfb2 100644
--- a/src/xmpp/roster.c
+++ b/src/xmpp/roster.c
@@ -1,7 +1,7 @@
 /*
  * roster.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/roster.h b/src/xmpp/roster.h
index 806c7316..15614377 100644
--- a/src/xmpp/roster.h
+++ b/src/xmpp/roster.h
@@ -1,7 +1,7 @@
 /*
  * roster.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/roster_list.c b/src/xmpp/roster_list.c
index 839ea0b8..a2c5653d 100644
--- a/src/xmpp/roster_list.c
+++ b/src/xmpp/roster_list.c
@@ -1,7 +1,7 @@
 /*
  * roster_list.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/roster_list.h b/src/xmpp/roster_list.h
index 4e6b1d47..a0b01625 100644
--- a/src/xmpp/roster_list.h
+++ b/src/xmpp/roster_list.h
@@ -1,7 +1,7 @@
 /*
  * roster_list.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/session.c b/src/xmpp/session.c
index 633af31f..e06b03f1 100644
--- a/src/xmpp/session.c
+++ b/src/xmpp/session.c
@@ -1,7 +1,7 @@
 /*
  * session.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -219,6 +219,8 @@ session_disconnect(void)
 
         accounts_set_last_activity(session_get_account_name());
 
+        iq_rooms_cache_clear();
+
         connection_disconnect();
 
         _session_free_saved_account();
diff --git a/src/xmpp/session.h b/src/xmpp/session.h
index a8c6ab83..a3413e9e 100644
--- a/src/xmpp/session.h
+++ b/src/xmpp/session.h
@@ -1,7 +1,7 @@
 /*
  * session.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 4dd0a2d4..2f690828 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -1,7 +1,7 @@
 /*
  * stanza.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 5da1c2c3..bd161616 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -1,7 +1,7 @@
 /*
  * stanza.h
  *
- * Copyright (C) 2012 - 20172017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index fa36cf19..d4a29196 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -1,7 +1,7 @@
 /*
  * xmpp.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -161,7 +161,8 @@ gboolean presence_sub_request_exists(const char *const bare_jid);
 void iq_enable_carbons(void);
 void iq_disable_carbons(void);
 void iq_send_software_version(const char *const fulljid);
-void iq_room_list_request(gchar *conferencejid);
+void iq_rooms_cache_clear(void);
+void iq_room_list_request(gchar *conferencejid, gchar *filter);
 void iq_disco_info_request(gchar *jid);
 void iq_disco_items_request(gchar *jid);
 void iq_last_activity_request(gchar *jid);