about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/database.c13
-rw-r--r--src/database.h4
-rw-r--r--src/ui/chatwin.c15
-rw-r--r--src/ui/ui.h2
-rw-r--r--src/ui/window.c13
-rw-r--r--src/xmpp/iq.c47
-rw-r--r--src/xmpp/stanza.c30
-rw-r--r--src/xmpp/stanza.h1
8 files changed, 69 insertions, 56 deletions
diff --git a/src/database.c b/src/database.c
index 82cd380f..ea971d4e 100644
--- a/src/database.c
+++ b/src/database.c
@@ -46,6 +46,7 @@
 #include "log.h"
 #include "common.h"
 #include "config/files.h"
+#include "database.h"
 
 static sqlite3* g_chatlog_database;
 
@@ -234,7 +235,7 @@ log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_las
 
 // Query previous chat
 GSList*
-log_database_get_previous_chat(const gchar* const contact_barejid, GDateTime* end_time, gboolean flip)
+log_database_get_previous_chat(const gchar* const contact_barejid, char* start_time, char* end_time, gboolean flip)
 {
     sqlite3_stmt* stmt = NULL;
     gchar* query;
@@ -244,15 +245,17 @@ log_database_get_previous_chat(const gchar* const contact_barejid, GDateTime* en
         return NULL;
 
     // Flip order when querying older pages
-    char* sort = !flip ? "ASC" : "DESC";
-    gchar* date_fmt = g_date_time_format_iso8601(end_time ? end_time : g_date_time_new_now_local());
-    query = sqlite3_mprintf("SELECT * FROM (SELECT `message`, `timestamp`, `from_jid`, `type` from `ChatLogs` WHERE ((`from_jid` = '%q' AND `to_jid` = '%q') OR (`from_jid` = '%q' AND `to_jid` = '%q')) AND `timestamp` < '%q' ORDER BY `timestamp` DESC LIMIT 10) ORDER BY `timestamp` %s;", contact_barejid, myjid->barejid, myjid->barejid, contact_barejid, date_fmt, sort);
+    gchar* sort = !flip ? "ASC" : "DESC";
+    gchar* end_date_fmt = end_time ? end_time : g_date_time_format_iso8601(g_date_time_new_now_local());
+    gchar* start_date_fmt = start_time ? start_time : NULL;
+    query = sqlite3_mprintf("SELECT * FROM (SELECT `message`, `timestamp`, `from_jid`, `type` from `ChatLogs` WHERE ((`from_jid` = '%q' AND `to_jid` = '%q') OR (`from_jid` = '%q' AND `to_jid` = '%q')) AND `timestamp` < '%q' AND (%Q IS NULL OR `timestamp` > %Q) ORDER BY `timestamp` DESC LIMIT %d) ORDER BY `timestamp` %s;", contact_barejid, myjid->barejid, myjid->barejid, contact_barejid, end_date_fmt, start_date_fmt, start_date_fmt, MESSAGES_TO_RETRIEVE, sort);
     if (!query) {
         log_error("log_database_get_previous_chat(): SQL query. could not allocate memory");
         return NULL;
     }
 
-    g_free(date_fmt);
+    g_free(end_date_fmt);
+
     jid_destroy(myjid);
 
     int rc = sqlite3_prepare_v2(g_chatlog_database, query, -1, &stmt, NULL);
diff --git a/src/database.h b/src/database.h
index 08a6bab0..d575d62e 100644
--- a/src/database.h
+++ b/src/database.h
@@ -40,12 +40,14 @@
 #include "config/account.h"
 #include "xmpp/xmpp.h"
 
+#define MESSAGES_TO_RETRIEVE 10
+
 gboolean log_database_init(ProfAccount* account);
 void log_database_add_incoming(ProfMessage* message);
 void log_database_add_outgoing_chat(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(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, GDateTime* end_time, gboolean flip);
+GSList* log_database_get_previous_chat(const gchar* const contact_barejid, char* start_time, char* end_time, gboolean flip);
 ProfMessage* log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_last);
 void log_database_close(void);
 
diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c
index 02068837..82df1e80 100644
--- a/src/ui/chatwin.c
+++ b/src/ui/chatwin.c
@@ -66,8 +66,11 @@ chatwin_new(const char* const barejid)
     ProfWin* window = wins_new_chat(barejid);
     ProfChatWin* chatwin = (ProfChatWin*)window;
 
-    if (prefs_get_boolean(PREF_MAM) || (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY))) {
+    if (!prefs_get_boolean(PREF_MAM) || (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY))) {
+        if (0) {
+            
         _chatwin_history(chatwin, barejid);
+        }
     }
 
     // if the contact is offline, show a message
@@ -307,7 +310,7 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
         // MUCPMs also get printed here. In their case we don't save any logs (because nick owners can change) and thus we shouldn't read logs
         // (and if we do we need to check the resourcepart)
         if (!prefs_get_boolean(PREF_MAM) && prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY) && message->type == PROF_MSG_TYPE_CHAT) {
-            _chatwin_history(chatwin, chatwin->barejid);
+            /* _chatwin_history(chatwin, chatwin->barejid); */
         }
 
         // show users status first, when receiving message via delayed delivery
