about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2015-03-11 23:18:28 +0000
committerJames Booth <boothj5@gmail.com>2015-03-11 23:18:28 +0000
commit78becceedb19b1a793fcd3465363501f5468a83d (patch)
tree87a48969a86c6ed219e892083d9f43d7b29625a8 /src
parente5bb12a0d6223e6c6297c1700914332942a4ca00 (diff)
downloadprofani-tty-78becceedb19b1a793fcd3465363501f5468a83d.tar.gz
Added basic delivery receipts
Diffstat (limited to 'src')
-rw-r--r--src/config/preferences.c5
-rw-r--r--src/config/preferences.h1
-rw-r--r--src/server_events.c6
-rw-r--r--src/server_events.h1
-rw-r--r--src/ui/core.c13
-rw-r--r--src/ui/ui.h1
-rw-r--r--src/xmpp/message.c103
-rw-r--r--src/xmpp/stanza.c55
-rw-r--r--src/xmpp/stanza.h8
9 files changed, 156 insertions, 37 deletions
diff --git a/src/config/preferences.c b/src/config/preferences.c
index 0dbfe3e3..ce25ff9e 100644
--- a/src/config/preferences.c
+++ b/src/config/preferences.c
@@ -543,6 +543,7 @@ _get_group(preference_t pref)
         case PREF_CONNECT_ACCOUNT:
         case PREF_DEFAULT_ACCOUNT:
         case PREF_CARBONS:
+        case PREF_RECEIPTS:
             return PREF_GROUP_CONNECTION;
         case PREF_OTR_LOG:
         case PREF_OTR_POLICY:
@@ -579,6 +580,8 @@ _get_key(preference_t pref)
             return "history";
         case PREF_CARBONS:
             return "carbons";
+        case PREF_RECEIPTS:
+            return "receipts";
         case PREF_MOUSE:
             return "mouse";
         case PREF_OCCUPANTS:
@@ -730,4 +733,4 @@ _get_default_string(preference_t pref)
         default:
             return NULL;
     }
-}
+}
\ No newline at end of file
diff --git a/src/config/preferences.h b/src/config/preferences.h
index 7b29ae33..b031e857 100644
--- a/src/config/preferences.h
+++ b/src/config/preferences.h
@@ -60,6 +60,7 @@ typedef enum {
     PREF_INTYPE,
     PREF_HISTORY,
     PREF_CARBONS,
+    PREF_RECEIPTS,
     PREF_MOUSE,
     PREF_OCCUPANTS,
     PREF_OCCUPANTS_SIZE,
diff --git a/src/server_events.c b/src/server_events.c
index b0a9b1e3..2509dd43 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -403,6 +403,12 @@ handle_delayed_message(char *barejid, char *message, GTimeVal tv_stamp)
 }
 
 void
+handle_message_receipt(char *barejid, char *id)
+{
+    ui_message_receipt(barejid, id);
+}
+
+void
 handle_typing(char *barejid, char *resource)
 {
     ui_contact_typing(barejid, resource);
diff --git a/src/server_events.h b/src/server_events.h
index 042eb934..403c5bb5 100644
--- a/src/server_events.h
+++ b/src/server_events.h
@@ -79,6 +79,7 @@ void handle_inactive(char *barejid, char *resource);
 void handle_activity(char *barejid, char *resource, gboolean send_states);
 void handle_gone(const char * const barejid, const char * const resource);
 void handle_subscription(const char *from, jabber_subscr_t type);
+void handle_message_receipt(char *barejid, char *id);
 void handle_contact_offline(char *contact, char *resource, char *status);
 void handle_contact_online(char *contact, Resource *resource,
     GDateTime *last_activity);
diff --git a/src/ui/core.c b/src/ui/core.c
index b9f526cc..48143f48 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -382,6 +382,19 @@ ui_get_current_chat(void)
 }
 
 void
