about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorMarcoPolo-PasTonMolo <marcopolopastonmolo@protonmail.com>2022-07-03 21:23:07 +0300
committerMarcoPolo-PasTonMolo <marcopolopastonmolo@protonmail.com>2022-07-03 21:23:07 +0300
commitf0202a2fe0da0a1aa05009b875dffe47bfa3df8d (patch)
treea62f0792df34fae5796fe55743485ac79bd3f825 /src
parent476c73251c2787930f866c76484eb1417a834cea (diff)
downloadprofani-tty-f0202a2fe0da0a1aa05009b875dffe47bfa3df8d.tar.gz
On new chatwin fetch mam according to guidelines.
Taken from here:
https://github.com/modernxmpp/modernxmpp/commit/cd3e871e55c2cff45dffd05d6e50380b99845849
Diffstat (limited to 'src')
-rw-r--r--src/database.c45
-rw-r--r--src/database.h1
-rw-r--r--src/xmpp/iq.c61
-rw-r--r--src/xmpp/stanza.c89
-rw-r--r--src/xmpp/stanza.h4
5 files changed, 161 insertions, 39 deletions
diff --git a/src/database.c b/src/database.c
index 6e10b222..6f719aa2 100644
--- a/src/database.c
+++ b/src/database.c
@@ -187,6 +187,51 @@ log_database_add_outgoing_muc_pm(const char* const id, const char* const barejid
     _log_database_add_outgoing("mucpm", id, barejid, message, replace_id, enc);
 }
 
+// Get info (timestamp and stanza_id) of the first or last message in db
+ProfMessage*
+log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_last)
+{
+    sqlite3_stmt* stmt = NULL;
+    gchar* query;
+    const char* jid = connection_get_fulljid();
+    Jid* myjid = jid_create(jid);
+    if (!myjid)
+        return NULL;
+
+    if (is_last) {
+        query = sqlite3_mprintf("SELECT * FROM (SELECT `archive_id`, `timestamp` from `ChatLogs` WHERE (`from_jid` = '%q' AND `to_jid` = '%q') OR (`from_jid` = '%q' AND `to_jid` = '%q') ORDER BY `timestamp` DESC LIMIT 1) ORDER BY `timestamp` ASC;", contact_barejid, myjid->barejid, myjid->barejid, contact_barejid);
+    } else {
+        query = sqlite3_mprintf("SELECT * FROM (SELECT `archive_id`, `timestamp` from `ChatLogs` WHERE (`from_jid` = '%q' AND `to_jid` = '%q') OR (`from_jid` = '%q' AND `to_jid` = '%q') ORDER BY `timestamp` ASC LIMIT 1) ORDER BY `timestamp` ASC;", contact_barejid, myjid->barejid, myjid->barejid, contact_barejid);
+    }
+
+    if (!query) {
+        log_error("log_database_get_last_info(): SQL query. could not allocate memory");
+        return NULL;
+    }
+
+    jid_destroy(myjid);
+
+    int rc = sqlite3_prepare_v2(g_chatlog_database, query, -1, &stmt, NULL);
+    if (rc != SQLITE_OK) {
+        log_error("log_database_get_last_info(): unknown SQLite error");
+        return NULL;
+    }
+
+    ProfMessage* msg = message_init();
+
+    if (sqlite3_step(stmt) == SQLITE_ROW) {
+        char* archive_id = (char*)sqlite3_column_text(stmt, 0);
+        char* date = (char*)sqlite3_column_text(stmt, 1);
+
+        msg->stanzaid = strdup(archive_id);
+        msg->timestamp = g_date_time_new_from_iso8601(date, NULL);
+    }
+    sqlite3_finalize(stmt);
+    sqlite3_free(query);
+
+    return msg;
+}
+
 GSList*
 log_database_get_previous_chat(const gchar* const contact_barejid)
 {
diff --git a/src/database.h b/src/database.h
index a29b0808..21f04595 100644
--- a/src/database.h
+++ b/src/database.h
@@ -46,6 +46,7 @@ void log_database_add_outgoing_chat(const char* const id, const char* const bare
 void log_database_add_outgoing_muc(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
 void log_database_add_outgoing_muc_pm(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
 GSList* log_database_get_previous_chat(const gchar* const contact_barejid);
+ProfMessage* log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_last);
 void log_database_close(void);
 
 #endif // DATABASE_H
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index 8d40a86f..9918354e 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -2582,24 +2582,43 @@ iq_mam_request(ProfChatWin* win)
         return;
     }
 
+    ProfMessage* last_msg = log_database_get_limits_info(win->barejid, TRUE);
+    char* lastid = NULL;
+    char* firstid = NULL;
+    char* startdate = NULL;
+    char* enddate = NULL;
+    gboolean should_add_rsm_handler = TRUE;
+
+    // If last message found
+    if (last_msg->timestamp) {
+        lastid = last_msg->stanzaid;
+        startdate = g_date_time_format(last_msg->timestamp, "%FT%T.%f%:z");
+
+    } else {
+        GDateTime* now = g_date_time_new_now_utc();
+        enddate = g_date_time_format(now, "%FT%T.%f%:z");
+        g_date_time_unref(now);
+        // To get last page we need to set before to empty string
+        firstid = "";
+        should_add_rsm_handler = FALSE;
+    }
+
     xmpp_ctx_t* const ctx = connection_get_ctx();
 
-    GDateTime* now = g_date_time_new_now_utc();
-    GDateTime* timestamp = g_date_time_add_days(now, -7);
-    g_date_time_unref(now);
-    gchar* datestr = g_date_time_format(timestamp, "%FT%TZ");
-    xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, datestr, NULL);
+    xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, startdate, enddate, firstid, lastid);
 