@@ -518,7 +521,7 @@ static void
 _chatwin_history(ProfChatWin* chatwin, const char* const contact_barejid)
 {
     if (!chatwin->history_shown) {
-        GSList* history = log_database_get_previous_chat(contact_barejid, NULL, FALSE);
+        GSList* history = log_database_get_previous_chat(contact_barejid, NULL, NULL, FALSE);
         GSList* curr = history;
 
         while (curr) {
@@ -538,11 +541,11 @@ _chatwin_history(ProfChatWin* chatwin, const char* const contact_barejid)
 }
 
 gboolean
-chatwin_old_history(ProfChatWin* chatwin)
+chatwin_old_history(ProfChatWin* chatwin, char* start_time)
 {
     // TODO: not correct location but check whether notifications get screwed
-    GDateTime* time = buffer_size(((ProfWin*)chatwin)->layout->buffer) == 0 ? NULL : buffer_get_entry(((ProfWin*)chatwin)->layout->buffer, 0)->time;
-    GSList* history = log_database_get_previous_chat(chatwin->barejid, time, TRUE);
+    char* end_time = buffer_size(((ProfWin*)chatwin)->layout->buffer) == 0 ? NULL : g_date_time_format_iso8601(buffer_get_entry(((ProfWin*)chatwin)->layout->buffer, 0)->time);
+    GSList* history = log_database_get_previous_chat(chatwin->barejid, start_time, end_time, TRUE);
     gboolean has_items = g_slist_length(history) != 0;
     GSList* curr = history;
 
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 264ce38b..1b87783a 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -145,7 +145,7 @@ void chatwin_set_incoming_char(ProfChatWin* chatwin, const char* const ch);
 void chatwin_unset_incoming_char(ProfChatWin* chatwin);
 void chatwin_set_outgoing_char(ProfChatWin* chatwin, const char* const ch);
 void chatwin_unset_outgoing_char(ProfChatWin* chatwin);
-gboolean chatwin_old_history(ProfChatWin* chatwin);
+gboolean chatwin_old_history(ProfChatWin* chatwin, char* start_date);
 
 // MUC window
 ProfMucWin* mucwin_new(const char* const barejid);
diff --git a/src/ui/window.c b/src/ui/window.c
index 1dedb1d8..391aec21 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -61,6 +61,7 @@
 #include "xmpp/xmpp.h"
 #include "xmpp/roster_list.h"
 #include "xmpp/connection.h"
+#include "database.h"
 
 #define CONS_WIN_TITLE "Profanity. Type /help for help information."
 #define XML_WIN_TITLE  "XML Console"
@@ -607,7 +608,7 @@ win_page_up(ProfWin* window)
 
         // Don't do anything if still fetching mam messages
         if (first_entry && !(first_entry->theme_item == THEME_ROOMINFO && g_strcmp0(first_entry->message, loading_text) == 0)) {
-            if (!chatwin_old_history(chatwin)) {
+            if (!chatwin_old_history(chatwin, NULL)) {
                 cons_show("Fetched mam");
                 buffer_prepend(window->layout->buffer, "-", 0, first_entry->time, NO_DATE, THEME_ROOMINFO, NULL, NULL, loading_text, NULL, NULL);
                 win_redraw(window);
@@ -1211,8 +1212,8 @@ win_print_incoming(ProfWin* window, const char* const display_name_from, ProfMes
         if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && message->replace_id) {
             _win_correct(window, message->plain, message->id, message->replace_id, message->from_jid->barejid);
         } else {
-            // Prevent duplicate messages when current client is sending a message
-            if (g_strcmp0(message->from_jid->fulljid, connection_get_fulljid()) != 0) {
+            // Prevent duplicate messages when current client is sending a message or if it's mam
+            if (g_strcmp0(message->from_jid->fulljid, connection_get_fulljid()) != 0 && !message->is_mam) {
                 _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_from, message->from_jid->barejid, message->id, "%s", message->plain);
             }
         }
@@ -1550,10 +1551,8 @@ _win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* t
     GString* fmt_msg = g_string_new(NULL);
     g_string_vprintf(fmt_msg, message, arg);
 
-    if (buffer_size(window->layout->buffer) == 0 || g_date_time_compare(buffer_get_entry(window->layout->buffer, 0)->time, timestamp) != 1) {
-        buffer_append(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, display_from, from_jid, fmt_msg->str, NULL, message_id);
-        _win_print_internal(window, show_char, pad_indent, timestamp, flags, theme_item, display_from, fmt_msg->str, NULL);
-    }
+    buffer_append(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, display_from, from_jid, fmt_msg->str, NULL, message_id);
+    _win_print_internal(window, show_char, pad_indent, timestamp, flags, theme_item, display_from, fmt_msg->str, NULL);
 
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index d2ae7de2..098d19db 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -108,6 +108,7 @@ typedef struct mam_rsm_userdata
     char* barejid;
     char* start_datestr;
     char* end_datestr;
+    ProfChatWin* win;
 } MamRsmUserdata;
 
 static int _iq_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const userdata);
@@ -2582,7 +2583,7 @@ _mam_buffer_commit_handler(xmpp_stanza_t* const stanza, void* const userdata)
     cons_show("Comitted history");
     // Remove the "Loading messages ..." message
     buffer_remove_entry(((ProfWin*)chatwin)->layout->buffer, 0);
-    chatwin_old_history(chatwin);
+    chatwin_old_history(chatwin, NULL);
     return 0;
 }
 
@@ -2630,39 +2631,32 @@ iq_mam_request(ProfChatWin* win)
     }
 
     ProfMessage* last_msg = log_database_get_limits_info(win->barejid, TRUE);
-    char* lastid = NULL;
-    char* firstid = NULL;
+    // To get last page and have flipped paging set firstid to empty string
+    char* firstid = "";
     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();
 
-    xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, startdate, enddate, firstid, lastid);
+    xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, startdate, enddate, firstid, NULL);
 