+ui_message_receipt(const char * const barejid, const char * const id)
+{
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        ProfWin *win = (ProfWin*) chatwin;
+        GString *message = g_string_new("Message received: ");
+        g_string_append(message, id);
+        win_save_println(win, message->str);
+        g_string_free(message, TRUE);
+    }
+}
+
+void
 ui_incoming_msg(const char * const barejid, const char * const resource, const char * const message, GTimeVal *tv_stamp)
 {
     gboolean win_created = FALSE;
diff --git a/src/ui/ui.h b/src/ui/ui.h
index a0408503..b621a539 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -116,6 +116,7 @@ void ui_handle_stanza(const char * const msg);
 void ui_contact_typing(const char * const barejid, const char * const resource);
 void ui_incoming_msg(const char * const from, const char * const resource,  const char * const message, GTimeVal *tv_stamp);
 void ui_incoming_private_msg(const char * const fulljid, const char * const message, GTimeVal *tv_stamp);
+void ui_message_receipt(const char * const barejid, const char * const id);
 
 void ui_disconnected(void);
 void ui_recipient_gone(const char * const barejid, const char * const resource);
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index ab7f52cd..739a95e6 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -82,25 +82,35 @@ message_add_handlers(void)
 void
 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();
 
     ChatSession *session = chat_session_get(barejid);
+    char *state = NULL;
+    char *jid = NULL;
     if (session) {
-        char *state = NULL;
         if (prefs_get_boolean(PREF_STATES) && session->send_states) {
             state = STANZA_NAME_ACTIVE;
         }
         Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource);
-        message = stanza_create_message(ctx, jidp->fulljid, STANZA_TYPE_CHAT, msg, state, false);
+        jid = strdup(jidp->fulljid);
         jid_destroy(jidp);
+
     } else {
-        char *state = NULL;
         if (prefs_get_boolean(PREF_STATES)) {
             state = STANZA_NAME_ACTIVE;
         }
-        message = stanza_create_message(ctx, barejid, STANZA_TYPE_CHAT, msg, state, false);
+        jid = strdup(barejid);
+    }
+
+    xmpp_stanza_t *message = stanza_create_message(ctx, jid, STANZA_TYPE_CHAT, msg);
+    free(jid);
+
+    if (state) {
+        stanza_attach_state(ctx, message, state);
+    }
+    if (prefs_get_boolean(PREF_RECEIPTS)) {
+        stanza_attach_receipt_request(ctx, message);
     }
 
     xmpp_send(conn, message);
@@ -110,25 +120,35 @@ message_send_chat(const char * const barejid, const char * const msg)
 void
 message_send_chat_encrypted(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();
 
     ChatSession *session = chat_session_get(barejid);
+    char *state = NULL;
+    char *jid = NULL;
     if (session) {
-        char *state = NULL;
         if (prefs_get_boolean(PREF_STATES) && session->send_states) {
             state = STANZA_NAME_ACTIVE;
         }
         Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource);
-        message = stanza_create_message(ctx, jidp->fulljid, STANZA_TYPE_CHAT, msg, state, true);
+        jid = strdup(jidp->fulljid);
         jid_destroy(jidp);
     } else {
-        char *state = NULL;
         if (prefs_get_boolean(PREF_STATES)) {
             state = STANZA_NAME_ACTIVE;
         }
-        message = stanza_create_message(ctx, barejid, STANZA_TYPE_CHAT, msg, state, true);
+        jid = strdup(barejid);
+    }
+
+    xmpp_stanza_t *message = stanza_create_message(ctx, barejid, STANZA_TYPE_CHAT, msg);
+    free(jid);
+
+    if (state) {
+        stanza_attach_state(ctx, message, state);
+    }
+    stanza_attach_carbons_private(ctx, message);
+    if (prefs_get_boolean(PREF_RECEIPTS)) {
+        stanza_attach_receipt_request(ctx, message);
     }
 
     xmpp_send(conn, message);
