about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/chat_session.c294
-rw-r--r--src/chat_session.h12
-rw-r--r--src/command/command.c9
-rw-r--r--src/command/commands.c49
-rw-r--r--src/otr/otr.c3
-rw-r--r--src/server_events.c6
-rw-r--r--src/ui/core.c8
-rw-r--r--src/ui/inputwin.c16
-rw-r--r--src/xmpp/message.c27
-rw-r--r--src/xmpp/stanza.c5
-rw-r--r--src/xmpp/stanza.h2
-rw-r--r--src/xmpp/xmpp.h11
-rw-r--r--tests/test_cmd_otr.c2
-rw-r--r--tests/test_server_events.c7
-rw-r--r--tests/xmpp/stub_xmpp.c7
15 files changed, 279 insertions, 179 deletions
diff --git a/src/chat_session.c b/src/chat_session.c
index d27a3449..67104fa6 100644
--- a/src/chat_session.c
+++ b/src/chat_session.c
@@ -34,6 +34,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 #include <glib.h>
 
@@ -57,24 +58,30 @@ typedef enum {
 typedef struct chat_session_t {
     char *barejid;
     char *resource;
-    gboolean supported;
+    gboolean send_states;
     chat_state_t state;
     GTimer *active_timer;
     gboolean sent;
+    gboolean includes_message;
 } ChatSession;
 
 static GHashTable *sessions;
 
 static ChatSession*
-_chat_session_new(const char * const barejid, gboolean supported)
+_chat_session_new(const char * const barejid, const char * const resource, gboolean send_states)
 {
     ChatSession *new_session = malloc(sizeof(struct chat_session_t));
     new_session->barejid = strdup(barejid);
-    new_session->resource = NULL;
-    new_session->supported = supported;
+    if (resource) {
+        new_session->resource = strdup(resource);
+    } else {
+        new_session->resource = NULL;
+    }
+    new_session->send_states = send_states;
     new_session->state = CHAT_STATE_STARTED;
     new_session->active_timer = g_timer_new();
     new_session->sent = FALSE;
+    new_session->includes_message = FALSE;
 
     return new_session;
 }
@@ -84,6 +91,7 @@ _chat_session_free(ChatSession *session)
 {
     if (session != NULL) {
         free(session->barejid);
+        free(session->resource);
         if (session->active_timer != NULL) {
             g_timer_destroy(session->active_timer);
             session->active_timer = NULL;
@@ -107,137 +115,247 @@ chat_sessions_clear(void)
 }
 
 gboolean
-chat_session_on_message_send(const char * const barejid)
+chat_session_exists(const char * const barejid)
 {
-    gboolean send_state = FALSE;
-    if (prefs_get_boolean(PREF_STATES)) {
-        ChatSession *session = g_hash_table_lookup(sessions, barejid);
-        if (!session) {
-            session = _chat_session_new(barejid, TRUE);
-            g_hash_table_insert(sessions, strdup(barejid), session);
+    ChatSession *session = g_hash_table_lookup(sessions, barejid);
 
-        }
-        if (session->supported) {
-            session->state = CHAT_STATE_ACTIVE;
-            g_timer_start(session->active_timer);
-            session->sent = TRUE;
-            send_state = TRUE;
-        }
-    }
+    return (session != NULL);
+}
+
+char*
+chat_session_get_resource(const char * const barejid)
+{
+    ChatSession *session = g_hash_table_lookup(sessions, barejid);
+    assert(session != NULL);
 
-    return send_state;
+    return session->resource;
+}
+
+gboolean
+chat_session_send_states(const char * const barejid)
+{
+    ChatSession *session = g_hash_table_lookup(sessions, barejid);
+    assert(session != NULL);
+
+    return session->send_states;
 }
 
 void
-chat_session_on_incoming_message(const char * const barejid, gboolean supported)
+chat_session_on_incoming_message(const char * const barejid, const char * const resource, gboolean send_states)
 {
     ChatSession *session = g_hash_table_lookup(sessions, barejid);
+    GString *log_msg = g_string_new("");
+
+    // no session exists, create one
     if (!session) {
-        session = _chat_session_new(barejid, supported);
+        g_string_append(log_msg, "Creating chat session for ");
+        g_string_append(log_msg, barejid);
+        if (resource) {
+            g_string_append(log_msg, "/");
+            g_string_append(log_msg, resource);
+        }
+        session = _chat_session_new(barejid, resource, send_states);
+        g_hash_table_insert(sessions, strdup(barejid), session);
+
+    // session exists for different resource, replace session
+    } else if (g_strcmp0(session->resource, resource) != 0) {
+        g_string_append(log_msg, "Replacing chat session for ");
+        g_string_append(log_msg, barejid);
+        if (session->resource) {
+            g_string_append(log_msg, "/");
+            g_string_append(log_msg, session->resource);
+        }
+        g_string_append(log_msg, " with session for ");
+        g_string_append(log_msg, barejid);
+        if (resource) {
+            g_string_append(log_msg, "/");
+            g_string_append(log_msg, resource);
+        }
+        g_hash_table_remove(sessions, session);
+        session = _chat_session_new(barejid, resource, send_states);
+        session->includes_message = TRUE;
         g_hash_table_insert(sessions, strdup(barejid), session);
+
+    // session exists for resource, update state
+    } else {
+        g_string_append(log_msg, "Updating chat session for ");
+        g_string_append(log_msg, session->barejid);
+        if (session->resource) {
+            g_string_append(log_msg, "/");
+            g_string_append(log_msg, session->resource);
+        }
+        session->send_states = send_states;
+        session->includes_message = TRUE;
+    }
+    if (send_states) {
+        g_string_append(log_msg, ", chat states supported");
     } else {
-        session->supported = supported;
+        g_string_append(log_msg, ", chat states not supported");
     }
+
+    log_debug(log_msg->str);
+    g_string_free(log_msg, TRUE);
 }
 
 void
-chat_session_on_window_open(const char * const barejid)
+chat_session_on_message_send(const char * const barejid)
 {
-    if (prefs_get_boolean(PREF_STATES)) {
-        ChatSession *session = g_hash_table_lookup(sessions, barejid);
-        if (!session) {
-            session = _chat_session_new(barejid, TRUE);
-            g_hash_table_insert(sessions, strdup(barejid), session);
-        }
+    ChatSession *session = g_hash_table_lookup(sessions, barejid);
+
+    // if no session exists, create one with no resource, and send states
+    if (!session) {
+        log_debug("Creating chat session for %s, chat states supported", barejid);
+        session = _chat_session_new(barejid, NULL, TRUE);
+        g_hash_table_insert(sessions, strdup(barejid), session);
     }
+
+    session->state = CHAT_STATE_ACTIVE;
+    g_timer_start(session->active_timer);
+    session->sent = TRUE;
+    session->includes_message = TRUE;
 }
 
 void
 chat_session_on_window_close(const char * const barejid)
 {
-    if (prefs_get_boolean(PREF_STATES)) {
-        ChatSession *session = g_hash_table_lookup(sessions, barejid);
-        // send <gone/> chat state before closing
-        if (session->supported) {
-            session->state = CHAT_STATE_GONE;
-            message_send_gone(barejid);
-            session->sent = TRUE;
-            g_hash_table_remove(sessions, barejid);
+    ChatSession *session = g_hash_table_lookup(sessions, barejid);
+
+    if (session) {
+        if (prefs_get_boolean(PREF_STATES) && session->send_states && session->includes_message) {
+            GString *jid = g_string_new(session->barejid);
+            if (session->resource) {
+                g_string_append(jid, "/");
+                g_string_append(jid, session->resource);
+            }
+            message_send_gone(jid->str);
+            g_string_free(jid, TRUE);
+        }
+        GString *log_msg = g_string_new("Removing chat session for ");
+        g_string_append(log_msg, barejid);
+        if (session->resource) {
+            g_string_append(log_msg, "/");
+            g_string_append(log_msg, session->resource);
         }
+        log_debug(log_msg->str);
+        g_string_free(log_msg, TRUE);
+        g_hash_table_remove(sessions, barejid);
     }
 }
 
 void
-chat_session_on_cancel(const char * const jid)
+chat_session_on_activity(const char * const barejid)
 {
-    if (prefs_get_boolean(PREF_STATES)) {
-        ChatSession *session = g_hash_table_lookup(sessions, jid);
-        if (session) {
-            session->supported = FALSE;
+    ChatSession *session = g_hash_table_lookup(sessions, barejid);
+
+    if (!session) {
+        log_debug("Creating chat session for %s, chat states supported", barejid);
+        session = _chat_session_new(barejid, NULL, TRUE);
+        g_hash_table_insert(sessions, strdup(barejid), session);
+    }
+
+    if (session->state != CHAT_STATE_COMPOSING) {
+        session->sent = FALSE;
+    }
+
+    session->state = CHAT_STATE_COMPOSING;
+    g_timer_start(session->active_timer);
+
+    if (!session->sent || session->state == CHAT_STATE_PAUSED) {
+        if (prefs_get_boolean(PREF_STATES) && prefs_get_boolean(PREF_OUTTYPE) && session->send_states) {
+            GString *jid = g_string_new(session->barejid);
+            if (session->resource) {
+                g_string_append(jid, "/");
+                g_string_append(jid, session->resource);
+            }
+            message_send_composing(jid->str);
+            g_string_free(jid, TRUE);
         }
+        session->sent = TRUE;
     }
 }
 
 void
-chat_session_on_activity(const char * const barejid)
+chat_session_on_inactivity(const char * const barejid)
 {
     ChatSession *session = g_hash_table_lookup(sessions, barejid);
-    if (session) {
-        if (session->supported) {
-            if (session->state != CHAT_STATE_COMPOSING) {
+    if (!session) {
+        return;
+    }
+
+    if (session->active_timer != NULL) {
+        gdouble elapsed = g_timer_elapsed(session->active_timer, NULL);
+
+        if ((prefs_get_gone() != 0) && (elapsed > (prefs_get_gone() * 60.0))) {
+            if (session->state != CHAT_STATE_GONE) {
+                session->sent = FALSE;
+            }
+            session->state = CHAT_STATE_GONE;
+
+        } else if (elapsed > INACTIVE_TIMOUT) {
+            if (session->state != CHAT_STATE_INACTIVE) {
                 session->sent = FALSE;
             }
+            session->state = CHAT_STATE_INACTIVE;
 
-            session->state = CHAT_STATE_COMPOSING;
-            g_timer_start(session->active_timer);
+        } else if (elapsed > PAUSED_TIMOUT) {
+            if (session->state == CHAT_STATE_COMPOSING) {
+                session->sent = FALSE;
+                session->state = CHAT_STATE_PAUSED;
+            }
+        }
+    }
 
-            if (!session->sent || session->state == CHAT_STATE_PAUSED) {
-                message_send_composing(barejid);
-                session->sent = TRUE;
+    if (session->sent == FALSE) {
+        GString *jid = g_string_new(session->barejid);
+        if (session->resource) {
+            g_string_append(jid, "/");
+            g_string_append(jid, session->resource);
+        }
+        if (session->state == CHAT_STATE_GONE) {
+            if (prefs_get_boolean(PREF_STATES) && session->send_states && session->includes_message) {
+                message_send_gone(jid->str);
+            }
+            session->sent = TRUE;
+            GString *log_msg = g_string_new("Removing chat session for ");
+            g_string_append(log_msg, barejid);
+            if (session->resource) {
+                g_string_append(log_msg, "/");
+                g_string_append(log_msg, session->resource);
+            }
+            log_debug(log_msg->str);
+            g_string_free(log_msg, TRUE);
+            g_hash_table_remove(sessions, barejid);
+        } else if (session->state == CHAT_STATE_INACTIVE) {
+            if (prefs_get_boolean(PREF_STATES) && session->send_states) {
+                message_send_inactive(jid->str);
             }
+            session->sent = TRUE;
+        } else if (session->state == CHAT_STATE_PAUSED && prefs_get_boolean(PREF_OUTTYPE)) {
+            if (prefs_get_boolean(PREF_STATES) && session->send_states) {
+                message_send_paused(jid->str);
+            }
+            session->sent = TRUE;
         }
+        g_string_free(jid, TRUE);
     }
 }
 
 void
-chat_session_on_inactivity(const char * const barejid)
+chat_session_on_cancel(const char * const jid)
 {
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-    if (session && session->supported) {
-        if (session->active_timer != NULL) {
-            gdouble elapsed = g_timer_elapsed(session->active_timer, NULL);
-
-            if ((prefs_get_gone() != 0) && (elapsed > (prefs_get_gone() * 60.0))) {
-                if (session->state != CHAT_STATE_GONE) {
-                    session->sent = FALSE;
-                }
-                session->state = CHAT_STATE_GONE;
-
-            } else if (elapsed > INACTIVE_TIMOUT) {
-                if (session->state != CHAT_STATE_INACTIVE) {
-                    session->sent = FALSE;
-                }
-                session->state = CHAT_STATE_INACTIVE;
-
-            } else if (elapsed > PAUSED_TIMOUT) {
-                if (session->state == CHAT_STATE_COMPOSING) {
-                    session->sent = FALSE;
-                    session->state = CHAT_STATE_PAUSED;
-                }
-            }
-        }
-
-        if (session->sent == FALSE) {
-            if (session->state == CHAT_STATE_GONE) {
-                message_send_gone(barejid);
-                session->sent = TRUE;
-            } else if (session->state == CHAT_STATE_INACTIVE) {
-                message_send_inactive(barejid);
-                session->sent = TRUE;
-            } else if (session->state == CHAT_STATE_PAUSED && prefs_get_boolean(PREF_OUTTYPE)) {
-                message_send_paused(barejid);
-                session->sent = TRUE;
+    Jid *jidp = jid_create(jid);
+    if (jidp) {
+        ChatSession *session = g_hash_table_lookup(sessions, jidp->barejid);
+        if (session) {
+            GString *log_msg = g_string_new("Removing chat session for ");
+            g_string_append(log_msg, jidp->barejid);
+            if (session->resource) {
+                g_string_append(log_msg, "/");
+                g_string_append(log_msg, session->resource);
             }
+            log_debug(log_msg->str);
+            g_string_free(log_msg, TRUE);
+            g_hash_table_remove(sessions, jidp->barejid);
         }
     }
 }
\ No newline at end of file
diff --git a/src/chat_session.h b/src/chat_session.h
index d1815f44..441f9096 100644
--- a/src/chat_session.h
+++ b/src/chat_session.h
@@ -40,12 +40,16 @@
 void chat_sessions_init(void);
 void chat_sessions_clear(void);
 
-gboolean chat_session_on_message_send(const char * const barejid);
-void chat_session_on_window_open(const char * const barejid);
+gboolean chat_session_exists(const char * const barejid);
+char* chat_session_get_resource(const char * const barejid);
+gboolean chat_session_send_states(const char * const barejid);
+
+void chat_session_on_message_send(const char * const barejid);
 void chat_session_on_window_close(const char * const barejid);
-void chat_session_on_incoming_message(const char * const barejid, gboolean supported);
+void chat_session_on_incoming_message(const char * const barejid, const char * const resource, gboolean send_states);
 void chat_session_on_cancel(const char * const jid);
+
 void chat_session_on_activity(const char * const barejid);
-void chat_session_on_inactivity(const char * const recipient);
+void chat_session_on_inactivity(const char * const barejid);
 
 #endif
diff --git a/src/command/command.c b/src/command/command.c
index 5c1f858d..7fd1616e 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -1814,8 +1814,7 @@ cmd_execute_default(const char * inp)
                 if (otr_is_secure(chatwin->barejid)) {
                     char *encrypted = otr_encrypt_message(chatwin->barejid, inp);
                     if (encrypted != NULL) {
-                        gboolean send_state = chat_session_on_message_send(chatwin->barejid);
-                        message_send_chat(chatwin->barejid, chatwin->resource, encrypted, send_state);
+                        message_send_chat(chatwin->barejid, encrypted);
                         otr_free_message(encrypted);
                         if (prefs_get_boolean(PREF_CHLOG)) {
                             const char *jid = jabber_get_fulljid();
@@ -1835,8 +1834,7 @@ cmd_execute_default(const char * inp)
                         cons_show_error("Failed to send message.");
                     }
                 } else {
-                    gboolean send_state = chat_session_on_message_send(chatwin->barejid);
-                    message_send_chat(chatwin->barejid, chatwin->resource, inp, send_state);
+                    message_send_chat(chatwin->barejid, inp);
                     if (prefs_get_boolean(PREF_CHLOG)) {
                         const char *jid = jabber_get_fulljid();
                         Jid *jidp = jid_create(jid);
@@ -1847,8 +1845,7 @@ cmd_execute_default(const char * inp)
                     ui_outgoing_chat_msg("me", chatwin->barejid, inp);
                 }
 #else
-                gboolean send_state = chat_session_on_message_send(chatwin->barejid);
-                message_send_chat(chatwin->barejid, chatwin->resource, inp, send_state);
+                message_send_chat(chatwin->barejid, inp);
                 if (prefs_get_boolean(PREF_CHLOG)) {
                     const char *jid = jabber_get_fulljid();
                     Jid *jidp = jid_create(jid);
diff --git a/src/command/commands.c b/src/command/commands.c
index 5b5bd95e..049582c0 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -1203,24 +1203,23 @@ cmd_msg(gchar **args, struct cmd_help_t help)
             barejid = usr;
         }
 
-        // if msg to current recipient, and resource specified, set resource
-        char *resource = NULL;
-        ProfWin *current = wins_get_current();
-        if (current->type == WIN_CHAT) {
-            ProfChatWin *chatwin = (ProfChatWin*)current;
-            assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
-            if ((g_strcmp0(chatwin->barejid, barejid) == 0) && (chatwin->resource)) {
-                resource = chatwin->resource;
-            }
-        }
+        // TODO if msg to current recipient, and resource specified, set resource
+//        char *resource = NULL;
+//        ProfWin *current = wins_get_current();
+//        if (current->type == WIN_CHAT) {
+//            ProfChatWin *chatwin = (ProfChatWin*)current;
+//            assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
+//            if ((g_strcmp0(chatwin->barejid, barejid) == 0) && (chatwin->resource)) {
+//                resource = chatwin->resource;
+//            }
+//        }
 
         if (msg != NULL) {
 #ifdef HAVE_LIBOTR
             if (otr_is_secure(barejid)) {
                 char *encrypted = otr_encrypt_message(barejid, msg);
                 if (encrypted != NULL) {
-                    gboolean send_state = chat_session_on_message_send(barejid);
-                    message_send_chat(barejid, resource, encrypted, send_state);
+                    message_send_chat(barejid, encrypted);
                     otr_free_message(encrypted);
                     ui_outgoing_chat_msg("me", barejid, msg);
 
@@ -1249,13 +1248,11 @@ cmd_msg(gchar **args, struct cmd_help_t help)
                     GString *otr_message = g_string_new(msg);
                     g_string_append(otr_message, OTRL_MESSAGE_TAG_BASE);
                     g_string_append(otr_message, OTRL_MESSAGE_TAG_V2);
-                    gboolean send_state = chat_session_on_message_send(barejid);
-                    message_send_chat(barejid, resource, otr_message->str, send_state);
+                    message_send_chat(barejid, otr_message->str);
 
                     g_string_free(otr_message, TRUE);
                 } else {
-                    gboolean send_state = chat_session_on_message_send(barejid);
-                    message_send_chat(barejid, resource, msg, send_state);
+                    message_send_chat(barejid, msg);
                 }
                 ui_outgoing_chat_msg("me", barejid, msg);
 
@@ -1268,8 +1265,7 @@ cmd_msg(gchar **args, struct cmd_help_t help)
             }
             return TRUE;
 #else
-            gboolean send_state = chat_session_on_message_send(barejid);
-            message_send_chat(barejid, resource, msg, send_state);
+            message_send_chat(barejid, msg);
             ui_outgoing_chat_msg("me", barejid, msg);
 
             if (((win_type == WIN_CHAT) || (win_type == WIN_CONSOLE)) && prefs_get_boolean(PREF_CHLOG)) {
@@ -1282,7 +1278,6 @@ cmd_msg(gchar **args, struct cmd_help_t help)
 #endif
 
         } else { // msg == NULL
-            chat_session_on_window_open(barejid);
             ui_new_chat_win(barejid);
 #ifdef HAVE_LIBOTR
             if (otr_is_secure(barejid)) {
@@ -3009,8 +3004,7 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                 if (otr_is_secure(chatwin->barejid)) {
                     char *encrypted = otr_encrypt_message(chatwin->barejid, tiny);
                     if (encrypted != NULL) {
-                        gboolean send_state = chat_session_on_message_send(chatwin->barejid);
-                        message_send_chat(chatwin->barejid, chatwin->resource, encrypted, send_state);
+                        message_send_chat(chatwin->barejid, encrypted);
                         otr_free_message(encrypted);
                         if (prefs_get_boolean(PREF_CHLOG)) {
                             const char *jid = jabber_get_fulljid();
@@ -3030,8 +3024,7 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                         cons_show_error("Failed to send message.");
                     }
                 } else {
-                    gboolean send_state = chat_session_on_message_send(chatwin->barejid);
-                    message_send_chat(chatwin->barejid, chatwin->resource, tiny, send_state);
+                    message_send_chat(chatwin->barejid, tiny);
                     if (prefs_get_boolean(PREF_CHLOG)) {
                         const char *jid = jabber_get_fulljid();
                         Jid *jidp = jid_create(jid);
@@ -3042,8 +3035,7 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                     ui_outgoing_chat_msg("me", chatwin->barejid, tiny);
                 }
 #else
-                gboolean send_state = chat_session_on_message_send(chatwin->barejid);
-                message_send_chat(chatwin->barejid, chatwin->resource, tiny, send_state);
+                message_send_chat(chatwin->barejid, tiny);
                 if (prefs_get_boolean(PREF_CHLOG)) {
                     const char *jid = jabber_get_fulljid();
                     Jid *jidp = jid_create(jid);
@@ -3951,7 +3943,6 @@ cmd_otr(gchar **args, struct cmd_help_t help)
                 barejid = contact;
             }
 
-            chat_session_on_window_open(barejid);
             ui_new_chat_win(barejid);
 
             if (ui_current_win_is_otr()) {
@@ -3961,8 +3952,7 @@ cmd_otr(gchar **args, struct cmd_help_t help)
                     ui_current_print_formatted_line('!', 0, "You have not generated or loaded a private key, use '/otr gen'");
                 } else if (!otr_is_secure(barejid)) {
                     char *otr_query_message = otr_start_query();
-                    gboolean send_state = chat_session_on_message_send(barejid);
-                    message_send_chat(barejid, NULL, otr_query_message, send_state);
+                    message_send_chat(barejid, otr_query_message);
                 } else {
                     ui_gone_secure(barejid, otr_is_trusted(barejid));
                 }
@@ -3980,8 +3970,7 @@ cmd_otr(gchar **args, struct cmd_help_t help)
                 } else {
                     ProfChatWin *chatwin = ui_get_current_chat();
                     char *otr_query_message = otr_start_query();
-                    gboolean send_state = chat_session_on_message_send(chatwin->barejid);
-                    message_send_chat(chatwin->barejid, NULL, otr_query_message, send_state);
+                    message_send_chat(chatwin->barejid, otr_query_message);
                 }
             }
         }
diff --git a/src/otr/otr.c b/src/otr/otr.c
index 680c4c10..bd1c2ce3 100644
--- a/src/otr/otr.c
+++ b/src/otr/otr.c
@@ -110,8 +110,7 @@ static void
 cb_inject_message(void *opdata, const char *accountname,
     const char *protocol, const char *recipient, const char *message)
 {
-    gboolean send_state = chat_session_on_message_send(recipient);
-    message_send_chat(recipient, NULL, message, send_state);
+    message_send_chat(recipient, message);
 }
 
 static void
diff --git a/src/server_events.c b/src/server_events.c
index 9d7883d6..02522f98 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -318,8 +318,7 @@ handle_incoming_message(char *barejid, char *message)
                 memmove(whitespace_base, whitespace_base+tag_length, tag_length);
                 char *otr_query_message = otr_start_query();
                 cons_show("OTR Whitespace pattern detected. Attempting to start OTR session...");
-                gboolean send_state = chat_session_on_message_send(barejid);
-                message_send_chat(barejid, NULL, otr_query_message, send_state);
+                message_send_chat(barejid, otr_query_message);
             }
         }
     }
@@ -333,8 +332,7 @@ handle_incoming_message(char *barejid, char *message)
     if (policy == PROF_OTRPOLICY_ALWAYS && !was_decrypted && !whitespace_base) {
         char *otr_query_message = otr_start_query();
         cons_show("Attempting to start OTR session...");
-        gboolean send_state = chat_session_on_message_send(barejid);
-        message_send_chat(barejid, NULL, otr_query_message, send_state);
+        message_send_chat(barejid, otr_query_message);
     }
 
     ui_incoming_msg(barejid, newmessage, NULL);
diff --git a/src/ui/core.c b/src/ui/core.c
index 2e8ae9ff..d5e01d94 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -705,7 +705,9 @@ ui_close_connected_win(int index)
                 otr_end_session(chatwin->barejid);
             }
 #endif
-            chat_session_on_window_close(chatwin->barejid);
+            if (chat_session_exists(chatwin->barejid)) {
+                chat_session_on_window_close(chatwin->barejid);
+            }
         }
     }
 }
@@ -1162,7 +1164,9 @@ ui_prune_wins(void)
         if (window->type == WIN_CHAT) {
             if (conn_status == JABBER_CONNECTED) {
                 ProfChatWin *chatwin = (ProfChatWin*)window;
-                chat_session_on_window_close(chatwin->barejid);
+                if (chat_session_exists(chatwin->barejid)) {
+                    chat_session_on_window_close(chatwin->barejid);
+                }
             }
         }
 
diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c
index 4165bd3f..19318745 100644
--- a/src/ui/inputwin.c
+++ b/src/ui/inputwin.c
@@ -151,17 +151,11 @@ inp_get_char(char *input, int *size, int *result)
         in_command = TRUE;
     }
 
-    if (prefs_get_boolean(PREF_STATES)) {
-        if (*result == ERR) {
-            prof_handle_idle();
-        }
-        if (prefs_get_boolean(PREF_OUTTYPE)
-                && (*result != ERR)
-                && (*result != KEY_CODE_YES)
-                && !in_command
-                && _printable(ch)) {
-            prof_handle_activity();
-        }
+    if (*result == ERR) {
+        prof_handle_idle();
+    }
+    if ((*result != ERR) && (*result != KEY_CODE_YES) && !in_command && _printable(ch)) {
+        prof_handle_activity();
     }
 
     // if it wasn't an arrow key etc
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index d87c5fb2..c3cbc14f 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -80,19 +80,23 @@ message_add_handlers(void)
 }
 
 void
-message_send_chat(const char * const barejid, const char * const resource, const char * const msg, gboolean send_state)
+message_send_chat(const char * const barejid, const char * const msg)
 {
     xmpp_stanza_t *message;
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
 
+    chat_session_on_message_send(barejid);
+    char *resource = chat_session_get_resource(barejid);
+    gboolean send_state = chat_session_send_states(barejid);
+
     GString *jid = g_string_new(barejid);
     if (resource) {
         g_string_append(jid, "/");
         g_string_append(jid, resource);
     }
 
-    if (send_state) {
+    if (prefs_get_boolean(PREF_STATES) && send_state) {
         message = stanza_create_message(ctx, jid->str, STANZA_TYPE_CHAT, msg, STANZA_NAME_ACTIVE);
     } else {
         message = stanza_create_message(ctx, jid->str, STANZA_TYPE_CHAT, msg, NULL);
@@ -149,23 +153,22 @@ message_send_invite(const char * const roomjid, const char * const contact,
 }
 
 void
-message_send_composing(const char * const barejid)
+message_send_composing(const char * const jid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
-        STANZA_NAME_COMPOSING);
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, jid, STANZA_NAME_COMPOSING);
 
     xmpp_send(conn, stanza);
     xmpp_stanza_release(stanza);
 }
 
 void
-message_send_paused(const char * const barejid)
+message_send_paused(const char * const jid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, jid,
         STANZA_NAME_PAUSED);
 
     xmpp_send(conn, stanza);
@@ -173,11 +176,11 @@ message_send_paused(const char * const barejid)
 }
 
 void
-message_send_inactive(const char * const barejid)
+message_send_inactive(const char * const jid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, jid,
         STANZA_NAME_INACTIVE);
 
     xmpp_send(conn, stanza);
@@ -185,11 +188,11 @@ message_send_inactive(const char * const barejid)
 }
 
 void
-message_send_gone(const char * const barejid)
+message_send_gone(const char * const jid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, jid,
         STANZA_NAME_GONE);
 
     xmpp_send(conn, stanza);
@@ -469,7 +472,7 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
         }
 
         // create or update chat session
-        chat_session_on_incoming_message(jid->barejid, recipient_supports);
+        chat_session_on_incoming_message(jid->barejid, jid->resourcepart, recipient_supports);
 
         // determine if the notifications happened whilst offline
         GTimeVal tv_stamp;
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 1766fe26..4f1d412d 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -199,15 +199,14 @@ stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char * const jid,
 #endif
 
 xmpp_stanza_t *
-stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient,
-    const char * const state)
+stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state)
 {
     xmpp_stanza_t *msg, *chat_state;
 
     msg = xmpp_stanza_new(ctx);
     xmpp_stanza_set_name(msg, STANZA_NAME_MESSAGE);
     xmpp_stanza_set_type(msg, STANZA_TYPE_CHAT);
-    xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, recipient);
+    xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, fulljid);
     char *id = create_unique_id(NULL);
     xmpp_stanza_set_id(msg, id);
     free(id);
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index e60e9fe1..84282401 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -179,7 +179,7 @@ typedef enum {
 xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx);
 
 xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx,
-    const char * const recipient, const char * const state);
+    const char * const fulljid, const char * const state);
 
 xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx,
     const char * const recipient, const char * const type,
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 2499d008..161eebdf 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -145,16 +145,15 @@ char* jabber_get_account_name(void);
 GList * jabber_get_available_resources(void);
 
 // message functions
-void message_send_chat(const char * const barejid, const char * const resource, const char * const msg,
-    gboolean send_state);
+void message_send_chat(const char * const barejid, const char * const msg);
 void message_send_private(const char * const fulljid, const char * const msg);
 void message_send_groupchat(const char * const roomjid, const char * const msg);
 void message_send_groupchat_subject(const char * const roomjid, const char * const subject);
 
-void message_send_inactive(const char * const barejid);
-void message_send_composing(const char * const barejid);
-void message_send_paused(const char * const barejid);
-void message_send_gone(const char * const barejid);
+void message_send_inactive(const char * const jid);
+void message_send_composing(const char * const jid);
+void message_send_paused(const char * const jid);
+void message_send_gone(const char * const jid);
 
 void message_send_invite(const char * const room, const char * const contact,
     const char * const reason);
diff --git a/tests/test_cmd_otr.c b/tests/test_cmd_otr.c
index 3cd9dd59..7d0adc1a 100644
--- a/tests/test_cmd_otr.c
+++ b/tests/test_cmd_otr.c
@@ -552,9 +552,7 @@ cmd_otr_start_sends_otr_query_message_to_current_recipeint(void **state)
     will_return(otr_start_query, query_message);
 
     expect_string(message_send_chat, barejid, chatwin->barejid);
-    expect_value(message_send_chat, resource, NULL);
     expect_string(message_send_chat, msg, query_message);
-    expect_any(message_send_chat, send_state);
 
     gboolean result = cmd_otr(args, *help);
     assert_true(result);
diff --git a/tests/test_server_events.c b/tests/test_server_events.c
index 435493a2..0b5cfd09 100644
--- a/tests/test_server_events.c
+++ b/tests/test_server_events.c
@@ -130,19 +130,20 @@ void handle_message_error_when_recipient_cancel_disables_chat_session(void **sta
 {
     char *err_msg = "Some error.";
     char *from = "bob@server.com";
+    char *resource = "resource";
     char *type = "cancel";
 
     prefs_set_boolean(PREF_STATES, TRUE);
     chat_sessions_init();
-    chat_session_on_incoming_message(from, TRUE);
+    chat_session_on_incoming_message(from, resource, TRUE);
 
     expect_any(ui_handle_recipient_not_found, recipient);
     expect_any(ui_handle_recipient_not_found, err_msg);
 
     handle_message_error(from, type, err_msg);
-    gboolean chat_session_supported = chat_session_on_message_send(from);
+    gboolean session_exists = chat_session_exists(from);
 
-    assert_false(chat_session_supported);
+    assert_false(session_exists);
     chat_sessions_clear();
 }
 
diff --git a/tests/xmpp/stub_xmpp.c b/tests/xmpp/stub_xmpp.c
index 580a6c61..a6058058 100644
--- a/tests/xmpp/stub_xmpp.c
+++ b/tests/xmpp/stub_xmpp.c
@@ -58,13 +58,10 @@ GList * jabber_get_available_resources(void)
 }
 
 // message functions
-void message_send_chat(const char * const barejid, const char * const resource, const char * const msg,
-    gboolean send_state)
+void message_send_chat(const char * const barejid, const char * const msg)
 {
     check_expected(barejid);
-    check_expected(resource);
     check_expected(msg);
-    check_expected(send_state);
 }
 
 void message_send_private(const char * const fulljid, const char * const msg) {}
@@ -218,4 +215,4 @@ void roster_send_add_new(const char * const barejid, const char * const name)
 void roster_send_remove(const char * const barejid)
 {
     check_expected(barejid);
-}
\ No newline at end of file
+}