about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2014-01-26 18:30:34 +0000
committerJames Booth <boothj5@gmail.com>2014-01-26 18:30:34 +0000
commit292ae567aa0766dba4975c02379ec0e4a4ac3ecd (patch)
tree01710c63cc73d269ac47091dca4abb3385a9656c /src
parent46b3ff6f440546a6cc253610b05f3ae957f094e7 (diff)
downloadprofani-tty-292ae567aa0766dba4975c02379ec0e4a4ac3ecd.tar.gz
Handle recipient not found
Diffstat (limited to 'src')
-rw-r--r--src/profanity.c36
-rw-r--r--src/server_events.c10
-rw-r--r--src/server_events.h1
-rw-r--r--src/ui/core.c27
-rw-r--r--src/ui/ui.h1
-rw-r--r--src/xmpp/message.c34
-rw-r--r--src/xmpp/stanza.c65
-rw-r--r--src/xmpp/stanza.h26
8 files changed, 183 insertions, 17 deletions
diff --git a/src/profanity.c b/src/profanity.c
index 827cd962..6e15f1dd 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -128,18 +128,20 @@ prof_handle_idle(void)
 
         while (curr != NULL) {
             char *recipient = curr->data;
-            chat_session_no_activity(recipient);
-
-            if (chat_session_is_gone(recipient) &&
-                    !chat_session_get_sent(recipient)) {
-                message_send_gone(recipient);
-            } else if (chat_session_is_inactive(recipient) &&
-                    !chat_session_get_sent(recipient)) {
-                message_send_inactive(recipient);
-            } else if (prefs_get_boolean(PREF_OUTTYPE) &&
-                    chat_session_is_paused(recipient) &&
-                    !chat_session_get_sent(recipient)) {
-                message_send_paused(recipient);
+            if (chat_session_get_recipient_supports(recipient)) {
+                chat_session_no_activity(recipient);
+
+                if (chat_session_is_gone(recipient) &&
+                        !chat_session_get_sent(recipient)) {
+                    message_send_gone(recipient);
+                } else if (chat_session_is_inactive(recipient) &&
+                        !chat_session_get_sent(recipient)) {
+                    message_send_inactive(recipient);
+                } else if (prefs_get_boolean(PREF_OUTTYPE) &&
+                        chat_session_is_paused(recipient) &&
+                        !chat_session_get_sent(recipient)) {
+                    message_send_paused(recipient);
+                }
             }
 
             curr = g_slist_next(curr);
@@ -159,10 +161,12 @@ prof_handle_activity(void)
 
     if ((status == JABBER_CONNECTED) && (win_type == WIN_CHAT)) {
         char *recipient = ui_current_recipient();
-        chat_session_set_composing(recipient);
-        if (!chat_session_get_sent(recipient) ||
-                chat_session_is_paused(recipient)) {
-            message_send_composing(recipient);
+        if (chat_session_get_recipient_supports(recipient)) {
+            chat_session_set_composing(recipient);
+            if (!chat_session_get_sent(recipient) ||
+                    chat_session_is_paused(recipient)) {
+                message_send_composing(recipient);
+            }
         }
     }
 }
diff --git a/src/server_events.c b/src/server_events.c
index a87d22a2..6ca832d0 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -53,6 +53,16 @@ handle_error_message(const char *from, const char *err_msg)
 }
 
 void
+handle_recipient_not_found(const char *from)
+{
+    log_info("Removing chat session for %s", from);
+    ui_handle_recipient_not_found(from);
+    if (prefs_get_boolean(PREF_STATES)) {
+        chat_session_set_recipient_supports(from, FALSE);
+    }
+}
+
+void
 handle_login_account_success(char *account_name)
 {
     ProfAccount *account = accounts_get_account(account_name);
diff --git a/src/server_events.h b/src/server_events.h
index 7704cd44..34f99c79 100644
--- a/src/server_events.h
+++ b/src/server_events.h
@@ -75,5 +75,6 @@ void handle_group_remove(const char * const contact,
 void handle_roster_remove(const char * const barejid);
 void handle_roster_add(const char * const barejid, const char * const name);
 void handle_autoping_cancel(void);
+void handle_recipient_not_found(const char *from);
 
 #endif
diff --git a/src/ui/core.c b/src/ui/core.c
index 43b22f83..cad43e59 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -355,6 +355,32 @@ _ui_handle_error_message(const char * const from, const char * const err_msg)
 }
 
 static void
+_ui_handle_recipient_not_found(const char * const from)
+{
+    ProfWin *win = wins_get_by_recipient(from);
+    GString *msg = g_string_new("");
+
+    // Message sent to chat room which hasn't been entered yet
+    if (win->type == WIN_MUC) {
+        g_string_printf(msg, "You have not joined %s.", from);
+
+    // unknown chat recipient
+    } else {
+        if (prefs_get_boolean(PREF_STATES)) {
+            chat_session_set_recipient_supports(from, FALSE);
+        }
+        g_string_printf(msg, "Recipient %s not found at server.", from);
+    }
+
+    cons_show_error(msg->str);
+    win_print_line(win, '!', COLOUR_ERROR, msg->str);
+
+    wins_refresh_current();
+
+    g_string_free(msg, TRUE);
+}
+
+static void
 _ui_disconnected(void)
 {
     wins_lost_connection();
@@ -1718,4 +1744,5 @@ ui_init_module(void)
     ui_untrust = _ui_untrust;
     ui_chat_win_contact_online = _ui_chat_win_contact_online;
     ui_chat_win_contact_offline = _ui_chat_win_contact_offline;
+    ui_handle_recipient_not_found = _ui_handle_recipient_not_found;
 }
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 9671b1af..11ffa765 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -130,6 +130,7 @@ void (*ui_group_added)(const char * const contact, const char * const group);
 void (*ui_group_removed)(const char * const contact, const char * const group);
 void (*ui_chat_win_contact_online)(PContact contact, Resource *resource, GDateTime *last_activity);
 void (*ui_chat_win_contact_offline)(PContact contact, char *resource, char *status);
+void (*ui_handle_recipient_not_found)(const char * const from);
 
 // contact status functions
 void (*ui_status_room)(const char * const contact);
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index bd31f594..bb5c58eb 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -37,6 +37,7 @@
 #include "roster_list.h"
 #include "xmpp/stanza.h"
 #include "xmpp/xmpp.h"
+#include "ui/ui.h"
 
 #define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_MESSAGE, type, ctx)
 
@@ -50,6 +51,8 @@ static int _conference_handler(xmpp_conn_t * const conn,
     xmpp_stanza_t * const stanza, void * const userdata);
 static int _captcha_handler(xmpp_conn_t * const conn,
     xmpp_stanza_t * const stanza, void * const userdata);
+static int _message_error_handler(xmpp_conn_t * const conn,
+    xmpp_stanza_t * const stanza, void * const userdata);
 
 void
 message_add_handlers(void)
@@ -57,7 +60,7 @@ message_add_handlers(void)
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
 
-    HANDLE(NULL,                 STANZA_TYPE_ERROR,      connection_error_handler);
+    HANDLE(NULL,                 STANZA_TYPE_ERROR,      _message_error_handler);
     HANDLE(NULL,                 STANZA_TYPE_GROUPCHAT,  _groupchat_handler);
     HANDLE(NULL,                 STANZA_TYPE_CHAT,       _chat_handler);
     HANDLE(STANZA_NS_MUC_USER,   NULL,                   _muc_user_handler);
@@ -187,6 +190,35 @@ _message_send_gone(const char * const recipient)
 }
 
 static int
+_message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
+    void * const userdata)
+{
+    // log message, function never returns NULL
+    char *err_msg = stanza_get_error_message(stanza);
+    char *id = xmpp_stanza_get_id(stanza);
+    if (id != NULL) {
+        log_info("Error recieved (id=%s): %s", id, err_msg);
+    } else {
+        log_info("Error received: %s", err_msg);
+    }
+
+    char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+    xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
+    char *type = NULL;
+    if (error_stanza != NULL) {
+        type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE);
+    }
+
+    // handle recipient not found
+    if ((from != NULL) && ((type != NULL && (strcmp(type, "cancel") == 0)))) {
+        log_info("Recipient %s not found.", from);
+        handle_recipient_not_found(from);
+    }
+
+    return 1;
+}
+
+static int
 _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
     void * const userdata)
 {
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 7f754dd3..756d3d44 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -821,6 +821,71 @@ stanza_get_caps_str(xmpp_stanza_t * const stanza)
     return  caps_str;
 }
 