@@ -140,7 +160,7 @@ message_send_private(const char * const fulljid, const char * const msg)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *message = stanza_create_message(ctx, fulljid, STANZA_TYPE_CHAT, msg, NULL, false);
+    xmpp_stanza_t *message = stanza_create_message(ctx, fulljid, STANZA_TYPE_CHAT, msg);
 
     xmpp_send(conn, message);
     xmpp_stanza_release(message);
@@ -151,7 +171,7 @@ message_send_groupchat(const char * const roomjid, const char * const msg)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *message = stanza_create_message(ctx, roomjid, STANZA_TYPE_GROUPCHAT, msg, NULL, false);
+    xmpp_stanza_t *message = stanza_create_message(ctx, roomjid, STANZA_TYPE_GROUPCHAT, msg);
 
     xmpp_send(conn, message);
     xmpp_stanza_release(message);
@@ -441,6 +461,29 @@ _groupchat_handler(xmpp_conn_t * const conn,
     return 1;
 }
 
+void
+_message_send_receipt(const char * const fulljid, const char * const message_id)
+{
+    xmpp_conn_t * const conn = connection_get_conn();
+    xmpp_ctx_t * const ctx = connection_get_ctx();
+    xmpp_stanza_t *message = xmpp_stanza_new(ctx);
+    char *id = create_unique_id("receipt");
+    xmpp_stanza_set_name(message, STANZA_NAME_MESSAGE);
+    xmpp_stanza_set_id(message, id);
+    xmpp_stanza_set_attribute(message, STANZA_ATTR_TO, fulljid);
+
+    xmpp_stanza_t *receipt = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(receipt, "received");
+    xmpp_stanza_set_ns(receipt, STANZA_NS_RECEIPTS);
+    xmpp_stanza_set_attribute(receipt, STANZA_ATTR_ID, message_id);
+
+    xmpp_stanza_add_child(message, receipt);
+    xmpp_stanza_release(receipt);
+
+    xmpp_send(conn, message);
+    xmpp_stanza_release(message);
+}
+
 static int
 _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
     void * const userdata)
@@ -451,10 +494,28 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
         return 1;
     }
 
+    // check if message receipt
+    xmpp_stanza_t *receipt = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_RECEIPTS);
+    if (receipt) {
+        char *name = xmpp_stanza_get_name(receipt);
+        if (g_strcmp0(name, "received") == 0) {
+            char *id = xmpp_stanza_get_attribute(receipt, STANZA_ATTR_ID);
+            if (id) {
+                char *fulljid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+                if (fulljid) {
+                    Jid *jidp = jid_create(fulljid);
+                    handle_message_receipt(jidp->barejid, id);
+                    jid_destroy(jidp);
+                }
+
+            }
+        }
+    }
+
     // check if carbon message
-    xmpp_stanza_t *received = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CARBONS);
-    if(received != NULL){
-        xmpp_stanza_t *forwarded = xmpp_stanza_get_child_by_ns(received, STANZA_NS_FORWARD);
+    xmpp_stanza_t *carbons = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CARBONS);
+    if (carbons){
+        xmpp_stanza_t *forwarded = xmpp_stanza_get_child_by_ns(carbons, STANZA_NS_FORWARD);
         xmpp_stanza_t *message = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE);
 
         xmpp_ctx_t *ctx = connection_get_ctx();
@@ -535,6 +596,7 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
         // determine if the notifications happened whilst offline
         GTimeVal tv_stamp;
         gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
+        char *id = xmpp_stanza_get_id(stanza);
 
         // check for and deal with message
         xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
@@ -546,6 +608,15 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
                 } else {
                     handle_incoming_message(jid->barejid, jid->resourcepart, message);
                 }
