about summary refs log tree commit diff stats
path: root/src/xmpp/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmpp/message.c')
-rw-r--r--src/xmpp/message.c250
1 files changed, 140 insertions, 110 deletions
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index 424c59ca..19657da0 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -75,6 +75,7 @@ typedef struct p_message_handle_t {
 } ProfMessageHandler;
 
 static int _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
+static void _private_chat_handler(xmpp_stanza_t *const stanza);
 
 static void _handle_error(xmpp_stanza_t *const stanza);
 static void _handle_groupchat(xmpp_stanza_t *const stanza);
@@ -178,6 +179,53 @@ message_handlers_init(void)
     pubsub_event_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
 }
 
+prof_message_t *
+message_init(void)
+{
+    prof_message_t *message = malloc(sizeof(prof_message_t));
+
+    message->jid = NULL;
+    message->id = NULL;
+    message->body = NULL;
+    message->encrypted = NULL;
+    message->plain = NULL;
+    message->enc = PROF_MSG_ENC_PLAIN;
+    message->timestamp = NULL;
+
+    return message;
+}
+
+void
+message_free(prof_message_t *message)
+{
+    xmpp_ctx_t *ctx = connection_get_ctx();
+    if (message->jid) {
+        jid_destroy(message->jid);
+    }
+
+    if (message->id) {
+        xmpp_free(ctx, message->id);
+    }
+
+    if (message->body) {
+        xmpp_free(ctx, message->body);
+    }
+
+    if (message->encrypted) {
+        xmpp_free(ctx, message->encrypted);
+    }
+
+    if (message->plain) {
+        free(message->plain);
+    }
+
+    if (message->timestamp) {
+        g_date_time_unref(message->timestamp);
+    }
+
+    free(message);
+}
+
 void
 message_handlers_clear(void)
 {
@@ -696,8 +744,6 @@ static void
 _handle_groupchat(xmpp_stanza_t *const stanza)
 {
     xmpp_ctx_t *ctx = connection_get_ctx();
-    int flags = 0;
-    char *message = NULL;
 
     const char *id = xmpp_stanza_get_id(stanza);
 
@@ -712,9 +758,10 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
     // handle room subject
     xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SUBJECT);
     if (subject) {
-        message = xmpp_stanza_get_text(subject);
-        sv_ev_room_subject(jid->barejid, jid->resourcepart, message);
-        xmpp_free(ctx, message);
+        char *subject_text;
+        subject_text = xmpp_stanza_get_text(subject);
+        sv_ev_room_subject(jid->barejid, jid->resourcepart, subject_text);
+        xmpp_free(ctx, subject_text);
 
         jid_destroy(jid);
         return;
@@ -722,14 +769,15 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
 
     // handle room broadcasts
     if (!jid->resourcepart) {
-        message = xmpp_message_get_body(stanza);
-        if (!message) {
+        char *broadcast;
+        broadcast = xmpp_message_get_body(stanza);
+        if (!broadcast) {
             jid_destroy(jid);
             return;
         }
 
-        sv_ev_room_broadcast(room_jid, message);
-        xmpp_free(ctx, message);
+        sv_ev_room_broadcast(room_jid, broadcast);
+        xmpp_free(ctx, broadcast);
 
         jid_destroy(jid);
         return;
@@ -748,37 +796,29 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
         return;
     }
 
+    prof_message_t *message = message_init();
+    message->jid = jid;
+    message->id = strdup(id);
+
     // check omemo encryption
 #ifdef HAVE_OMEMO
-    gboolean trusted = FALSE;
-    message = omemo_receive_message(stanza, &trusted);
-    if (message != NULL) {
-        flags |= MSG_ENC_OMEMO;
-        if (trusted) {
-            flags |= MSG_TRUSTED;
-        }
+    message->plain = omemo_receive_message(stanza, &message->trusted);
+    if (message->plain != NULL) {
+        message->enc = PROF_MSG_ENC_OMEMO;
     }
 #endif
 
-    if (!message) {
-        message = xmpp_message_get_body(stanza);
-        if (!message) {
-            jid_destroy(jid);
-            return;
-        }
-    }
+    message->body = xmpp_message_get_body(stanza);
 
     // determine if the notifications happened whilst offline
-    GDateTime *timestamp = stanza_get_delay(stanza);
-    if (timestamp) {
-        sv_ev_room_history(jid->barejid, jid->resourcepart, timestamp, message, flags);
-        g_date_time_unref(timestamp);
+    message->timestamp = stanza_get_delay(stanza);
+    if (message->timestamp) {
+        sv_ev_room_history(message);
     } else {
-        sv_ev_room_message(jid->barejid, jid->resourcepart, message, id, flags);
+        sv_ev_room_message(message);
     }
 
-    xmpp_free(ctx, message);
-    jid_destroy(jid);
+    message_free(message);
 }
 
 void
@@ -854,31 +894,38 @@ _receipt_request_handler(xmpp_stanza_t *const stanza)
     jid_destroy(jid);
 }
 
-void
-_private_chat_handler(xmpp_stanza_t *const stanza, const char *const fulljid)
+static void
+_private_chat_handler(xmpp_stanza_t *const stanza)
 {
-    char *message = xmpp_message_get_body(stanza);
-    if (!message) {
-        return;
+    // standard chat message, use jid without resource
+    prof_message_t *message = message_init();
+
+    const gchar *from = xmpp_stanza_get_from(stanza);
+    message->jid = jid_create(from);
+
+    // check omemo encryption
+#ifdef HAVE_OMEMO
+    message->plain = omemo_receive_message(stanza, &message->trusted);
+    if (message->plain != NULL) {
+        message->enc = PROF_MSG_ENC_OMEMO;
     }
+#endif
+
+    message->timestamp = stanza_get_delay(stanza);
+    message->body = xmpp_message_get_body(stanza);
 
-    GDateTime *timestamp = stanza_get_delay(stanza);
-    if (timestamp) {
-        sv_ev_delayed_private_message(fulljid, message, timestamp);
-        g_date_time_unref(timestamp);
+    if (message->timestamp) {
+        sv_ev_delayed_private_message(message);
     } else {
-        sv_ev_incoming_private_message(fulljid, message);
+        sv_ev_incoming_private_message(message);
     }
 
-    xmpp_ctx_t *ctx = connection_get_ctx();
-    xmpp_free(ctx, message);
+    message_free(message);
 }
 
 static gboolean
 _handle_carbons(xmpp_stanza_t *const stanza)
 {
-    char *message_txt = NULL;
-    int flags = 0;
     xmpp_stanza_t *carbons = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CARBONS);
     if (!carbons) {
         return FALSE;
@@ -906,32 +953,12 @@ _handle_carbons(xmpp_stanza_t *const stanza)
         return TRUE;
     }
 
-    xmpp_stanza_t *message = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE);
-    if (!message) {
+    xmpp_stanza_t *message_stanza = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE);
+    if (!message_stanza) {
         log_warning("Carbon received with no message element");
         return TRUE;
     }
 
-    // check omemo encryption
-#ifdef HAVE_OMEMO
-    gboolean trusted = FALSE;
-    message_txt = omemo_receive_message(message, &trusted);
-    if (message_txt != NULL) {
-        flags != MSG_ENC_OMEMO;
-        if (trusted) {
-            flags |= MSG_TRUSTED;
-        }
-    }
-#endif
-
-    if (!message_txt) {
-        message_txt = xmpp_message_get_body(message);
-        if (!message_txt) {
-            log_warning("Carbon received with no message.");
-            return TRUE;
-        }
-    }
-
     Jid *my_jid = jid_create(connection_get_fulljid());
     const char *const stanza_from = xmpp_stanza_get_from(stanza);
     if (g_strcmp0(my_jid->barejid, stanza_from) != 0) {
@@ -939,8 +966,20 @@ _handle_carbons(xmpp_stanza_t *const stanza)
         return TRUE;
     }
 
-    const gchar *to = xmpp_stanza_get_to(message);
-    const gchar *from = xmpp_stanza_get_from(message);
+    prof_message_t *message = message_init();
+
+    // check omemo encryption
+#ifdef HAVE_OMEMO
+    message->plain = omemo_receive_message(message_stanza, &message->trusted);
+    if (message->plain != NULL) {
+        message->enc = PROF_MSG_ENC_OMEMO;
+    }
+#endif
+
+    message->body = xmpp_message_get_body(message_stanza);
+
+    const gchar *to = xmpp_stanza_get_to(message_stanza);
+    const gchar *from = xmpp_stanza_get_from(message_stanza);
 
     // happens when receive a carbon of a self sent message
     if (!to) to = from;
@@ -949,27 +988,25 @@ _handle_carbons(xmpp_stanza_t *const stanza)
     Jid *jid_to = jid_create(to);
 
     // check for pgp encrypted message
-    char *enc_message = NULL;
-    xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(message, STANZA_NS_ENCRYPTED);
+    xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(message_stanza, STANZA_NS_ENCRYPTED);
     if (x) {
-        enc_message = xmpp_stanza_get_text(x);
+        message->encrypted = xmpp_stanza_get_text(x);
     }
 
     // if we are the recipient, treat as standard incoming message
     if (g_strcmp0(my_jid->barejid, jid_to->barejid) == 0) {
-        sv_ev_incoming_carbon(jid_from->barejid, jid_from->resourcepart, message_txt, enc_message, flags);
+        jid_destroy(jid_to);
+        message->jid = jid_from;
+        sv_ev_incoming_carbon(message);
 
     // else treat as a sent message
     } else {
-        sv_ev_outgoing_carbon(jid_to->barejid, message_txt, enc_message, flags);
+        jid_destroy(jid_from);
+        message->jid = jid_to;
+        sv_ev_outgoing_carbon(message);
     }
 
-    xmpp_ctx_t *ctx = connection_get_ctx();
-    xmpp_free(ctx, message_txt);
-    xmpp_free(ctx, enc_message);
-
-    jid_destroy(jid_from);
-    jid_destroy(jid_to);
+    message_free(message);
     jid_destroy(my_jid);
 
     return TRUE;
@@ -978,7 +1015,6 @@ _handle_carbons(xmpp_stanza_t *const stanza)
 static void
 _handle_chat(xmpp_stanza_t *const stanza)
 {
-    char *message = NULL;
     // ignore if type not chat or absent
     const char *type = xmpp_stanza_get_type(stanza);
     if (!(g_strcmp0(type, "chat") == 0 || type == NULL)) {
@@ -991,14 +1027,6 @@ _handle_chat(xmpp_stanza_t *const stanza)
         return;
     }
 
-    // check omemo encryption
-    gboolean omemo = FALSE;
-    gboolean trusted = FALSE;
-#ifdef HAVE_OMEMO
-    message = omemo_receive_message(stanza, &trusted);
-    omemo = message != NULL;
-#endif
-
     // ignore handled namespaces
     xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
     xmpp_stanza_t *captcha = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CAPTCHA);
@@ -1020,38 +1048,41 @@ _handle_chat(xmpp_stanza_t *const stanza)
 
     // private message from chat room use full jid (room/nick)
     if (muc_active(jid->barejid)) {
-        _private_chat_handler(stanza, jid->fulljid);
+        _private_chat_handler(stanza);
         jid_destroy(jid);
         return;
     }
 
     // standard chat message, use jid without resource
-    xmpp_ctx_t *ctx = connection_get_ctx();
-    GDateTime *timestamp = stanza_get_delay(stanza);
-    if (!message && body) {
-        message = xmpp_stanza_get_text(body);
+    prof_message_t *message = message_init();
+    message->jid = jid;
+
+    message->timestamp = stanza_get_delay(stanza);
+    if (body) {
+        message->body = xmpp_stanza_get_text(body);
     }
 
-    if (message) {
-        char *enc_message = NULL;
-        xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_ENCRYPTED);
-        if (x) {
-            enc_message = xmpp_stanza_get_text(x);
-        }
-        sv_ev_incoming_message(jid->barejid, jid->resourcepart, message, enc_message, timestamp, omemo, trusted);
-        xmpp_free(ctx, enc_message);
+    // check omemo encryption
+#ifdef HAVE_OMEMO
+    message->plain = omemo_receive_message(stanza, &message->trusted);
+    if (message->plain != NULL) {
+        message->enc = PROF_MSG_ENC_OMEMO;
+    }
+#endif
 
-        _receipt_request_handler(stanza);
+    xmpp_stanza_t *encrypted = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_ENCRYPTED);
+    if (encrypted) {
+        message->encrypted = xmpp_stanza_get_text(encrypted);
+    }
 
-        if (omemo) {
-            free(message);
-        } else {
-            xmpp_free(ctx, message);
-        }
+    if (message->plain || message->body || message->encrypted) {
+        sv_ev_incoming_message(message);
+
+        _receipt_request_handler(stanza);
     }
 
     // handle chat sessions and states
-    if (!timestamp && jid->resourcepart) {
+    if (!message->timestamp && jid->resourcepart) {
         gboolean gone = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL;
         gboolean typing = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL;
         gboolean paused = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL;
@@ -1071,8 +1102,7 @@ _handle_chat(xmpp_stanza_t *const stanza)
         }
     }
 
-    if (timestamp) g_date_time_unref(timestamp);
-    jid_destroy(jid);
+    message_free(message);
 }
 
 static void