-    MamRsmUserdata* data = malloc(sizeof(MamRsmUserdata));
-    if (data) {
-        data->datestr = strdup(datestr);
-        data->barejid = strdup(win->barejid);
+    if (should_add_rsm_handler) {
+        MamRsmUserdata* data = malloc(sizeof(MamRsmUserdata));
+        if (data) {
+            data->start_datestr = startdate;
+            data->end_datestr = enddate;
+            data->barejid = strdup(win->barejid);
 
-        iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data);
+            iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data);
+        }
     }
 
-    g_free(datestr);
-    g_date_time_unref(timestamp);
+    message_free(last_msg);
 
     iq_send_stanza(iq);
     xmpp_stanza_release(iq);
@@ -2619,24 +2638,28 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
     } else if (g_strcmp0(type, "result") == 0) {
         xmpp_stanza_t* fin = xmpp_stanza_get_child_by_name_and_ns(stanza, STANZA_NAME_FIN, STANZA_NS_MAM2);
         if (fin) {
+            gboolean is_complete = g_strcmp0(xmpp_stanza_get_attribute(fin, "complete"), "true") == 0;
+
+            if (is_complete) {
+                return 0;
+            }
+
             xmpp_stanza_t* set = xmpp_stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM);
             if (set) {
                 char* lastid = NULL;
                 xmpp_stanza_t* last = xmpp_stanza_get_child_by_name(set, STANZA_NAME_LAST);
-                if (last) {
-                    lastid = xmpp_stanza_get_text(last);
-                }
+                lastid = xmpp_stanza_get_text(last);
 
                 // 4.3.2. send same stanza with set,max stanza
                 xmpp_ctx_t* const ctx = connection_get_ctx();
 
                 MamRsmUserdata* data = (MamRsmUserdata*)userdata;
-                xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->datestr, lastid);
-                free(data->barejid);
-                free(data->datestr);
-                free(data);
+
+                xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->start_datestr, data->end_datestr, NULL, lastid);
                 free(lastid);
 
+                iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data);
+
                 iq_send_stanza(iq);
                 xmpp_stanza_release(iq);
             }
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 8dcad982..86791d94 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -2701,7 +2701,7 @@ stanza_attach_correction(xmpp_ctx_t* ctx, xmpp_stanza_t* stanza, const char* con
 }
 
 xmpp_stanza_t*
-stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char* const lastid)
+stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char* const enddate, const char* const firstid, const char* const lastid)
 {
     char* id = connection_create_stanza_id();
     xmpp_stanza_t* iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id);
@@ -2747,26 +2747,48 @@ stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const s
     xmpp_stanza_add_child(field_with, value_with);
 
     // field 'start'
-    xmpp_stanza_t* field_start = xmpp_stanza_new(ctx);
-    xmpp_stanza_set_name(field_start, STANZA_NAME_FIELD);
-    xmpp_stanza_set_attribute(field_start, STANZA_ATTR_VAR, "start");
+    xmpp_stanza_t* field_start, *value_start, *start_date_text;
+    if (startdate) {
+        field_start = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_name(field_start, STANZA_NAME_FIELD);
+        xmpp_stanza_set_attribute(field_start, STANZA_ATTR_VAR, "start");
 
-    xmpp_stanza_t* value_start = xmpp_stanza_new(ctx);
-    xmpp_stanza_set_name(value_start, STANZA_NAME_VALUE);
+        value_start = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_name(value_start, STANZA_NAME_VALUE);
 
-    xmpp_stanza_t* date_text = xmpp_stanza_new(ctx);
-    xmpp_stanza_set_text(date_text, startdate);
-    xmpp_stanza_add_child(value_start, date_text);
+        start_date_text = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_text(start_date_text, startdate);
+        xmpp_stanza_add_child(value_start, start_date_text);
 
-    xmpp_stanza_add_child(field_start, value_start);
+        xmpp_stanza_add_child(field_start, value_start);
+    }
+
+    xmpp_stanza_t* field_end, *value_end, *end_date_text;
+    if (enddate) {
+        field_end = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_name(field_end, STANZA_NAME_FIELD);
+        xmpp_stanza_set_attribute(field_end, STANZA_ATTR_VAR, "end");
+
+        value_end = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_name(value_end, STANZA_NAME_VALUE);
+
+        end_date_text = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_text(end_date_text, enddate);
+        xmpp_stanza_add_child(value_end, end_date_text);
+
+        xmpp_stanza_add_child(field_end, value_end);
+    }
 
     // 4.3.2 set/rsm