-    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);
+    MamRsmUserdata* data = malloc(sizeof(MamRsmUserdata));
+    if (data) {
+        data->start_datestr = startdate;
+        data->end_datestr = enddate;
+        data->barejid = strdup(win->barejid);
+        data->win = win;
 
-            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);
     }
 
     message_free(last_msg);
@@ -2686,24 +2680,25 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
         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;
+            MamRsmUserdata* data = (MamRsmUserdata*)userdata;
 
-            if (is_complete) {
+            if (is_complete || data->end_datestr) {
+                chatwin_old_history(data->win, is_complete ? NULL : data->start_datestr);
                 return 0;
             }
+            chatwin_old_history(data->win, data->start_datestr);
 
             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);
-                lastid = xmpp_stanza_get_text(last);
+                char* firstid = NULL;
+                xmpp_stanza_t* first = xmpp_stanza_get_child_by_name(set, STANZA_NAME_FIRST);
+                firstid = xmpp_stanza_get_text(first);
 
                 // 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->start_datestr, data->end_datestr, NULL, lastid);
-                free(lastid);
+                xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->start_datestr, data->end_datestr, firstid, NULL);
+                free(firstid);
 
                 iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data);
 
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 86791d94..4d56ebf4 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -58,6 +58,7 @@
 #include "xmpp/connection.h"
 #include "xmpp/form.h"
 #include "xmpp/muc.h"
+#include "database.h"
 
 static void _stanza_add_unique_id(xmpp_stanza_t* stanza);
 static char* _stanza_create_sha1_hash(char* str);
@@ -2780,12 +2781,21 @@ stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const s
     }
 
     // 4.3.2 set/rsm
-    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 *set, *max, *max_text;
+    set = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(set, STANZA_TYPE_SET);
+    xmpp_stanza_set_ns(set, STANZA_NS_RSM);
+
+    max = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(max, STANZA_NAME_MAX);
+
+    max_text = xmpp_stanza_new(ctx);
+    char* txt = g_strdup_printf("%d", MESSAGES_TO_RETRIEVE);
+    xmpp_stanza_set_text(max_text, txt);
+    g_free(txt);
+
+    xmpp_stanza_add_child(max, max_text);
+    xmpp_stanza_add_child(set, max);
 
     xmpp_stanza_t *after, *after_text;
     if (lastid) {
@@ -2831,10 +2841,10 @@ stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const s
         xmpp_stanza_release(end_date_text);
     }
 
-    if (firstid || lastid) {
-        xmpp_stanza_add_child(query, set);
-        xmpp_stanza_release(set);
-    }
+    xmpp_stanza_add_child(query, set);
+    xmpp_stanza_release(set);
+    xmpp_stanza_release(max_text);
+    xmpp_stanza_release(max);
 
     if (lastid) {
         xmpp_stanza_release(after_text);
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 71454e9d..4d41ef87 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -118,6 +118,7 @@
 #define STANZA_NAME_FIRST            "first"
 #define STANZA_NAME_AFTER            "after"
 #define STANZA_NAME_BEFORE           "before"
+#define STANZA_NAME_MAX              "max"
 #define STANZA_NAME_USERNAME         "username"
 #define STANZA_NAME_PROPOSE          "propose"
 #define STANZA_NAME_REPORT           "report"