# HG changeset patch # User franky # Date 1222249289 -7200 # Node ID f4a2c6f767d1dfbef104f3a4b13b7ad1401a8e70 # Parent 3efc92a48945d2b3be53bad48b0825cd0e00c210 Message Receipts support (XEP-0184) diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/commands.c --- a/mcabber/src/commands.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/commands.c Wed Sep 24 11:41:29 2008 +0200 @@ -1114,6 +1114,7 @@ gint crypted; gint retval = 0; int isroom; + gpointer xep184 = NULL; if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); @@ -1162,7 +1163,7 @@ // Network part xmpp_send_msg(fjid, msg, (isroom ? ROSTER_TYPE_ROOM : ROSTER_TYPE_USER), - subj, FALSE, &crypted, type_overwrite); + subj, FALSE, &crypted, type_overwrite, &xep184); if (crypted == -1) { scr_LogPrint(LPRINT_LOGNORM, "Encryption error. Message was not sent."); @@ -1172,7 +1173,7 @@ // Hook if (!isroom) - hk_message_out(bare_jid, rp, 0, hmsg, crypted); + hk_message_out(bare_jid, rp, 0, hmsg, crypted, xep184); send_message_to_return: if (hmsg != msg) g_free(hmsg); @@ -2630,7 +2631,7 @@ arg = to_utf8(arg); // Set the topic xmpp_send_msg(buddy_getjid(bud), NULL, ROSTER_TYPE_ROOM, arg ? arg : "", - FALSE, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET); + FALSE, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, NULL); g_free(arg); } diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/hbuf.c --- a/mcabber/src/hbuf.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/hbuf.c Wed Sep 24 11:41:29 2008 +0200 @@ -44,6 +44,7 @@ time_t timestamp; unsigned mucnicklen; guint flags; + gpointer xep184; } prefix; } hbuf_block; @@ -123,7 +124,7 @@ // Note 2: width does not include the ending \0. void hbuf_add_line(GList **p_hbuf, const char *text, time_t timestamp, guint prefix_flags, guint width, guint maxhbufblocks, - unsigned mucnicklen) + unsigned mucnicklen, gpointer xep184) { GList *curr_elt; char *line; @@ -132,6 +133,8 @@ if (!text) return; + prefix_flags |= (xep184 ? HBB_PREFIX_RECEIPT : 0); + textlen = strlen(text); hbb_blocksize = MAX(textlen+1, HBB_BLOCKSIZE); @@ -139,6 +142,7 @@ hbuf_block_elt->prefix.timestamp = timestamp; hbuf_block_elt->prefix.flags = prefix_flags; hbuf_block_elt->prefix.mucnicklen = mucnicklen; + hbuf_block_elt->prefix.xep184 = xep184; if (!*p_hbuf) { hbuf_block_elt->ptr = g_new(char, hbb_blocksize); if (!hbuf_block_elt->ptr) { @@ -474,6 +478,26 @@ return; } +// hbuf_remove_receipt(hbuf, xep184) +// Remove the Receipt Flag for the message with the given xep184 id +// Returns TRUE if it was found and removed, otherwise FALSE +gboolean hbuf_remove_receipt(GList *hbuf, gpointer xep184) +{ + hbuf_block *blk; + + hbuf = g_list_first(hbuf); + + for ( ; hbuf; hbuf = g_list_next(hbuf)) { + blk = (hbuf_block*)(hbuf->data); + if (blk->prefix.xep184 == xep184) { + blk->prefix.xep184 = NULL; + blk->prefix.flags ^= HBB_PREFIX_RECEIPT; + return TRUE; + } + } + return FALSE; +} + // hbuf_get_blocks_number() // Returns the number of allocated hbuf_block's. guint hbuf_get_blocks_number(GList *hbuf) diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/hbuf.h --- a/mcabber/src/hbuf.h Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/hbuf.h Wed Sep 24 11:41:29 2008 +0200 @@ -28,6 +28,7 @@ #define HBB_PREFIX_PGPCRYPT (1U<<11) #define HBB_PREFIX_OTRCRYPT (1U<<12) #define HBB_PREFIX_CONT (1U<<13) +#define HBB_PREFIX_RECEIPT (1U<<14) typedef struct { time_t timestamp; @@ -38,7 +39,7 @@ void hbuf_add_line(GList **p_hbuf, const char *text, time_t timestamp, guint prefix_flags, guint width, guint maxhbufblocks, - unsigned mucnicklen); + unsigned mucnicklen, gpointer xep184); void hbuf_free(GList **p_hbuf); void hbuf_rebuild(GList **p_hbuf, unsigned int width); GList *hbuf_previous_persistent(GList *l_line); @@ -47,6 +48,7 @@ GList *hbuf_search(GList *hbuf, int direction, const char *string); GList *hbuf_jump_date(GList *hbuf, time_t t); GList *hbuf_jump_percent(GList *hbuf, int pc); +gboolean hbuf_remove_receipt(GList *hbuf, gpointer xep184); void hbuf_dump_to_file(GList *hbuf, const char *filename); diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/histolog.c --- a/mcabber/src/histolog.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/histolog.c Wed Sep 24 11:41:29 2008 +0200 @@ -335,7 +335,7 @@ if (converted) { xtext = ut_expand_tabs(converted); // Expand tabs hbuf_add_line(p_buddyhbuf, xtext, timestamp, prefix_flags, width, - max_num_of_blocks, 0); + max_num_of_blocks, 0, NULL); if (xtext != converted) g_free(xtext); g_free(converted); diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/hooks.c --- a/mcabber/src/hooks.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/hooks.c Wed Sep 24 11:41:29 2008 +0200 @@ -251,7 +251,8 @@ // nick should be set for private messages in a chat room, and null for // normal messages. void hk_message_out(const char *bjid, const char *nick, - time_t timestamp, const char *msg, guint encrypted) + time_t timestamp, const char *msg, + guint encrypted, gpointer xep184) { char *wmsg = NULL, *bmsg = NULL, *mmsg = NULL; guint cryptflag = 0; @@ -280,7 +281,7 @@ cryptflag = HBB_PREFIX_PGPCRYPT; else if (encrypted == ENCRYPTED_OTR) cryptflag = HBB_PREFIX_OTRCRYPT; - scr_WriteOutgoingMessage(bjid, wmsg, cryptflag); + scr_WriteOutgoingMessage(bjid, wmsg, cryptflag, xep184); // We don't log private messages if (!nick) diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/hooks.h --- a/mcabber/src/hooks.h Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/hooks.h Wed Sep 24 11:41:29 2008 +0200 @@ -14,7 +14,8 @@ time_t timestamp, const char *msg, LmMessageSubType type, guint encrypted); void hk_message_out(const char *bjid, const char *nickname, - time_t timestamp, const char *msg, guint encrypted); + time_t timestamp, const char *msg, + guint encrypted, gpointer xep184); void hk_statuschange(const char *bjid, const char *resname, gchar prio, time_t timestamp, enum imstatus status, char const *status_msg); diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/otr.c --- a/mcabber/src/otr.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/otr.c Wed Sep 24 11:41:29 2008 +0200 @@ -645,7 +645,7 @@ { if (roster_gettype(recipient) == ROSTER_TYPE_USER) xmpp_send_msg(recipient, message, ROSTER_TYPE_USER, "", TRUE, NULL, - LM_MESSAGE_SUB_TYPE_NOT_SET); + LM_MESSAGE_SUB_TYPE_NOT_SET, NULL); } /* Display a notification message for a particular diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/screen.c --- a/mcabber/src/screen.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/screen.c Wed Sep 24 11:41:29 2008 +0200 @@ -159,7 +159,7 @@ void scr_WriteInWindow(const char *winId, const char *text, time_t timestamp, unsigned int prefix_flags, int force_show, - unsigned mucnicklen); + unsigned mucnicklen, gpointer xep184); void scr_WriteMessage(const char *bjid, const char *text, time_t timestamp, guint prefix_flags, @@ -909,12 +909,12 @@ wprintw(logWnd, "\n%s", buffer_locale); update_panels(); scr_WriteInWindow(NULL, buf_specialwindow, timestamp, - HBB_PREFIX_SPECIAL, FALSE, 0); + HBB_PREFIX_SPECIAL, FALSE, 0, NULL); } else { printf("%s\n", buffer_locale); // ncurses are not initialized yet, so we call directly hbuf routine hbuf_add_line(&statushbuf, buf_specialwindow, timestamp, - HBB_PREFIX_SPECIAL, 0, 0, 0); + HBB_PREFIX_SPECIAL, 0, 0, 0, NULL); } g_free(convbuf1); @@ -1038,14 +1038,18 @@ cryptflag = '='; g_snprintf(pref, preflen, "%s<%c= ", date, cryptflag); } else if (line->flags & HBB_PREFIX_OUT) { - char cryptflag; + char cryptflag, receiptflag; if (line->flags & HBB_PREFIX_PGPCRYPT) cryptflag = '~'; else if (line->flags & HBB_PREFIX_OTRCRYPT) cryptflag = 'O'; else cryptflag = '-'; - g_snprintf(pref, preflen, "%s-%c> ", date, cryptflag); + if (line->flags & HBB_PREFIX_RECEIPT) + receiptflag = 'r'; + else + receiptflag = '-'; + g_snprintf(pref, preflen, "%s%c%c> ", date, receiptflag, cryptflag); } else if (line->flags & HBB_PREFIX_SPECIAL) { strftime(date, 30, getspectprefix(), localtime(&line->timestamp)); g_snprintf(pref, preflen, "%s ", date); @@ -1295,7 +1299,7 @@ // If this window doesn't exist, it is created. void scr_WriteInWindow(const char *winId, const char *text, time_t timestamp, unsigned int prefix_flags, int force_show, - unsigned mucnicklen) + unsigned mucnicklen, gpointer xep184) { winbuf *win_entry; char *text_locale; @@ -1342,7 +1346,7 @@ } hbuf_add_line(&win_entry->bd->hbuf, text_locale, timestamp, prefix_flags, maxX - Roster_Width - scr_getprefixwidth(), num_history_blocks, - mucnicklen); + mucnicklen, xep184); g_free(text_locale); if (win_entry->bd->cleared) { @@ -2053,7 +2057,7 @@ void scr_WriteMessage(const char *bjid, const char *text, time_t timestamp, guint prefix_flags, - unsigned mucnicklen) + unsigned mucnicklen, gpointer xep184) { char *xtext; @@ -2061,7 +2065,8 @@ xtext = ut_expand_tabs(text); // Expand tabs and filter out some chars - scr_WriteInWindow(bjid, xtext, timestamp, prefix_flags, FALSE, mucnicklen); + scr_WriteInWindow(bjid, xtext, timestamp, prefix_flags, FALSE, mucnicklen, + xep184); if (xtext != (char*)text) g_free(xtext); @@ -2080,23 +2085,34 @@ if (url_regex) scr_LogUrls(text); #endif - scr_WriteMessage(jidfrom, text, timestamp, prefix, mucnicklen); + scr_WriteMessage(jidfrom, text, timestamp, prefix, mucnicklen, NULL); } -void scr_WriteOutgoingMessage(const char *jidto, const char *text, guint prefix) +void scr_WriteOutgoingMessage(const char *jidto, const char *text, guint prefix, + gpointer xep184) { GSList *roster_elt; roster_elt = roster_find(jidto, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM); scr_WriteMessage(jidto, text, - 0, prefix|HBB_PREFIX_OUT|HBB_PREFIX_HLIGHT_OUT, 0); + 0, prefix|HBB_PREFIX_OUT|HBB_PREFIX_HLIGHT_OUT, 0, xep184); // Show jidto's buffer unless the buddy is not in the buddylist if (roster_elt && g_list_position(buddylist, roster_elt->data) != -1) scr_ShowWindow(jidto, FALSE); } +void scr_RemoveReceiptFlag(const char *bjid, gpointer xep184) +{ + winbuf *win_entry = scr_SearchWindow(bjid, FALSE); + if (win_entry) { + hbuf_remove_receipt(win_entry->bd->hbuf, xep184); + if (chatmode && (buddy_search_jid(bjid) == current_buddy)) + scr_UpdateBuddyWindow(); + } +} + static inline void set_autoaway(bool setaway) { static enum imstatus oldstatus; diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/screen.h --- a/mcabber/src/screen.h Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/screen.h Wed Sep 24 11:41:29 2008 +0200 @@ -100,7 +100,8 @@ time_t timestamp, guint prefix, unsigned mucnicklen); void scr_WriteOutgoingMessage(const char *jidto, const char *text, - guint prefix); + guint prefix, gpointer xep184); +void scr_RemoveReceiptFlag(const char *jidto, gpointer xep184); void scr_ShowBuddyWindow(void); int scr_BuddyBufferExists(const char *jid); void scr_UpdateBuddyWindow(void); diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/xmpp.c --- a/mcabber/src/xmpp.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/xmpp.c Wed Sep 24 11:41:29 2008 +0200 @@ -314,6 +314,15 @@ g_slist_free(resources); } +static LmHandlerResult cb_xep184(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data) +{ + char *from = jidtodisp(lm_message_get_from(m)); + scr_RemoveReceiptFlag(from, h); + g_free(from); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + // xmpp_send_msg(jid, text, type, subject, // otrinject, *encrypted, type_overwrite) // When encrypted is not NULL, the function set *encrypted to 1 if the @@ -321,7 +330,7 @@ // encryption fails, *encrypted is set to -1. void xmpp_send_msg(const char *fjid, const char *text, int type, const char *subject, gboolean otrinject, gint *encrypted, - LmMessageSubType type_overwrite) + LmMessageSubType type_overwrite, gpointer *xep184) { LmMessage *x; LmMessageSubType subtype; @@ -433,6 +442,16 @@ g_free(enc); } + //XEP-0184: Message Receipts + if (sl_buddy && rname && xep184 && + caps_has_feature(buddy_resource_getcaps(sl_buddy->data, rname), + NS_RECEIPTS)) { + lm_message_node_set_attribute + (lm_message_node_add_child(x->node, "request", NULL), + "xmlns", NS_RECEIPTS); + *xep184 = lm_message_handler_new(cb_xep184, NULL, NULL); + } + #if defined JEP0022 || defined JEP0085 // If typing notifications are disabled, we can skip all this stuff... if (chatstates_disabled || type == ROSTER_TYPE_ROOM) @@ -492,7 +511,11 @@ xmpp_send_msg_no_chatstates: if (mystatus != invisible) update_last_use(); - lm_connection_send(lconnection, x, NULL); + if (xep184 && *xep184) { + lm_connection_send_with_reply(lconnection, x, *xep184, NULL); + lm_message_handler_unref(*xep184); + } else + lm_connection_send(lconnection, x, NULL); lm_message_unref(x); } @@ -1243,6 +1266,16 @@ if (from && (body || subject)) gotmessage(lm_message_get_sub_type(m), from, body, enc, subject, timestamp, lm_message_node_find_xmlns(m->node, NS_SIGNED)); + //report received message if message receipt was requested + if (lm_message_node_get_child(m->node, "request")) { + LmMessage *rcvd = lm_message_new(from, LM_MESSAGE_TYPE_MESSAGE); + lm_message_node_set_attribute(rcvd->node, "id", lm_message_get_id(m)); + lm_message_node_set_attribute + (lm_message_node_add_child(rcvd->node, "received", NULL), + "xmlns", NS_RECEIPTS); + lm_connection_send(connection, rcvd, NULL); + lm_message_unref(rcvd); + } if (from) { x = lm_message_node_find_xmlns(m->node, diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/xmpp.h --- a/mcabber/src/xmpp.h Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/xmpp.h Wed Sep 24 11:41:29 2008 +0200 @@ -49,7 +49,7 @@ void xmpp_send_msg(const char *fjid, const char *text, int type, const char *subject, gboolean otrinject, gint *encrypted, - LmMessageSubType type_overwrite); + LmMessageSubType type_overwrite, gpointer *xep184); void xmpp_send_s10n(const char *bjid, LmMessageSubType type); diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/xmpp_defines.h --- a/mcabber/src/xmpp_defines.h Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/xmpp_defines.h Wed Sep 24 11:41:29 2008 +0200 @@ -54,6 +54,7 @@ #define NS_XMPP_DELAY "urn:xmpp:delay" #define NS_XMPP_TIME "urn:xmpp:time" #define NS_PING "urn:xmpp:ping" +#define NS_RECEIPTS "urn:xmpp:receipts" #define NS_JABBERD_STOREDPRESENCE "http://jabberd.org/ns/storedpresence" #define NS_JABBERD_HISTORY "http://jabberd.org/ns/history" diff -r 3efc92a48945 -r f4a2c6f767d1 mcabber/src/xmpp_helper.c --- a/mcabber/src/xmpp_helper.c Sun Oct 11 15:59:20 2009 +0200 +++ b/mcabber/src/xmpp_helper.c Wed Sep 24 11:41:29 2008 +0200 @@ -151,6 +151,7 @@ caps_add_feature("", NS_VERSION); caps_add_feature("", NS_PING); caps_add_feature("", NS_COMMANDS); + caps_add_feature("", NS_RECEIPTS); if (!settings_opt_get_int("iq_last_disable") && (!settings_opt_get_int("iq_last_disable_when_notavail") || status != notavail))