+char *
+stanza_get_error_message(xmpp_stanza_t *stanza)
+{
+    xmpp_ctx_t *ctx = connection_get_ctx();
+    xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
+
+    // return nothing if no error stanza
+    if (error_stanza == NULL) {
+        return strdup("unknown");
+    } else {
+        xmpp_stanza_t *text_stanza = xmpp_stanza_get_child_by_name(error_stanza, STANZA_NAME_TEXT);
+
+        // check for text
+        if (text_stanza != NULL) {
+            gchar *err_msg = xmpp_stanza_get_text(text_stanza);
+            if (err_msg != NULL) {
+                char *result =  strdup(err_msg);
+                xmpp_free(ctx, err_msg);
+                return result;
+            }
+
+        // otherwise check each defined-condition RFC-6120 8.3.3
+        } else {
+            xmpp_stanza_t *cond_stanza = NULL;
+
+            gchar *defined_conditions[] = {
+                STANZA_NAME_BAD_REQUEST,
+                STANZA_NAME_CONFLICT,
+                STANZA_NAME_FEATURE_NOT_IMPLEMENTED,
+                STANZA_NAME_FORBIDDEN,
+                STANZA_NAME_GONE,
+                STANZA_NAME_INTERNAL_SERVER_ERROR,
+                STANZA_NAME_ITEM_NOT_FOUND,
+                STANZA_NAME_JID_MALFORMED,
+                STANZA_NAME_NOT_ACCEPTABLE,
+                STANZA_NAME_NOT_ALLOWED,
+                STANZA_NAME_NOT_AUTHORISED,
+                STANZA_NAME_POLICY_VIOLATION,
+                STANZA_NAME_RECIPIENT_UNAVAILABLE,
+                STANZA_NAME_REDIRECT,
+                STANZA_NAME_REGISTRATION_REQUIRED,
+                STANZA_NAME_REMOTE_SERVER_NOT_FOUND,
+                STANZA_NAME_REMOTE_SERVER_TIMEOUT,
+                STANZA_NAME_RESOURCE_CONSTRAINT,
+                STANZA_NAME_SERVICE_UNAVAILABLE,
+                STANZA_NAME_SUBSCRIPTION_REQUIRED,
+                STANZA_NAME_UNEXPECTED_REQUEST
+            };
+
+            int i;
+            for (i = 0; i < ARRAY_SIZE(defined_conditions); i++) {
+                cond_stanza = xmpp_stanza_get_child_by_name(error_stanza, defined_conditions[i]);
+                if (cond_stanza != NULL) {
+                    char *result = strdup(xmpp_stanza_get_name(cond_stanza));
+                    return result;
+                }
+            }
+
+        }
+    }
+
+    // if undefined-condition or no condition, return nothing
+    return strdup("unknown");
+}
+
 DataForm *
 stanza_create_form(xmpp_stanza_t * const stanza)
 {
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 16aa076a..c84c9b1f 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -56,6 +56,30 @@
 #define STANZA_NAME_STORAGE "storage"
 #define STANZA_NAME_CONFERENCE "conference"
 
+// error conditions
+#define STANZA_NAME_BAD_REQUEST "bad-request"
+#define STANZA_NAME_CONFLICT "conflict"
+#define STANZA_NAME_FEATURE_NOT_IMPLEMENTED "feature-not-implemented"
+#define STANZA_NAME_FORBIDDEN "forbidden"
+#define STANZA_NAME_GONE "gone"
+#define STANZA_NAME_INTERNAL_SERVER_ERROR "internal-server-error"
+#define STANZA_NAME_ITEM_NOT_FOUND "item-not-found"
+#define STANZA_NAME_JID_MALFORMED "jid-malformed"
+#define STANZA_NAME_NOT_ACCEPTABLE "not-acceptable"
+#define STANZA_NAME_NOT_ALLOWED "not-allowed"
+#define STANZA_NAME_NOT_AUTHORISED "not-authorised"
+#define STANZA_NAME_POLICY_VIOLATION "policy-violation"
+#define STANZA_NAME_RECIPIENT_UNAVAILABLE "recipient-unavailable"
+#define STANZA_NAME_REDIRECT "redirect"
+#define STANZA_NAME_REGISTRATION_REQUIRED "registration-required"
+#define STANZA_NAME_REMOTE_SERVER_NOT_FOUND "remote-server-not-found"
+#define STANZA_NAME_REMOTE_SERVER_TIMEOUT "remote-server-timeout"
+#define STANZA_NAME_RESOURCE_CONSTRAINT "resource-constraint"
+#define STANZA_NAME_SERVICE_UNAVAILABLE "service-unavailable"
+#define STANZA_NAME_SUBSCRIPTION_REQUIRED "subscription-required"
+#define STANZA_NAME_UNDEFINED_CONDITION "undefined-condition"
+#define STANZA_NAME_UNEXPECTED_REQUEST "unexpected-request"
+
 #define STANZA_TYPE_CHAT "chat"
 #define STANZA_TYPE_GROUPCHAT "groupchat"
 #define STANZA_TYPE_UNAVAILABLE "unavailable"
@@ -190,4 +214,6 @@ xmpp_stanza_t * stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const id,
 xmpp_stanza_t * stanza_create_roster_remove_set(xmpp_ctx_t *ctx,
     const char * const barejid);
 
+char * stanza_get_error_message(xmpp_stanza_t * const stanza);
+
 #endif