diff options
-rw-r--r-- | src/config/preferences.c | 5 | ||||
-rw-r--r-- | src/config/preferences.h | 1 | ||||
-rw-r--r-- | src/server_events.c | 6 | ||||
-rw-r--r-- | src/server_events.h | 1 | ||||
-rw-r--r-- | src/ui/core.c | 13 | ||||
-rw-r--r-- | src/ui/ui.h | 1 | ||||
-rw-r--r-- | src/xmpp/message.c | 103 | ||||
-rw-r--r-- | src/xmpp/stanza.c | 55 | ||||
-rw-r--r-- | src/xmpp/stanza.h | 8 | ||||
-rw-r--r-- | tests/ui/stub_ui.c | 2 |
10 files changed, 158 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); diff --git a/tests/ui/stub_ui.c b/tests/ui/stub_ui.c index 1a0f650d..55c67335 100644 --- a/tests/ui/stub_ui.c +++ b/tests/ui/stub_ui.c @@ -194,6 +194,8 @@ void ui_handle_stanza(const char * const msg) {} // ui events 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_message_receipt(const char * const barejid, const char * const id) {} + void ui_incoming_private_msg(const char * const fulljid, const char * const message, GTimeVal *tv_stamp) {} void ui_disconnected(void) {} |