-    xmpp_stanza_t *after, *after_text, *set;
-    if (lastid) {
+    xmpp_stanza_t *set;
+    if (lastid || firstid) {
         set = xmpp_stanza_new(ctx);
         xmpp_stanza_set_name(set, STANZA_TYPE_SET);
         xmpp_stanza_set_ns(set, STANZA_NS_RSM);
+    }
 
+    xmpp_stanza_t *after, *after_text;
+    if (lastid) {
         after = xmpp_stanza_new(ctx);
         xmpp_stanza_set_name(after, STANZA_NAME_AFTER);
 
@@ -2777,30 +2799,59 @@ stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const s
         xmpp_stanza_add_child(set, after);
     }
 
+    xmpp_stanza_t *before, *before_text;
+    if (firstid) {
+        before = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_name(before, STANZA_NAME_BEFORE);
+
+        before_text = xmpp_stanza_new(ctx);
+        xmpp_stanza_set_text(before_text, firstid);
+
+        xmpp_stanza_add_child(before, before_text);
+        xmpp_stanza_add_child(set, before);
+    }
+
     // add and release
     xmpp_stanza_add_child(iq, query);
     xmpp_stanza_add_child(query, x);
     xmpp_stanza_add_child(x, field_form_type);
     xmpp_stanza_add_child(x, field_with);
-    xmpp_stanza_add_child(x, field_start);
 
-    if (lastid) {
-        xmpp_stanza_add_child(query, after);
+    if (startdate) {
+        xmpp_stanza_add_child(x, field_start);
+        xmpp_stanza_release(field_start);
+        xmpp_stanza_release(value_start);
+        xmpp_stanza_release(start_date_text);
+    }
+
+    if (enddate) {
+        xmpp_stanza_add_child(x, field_end);
+        xmpp_stanza_release(field_end);
+        xmpp_stanza_release(value_end);
+        xmpp_stanza_release(end_date_text);
+    }
+
+    if (firstid || lastid) {
+        xmpp_stanza_add_child(query, set);
+        xmpp_stanza_release(set);
+    }
 
+    if (lastid) {
         xmpp_stanza_release(after_text);
         xmpp_stanza_release(after);
-        xmpp_stanza_release(set);
+    }
+
+    if (firstid) {
+        xmpp_stanza_release(before_text);
+        xmpp_stanza_release(before);
     }
 
     xmpp_stanza_release(mam_text);
     xmpp_stanza_release(with_text);
-    xmpp_stanza_release(date_text);
     xmpp_stanza_release(value_mam);
     xmpp_stanza_release(value_with);
-    xmpp_stanza_release(value_start);
     xmpp_stanza_release(field_form_type);
     xmpp_stanza_release(field_with);
-    xmpp_stanza_release(field_start);
     xmpp_stanza_release(x);
     xmpp_stanza_release(query);
 
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 12c9a5ee..71454e9d 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -115,7 +115,9 @@
 #define STANZA_NAME_MINIMIZE         "minimize"
 #define STANZA_NAME_FIN              "fin"
 #define STANZA_NAME_LAST             "last"
+#define STANZA_NAME_FIRST            "first"
 #define STANZA_NAME_AFTER            "after"
+#define STANZA_NAME_BEFORE           "before"
 #define STANZA_NAME_USERNAME         "username"
 #define STANZA_NAME_PROPOSE          "propose"
 #define STANZA_NAME_REPORT           "report"
@@ -413,7 +415,7 @@ void stanza_free_caps(XMPPCaps* caps);
 xmpp_stanza_t* stanza_create_avatar_retrieve_data_request(xmpp_ctx_t* ctx, const char* stanza_id, const char* const item_id, const char* const jid);
 xmpp_stanza_t* stanza_create_avatar_data_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len);
 xmpp_stanza_t* stanza_create_avatar_metadata_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len, int height, int width);
-xmpp_stanza_t* stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char* const lastid);
+xmpp_stanza_t* stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char* const enddate, const char* const firstid, const char* const lastid);
 xmpp_stanza_t* stanza_change_password(xmpp_ctx_t* ctx, const char* const user, const char* const password);
 xmpp_stanza_t* stanza_register_new_account(xmpp_ctx_t* ctx, const char* const user, const char* const password);
 xmpp_stanza_t* stanza_request_voice(xmpp_ctx_t* ctx, const char* const room);