+                if (id) {
+                    xmpp_stanza_t *receipts = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_RECEIPTS);
+                    if (receipts) {
+                        char *receipts_name = xmpp_stanza_get_name(receipts);
+                        if (g_strcmp0(receipts_name, "request") == 0) {
+                            _message_send_receipt(jid->fulljid, id);
+                        }
+                    }
+                }
                 xmpp_free(ctx, message);
             }
         }
@@ -574,4 +645,4 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
         jid_destroy(jid);
         return 1;
     }
-}
+}
\ No newline at end of file
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index e849ac97..635f5678 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -282,9 +282,44 @@ stanza_create_room_subject_message(xmpp_ctx_t *ctx, const char * const room, con
 }
 
 xmpp_stanza_t *
+stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state)
+{
+    xmpp_stanza_t *chat_state = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(chat_state, state);
+    xmpp_stanza_set_ns(chat_state, STANZA_NS_CHATSTATES);
+    xmpp_stanza_add_child(stanza, chat_state);
+    xmpp_stanza_release(chat_state);
+
+    return stanza;
+}
+
+xmpp_stanza_t *
+stanza_attach_carbons_private(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza)
+{
+    xmpp_stanza_t *private_carbon = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(private_carbon, "private");
+    xmpp_stanza_set_ns(private_carbon, STANZA_NS_CARBONS);
+    xmpp_stanza_add_child(stanza, private_carbon);
+    xmpp_stanza_release(private_carbon);
+
+    return stanza;
+}
+
+xmpp_stanza_t *
+stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza)
+{
+    xmpp_stanza_t *receipet_request = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(receipet_request, "request");
+    xmpp_stanza_set_ns(receipet_request, STANZA_NS_RECEIPTS);
+    xmpp_stanza_add_child(stanza, receipet_request);
+    xmpp_stanza_release(receipet_request);
+
+    return stanza;
+}
+
+xmpp_stanza_t *
 stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
-    const char * const type, const char * const message,
-    const char * const state, gboolean encrypted)
+    const char * const type, const char * const message)
 {
     xmpp_stanza_t *msg, *body, *text;
 
@@ -306,22 +341,6 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
     xmpp_stanza_add_child(msg, body);
     xmpp_stanza_release(body);
 
-    if (state != NULL) {
-        xmpp_stanza_t *chat_state = xmpp_stanza_new(ctx);
-        xmpp_stanza_set_name(chat_state, state);
-        xmpp_stanza_set_ns(chat_state, STANZA_NS_CHATSTATES);
-        xmpp_stanza_add_child(msg, chat_state);
-        xmpp_stanza_release(chat_state);
-    }
-
-    if (encrypted) {
-        xmpp_stanza_t *private_carbon = xmpp_stanza_new(ctx);
-        xmpp_stanza_set_name(private_carbon, "private");
-        xmpp_stanza_set_ns(private_carbon, STANZA_NS_CARBONS);
-        xmpp_stanza_add_child(msg, private_carbon);
-        xmpp_stanza_release(private_carbon);
-    }
-
     return msg;
 }
 
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 365bed86..eca3bf8a 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -158,6 +158,7 @@
 #define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub"
 #define STANZA_NS_CARBONS "urn:xmpp:carbons:2"
 #define STANZA_NS_FORWARD "urn:xmpp:forward:0"
+#define STANZA_NS_RECEIPTS "urn:xmpp:receipts"
 
 #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
 
@@ -189,9 +190,12 @@ xmpp_stanza_t * stanza_disable_carbons(xmpp_ctx_t *ctx);
 xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx,
     const char * const fulljid, const char * const state);
 
+xmpp_stanza_t * stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state);
+xmpp_stanza_t * stanza_attach_carbons_private(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
+xmpp_stanza_t * stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
+
 xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx,
-    const char * const recipient, const char * const type,
-    const char * const message, const char * const state, gboolean encrypted);
+    const char * const recipient, const char * const type, const char * const message);
 
 xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
     const char * const full_room_jid, const char * const passwd);