From e3feacddd6667fd8e111d0ee54846c6aeabe3a7d Mon Sep 17 00:00:00 2001 From: Olivier LE MOAL Date: Mon, 2 Feb 2015 11:10:05 +0100 Subject: [PATCH 1/7] Add XEP-0280 support --- src/server_events.c | 5 +++++ src/server_events.h | 1 + src/xmpp/connection.c | 1 + src/xmpp/iq.c | 10 ++++++++++ src/xmpp/message.c | 38 ++++++++++++++++++++++++++++++++++++++ src/xmpp/stanza.c | 18 ++++++++++++++++++ src/xmpp/stanza.h | 5 +++++ src/xmpp/xmpp.h | 1 + 8 files changed, 79 insertions(+) diff --git a/src/server_events.c b/src/server_events.c index fbf534ac..bf880a9d 100644 --- a/src/server_events.c +++ b/src/server_events.c @@ -296,6 +296,11 @@ handle_incoming_private_message(char *fulljid, char *message) ui_incoming_private_msg(fulljid, message, NULL); } +void +handle_carbon(char *barejid, char *message){ + ui_outgoing_chat_msg("me", barejid, message); +} + void handle_incoming_message(char *barejid, char *resource, char *message) { diff --git a/src/server_events.h b/src/server_events.h index 6a12dc6e..3ec6a332 100644 --- a/src/server_events.h +++ b/src/server_events.h @@ -101,6 +101,7 @@ void handle_group_remove(const char * const contact, void handle_roster_remove(const char * const barejid); void handle_roster_add(const char * const barejid, const char * const name); void handle_autoping_cancel(void); +void handle_carbon(char *barejid, char *message); void handle_message_error(const char * const from, const char * const type, const char * const err_msg); void handle_presence_error(const char *from, const char * const type, diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 915525e4..8bb7c74c 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -463,6 +463,7 @@ _connection_handler(xmpp_conn_t * const conn, message_add_handlers(); presence_add_handlers(); iq_add_handlers(); + iq_enable_carbons(); roster_request(); bookmark_request(); diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 7fedf0ed..071b07c5 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -152,6 +152,16 @@ iq_room_list_request(gchar *conferencejid) xmpp_stanza_release(iq); } +void +iq_enable_carbons() +{ + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_enable_carbons(ctx); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); +} + void iq_disco_info_request(gchar *jid) { diff --git a/src/xmpp/message.c b/src/xmpp/message.c index e96c1a74..4f341f6a 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -423,6 +423,44 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, return 1; } + // 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 *message = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE); + + xmpp_ctx_t *ctx = connection_get_ctx(); + + gchar *to = xmpp_stanza_get_attribute(message, STANZA_ATTR_TO); + gchar *from = xmpp_stanza_get_attribute(message, STANZA_ATTR_FROM); + + Jid *jid_from = jid_create(from); + Jid *jid_to = jid_create(to); + Jid *my_jid = jid_create(jabber_get_fulljid()); + + // check for and deal with message + xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(message, STANZA_NAME_BODY); + if (body != NULL) { + char *message = xmpp_stanza_get_text(body); + if (message != NULL) { + // if we are the recipient, treat as standard incoming message + if(g_strcmp0(my_jid->barejid, jid_to->barejid) == 0){ + handle_incoming_message(jid_from->barejid, jid_from->resourcepart, message); + } + // else treat as a sent message + else{ + handle_carbon(jid_to->barejid, message); + } + xmpp_free(ctx, message); + } + } + + jid_destroy(jid_from); + jid_destroy(jid_to); + jid_destroy(my_jid); + return 1; + } + // ignore handled namespaces xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE); xmpp_stanza_t *mucuser = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 4f1d412d..06177800 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -198,6 +198,24 @@ stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char * const jid, } #endif +xmpp_stanza_t * +stanza_enable_carbons(xmpp_ctx_t *ctx){ + xmpp_stanza_t *iq = xmpp_stanza_new(ctx); + char *id = create_unique_id(NULL); + + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_SET); + xmpp_stanza_set_id(iq, id); + + xmpp_stanza_t *carbon_enable = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(carbon_enable, STANZA_NAME_ENABLE); + xmpp_stanza_set_ns(carbon_enable, STANZA_NS_CARBONS); + + xmpp_stanza_add_child(iq, carbon_enable); + + return iq; +} + xmpp_stanza_t * stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 84282401..0c5a2b01 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -77,6 +77,7 @@ #define STANZA_NAME_VALUE "value" #define STANZA_NAME_DESTROY "destroy" #define STANZA_NAME_ACTOR "actor" +#define STANZA_NAME_ENABLE "enable" // error conditions #define STANZA_NAME_BAD_REQUEST "bad-request" @@ -154,6 +155,8 @@ #define STANZA_NS_CONFERENCE "jabber:x:conference" #define STANZA_NS_CAPTCHA "urn:xmpp:captcha" #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_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" @@ -178,6 +181,8 @@ typedef enum { xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx); +xmpp_stanza_t * stanza_enable_carbons(xmpp_ctx_t *ctx); + xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index a004a4bf..41355e30 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -172,6 +172,7 @@ void presence_update(resource_presence_t status, const char * const msg, gboolean presence_sub_request_exists(const char * const bare_jid); // iq functions +void iq_enable_carbons(); void iq_send_software_version(const char * const fulljid); void iq_room_list_request(gchar *conferencejid); void iq_disco_info_request(gchar *jid); From 2a12a4d93bcb898225003a8d38e7f28662075b70 Mon Sep 17 00:00:00 2001 From: Olivier LE MOAL Date: Tue, 3 Feb 2015 15:27:56 +0100 Subject: [PATCH 2/7] Add preference/commands for carbons message --- src/command/command.c | 10 ++++++++++ src/command/commands.c | 16 ++++++++++++++++ src/command/commands.h | 1 + src/config/preferences.c | 5 ++++- src/config/preferences.h | 1 + src/ui/console.c | 9 +++++++++ src/ui/ui.h | 1 + src/xmpp/connection.c | 6 +++++- src/xmpp/iq.c | 10 ++++++++++ src/xmpp/stanza.c | 28 ++++++++++++++++++++++++---- src/xmpp/stanza.h | 3 +++ src/xmpp/xmpp.h | 1 + 12 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 7be6603d..f44a21f5 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -858,6 +858,16 @@ static struct cmd_t command_defs[] = "shared : Share logs between all instances, accepts 'on' or 'off', defaults to 'on'.", NULL } } }, + { "/carbons", + cmd_carbons, parse_args, 1, 1, &cons_carbons_setting, + { "/carbons on|off", "Message carbons.", + { "/carbons on|off", + "---------------", + "Enable or disable message carbons.", + "", + "Example : /carbons on", + NULL } } }, + { "/reconnect", cmd_reconnect, parse_args, 1, 1, &cons_reconnect_setting, { "/reconnect seconds", "Set reconnect interval.", diff --git a/src/command/commands.c b/src/command/commands.c index 2059c982..477471d5 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -3882,6 +3882,22 @@ cmd_history(gchar **args, struct cmd_help_t help) return result; } +gboolean +cmd_carbons(gchar **args, struct cmd_help_t help) +{ + gboolean result = _cmd_set_boolean_preference(args[0], help, + "Carbons message", PREF_CARBONS); + + // enable carbons + if (strcmp(args[0], "on") == 0) { + iq_enable_carbons(); + } + else if (strcmp(args[0], "off") == 0){ + iq_disable_carbons(); + } + return result; +} + gboolean cmd_away(gchar **args, struct cmd_help_t help) { diff --git a/src/command/commands.h b/src/command/commands.h index f4e040a9..1c16d635 100644 --- a/src/command/commands.h +++ b/src/command/commands.h @@ -85,6 +85,7 @@ gboolean cmd_grlog(gchar **args, struct cmd_help_t help); gboolean cmd_group(gchar **args, struct cmd_help_t help); gboolean cmd_help(gchar **args, struct cmd_help_t help); gboolean cmd_history(gchar **args, struct cmd_help_t help); +gboolean cmd_carbons(gchar **args, struct cmd_help_t help); gboolean cmd_info(gchar **args, struct cmd_help_t help); gboolean cmd_intype(gchar **args, struct cmd_help_t help); gboolean cmd_invite(gchar **args, struct cmd_help_t help); diff --git a/src/config/preferences.c b/src/config/preferences.c index 67f12b18..47ef9391 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -558,6 +558,7 @@ _get_group(preference_t pref) return PREF_GROUP_PRESENCE; case PREF_CONNECT_ACCOUNT: case PREF_DEFAULT_ACCOUNT: + case PREF_CARBONS: return PREF_GROUP_CONNECTION; case PREF_OTR_WARN: case PREF_OTR_LOG: @@ -593,6 +594,8 @@ _get_key(preference_t pref) return "intype"; case PREF_HISTORY: return "history"; + case PREF_CARBONS: + return "carbons"; case PREF_MOUSE: return "mouse"; case PREF_OCCUPANTS: @@ -698,7 +701,7 @@ _get_default_boolean(preference_t pref) case PREF_OCCUPANTS: case PREF_MUC_PRIVILEGES: case PREF_PRESENCE: - case PREF_WRAP: + case PREF_WRAP: case PREF_INPBLOCK_DYNAMIC: return TRUE; default: diff --git a/src/config/preferences.h b/src/config/preferences.h index 68286f09..aa23e48a 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -59,6 +59,7 @@ typedef enum { PREF_FLASH, PREF_INTYPE, PREF_HISTORY, + PREF_CARBONS, PREF_MOUSE, PREF_OCCUPANTS, PREF_OCCUPANTS_SIZE, diff --git a/src/ui/console.c b/src/ui/console.c index cdf5d1b8..82bac1e0 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -1167,6 +1167,15 @@ cons_history_setting(void) cons_show("Chat history (/history) : OFF"); } +void +cons_carbons_setting(void) +{ + if (prefs_get_boolean(PREF_CARBONS)) + cons_show("Message carbons (/carbons) : ON"); + else + cons_show("Message carbons (/carbons) : OFF"); +} + void cons_show_chat_prefs(void) { diff --git a/src/ui/ui.h b/src/ui/ui.h index 99e73b4a..44ff42f4 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -308,6 +308,7 @@ void cons_outtype_setting(void); void cons_intype_setting(void); void cons_gone_setting(void); void cons_history_setting(void); +void cons_carbons_setting(void); void cons_log_setting(void); void cons_chlog_setting(void); void cons_grlog_setting(void); diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 8bb7c74c..34fba22d 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -463,10 +463,14 @@ _connection_handler(xmpp_conn_t * const conn, message_add_handlers(); presence_add_handlers(); iq_add_handlers(); - iq_enable_carbons(); roster_request(); bookmark_request(); + + if (prefs_get_boolean(PREF_CARBONS)){ + iq_enable_carbons(); + } + jabber_conn.conn_status = JABBER_CONNECTED; if (prefs_get_reconnect() != 0) { diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 071b07c5..be22b01f 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -162,6 +162,16 @@ iq_enable_carbons() xmpp_stanza_release(iq); } +void +iq_disable_carbons() +{ + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_disable_carbons(ctx); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); +} + void iq_disco_info_request(gchar *jid) { diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 06177800..b0d7de86 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -206,12 +206,32 @@ stanza_enable_carbons(xmpp_ctx_t *ctx){ xmpp_stanza_set_name(iq, STANZA_NAME_IQ); xmpp_stanza_set_type(iq, STANZA_TYPE_SET); xmpp_stanza_set_id(iq, id); + free(id); - xmpp_stanza_t *carbon_enable = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(carbon_enable, STANZA_NAME_ENABLE); - xmpp_stanza_set_ns(carbon_enable, STANZA_NS_CARBONS); + xmpp_stanza_t *carbons_enable = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(carbons_enable, STANZA_NAME_ENABLE); + xmpp_stanza_set_ns(carbons_enable, STANZA_NS_CARBONS); - xmpp_stanza_add_child(iq, carbon_enable); + xmpp_stanza_add_child(iq, carbons_enable); + + return iq; +} + +xmpp_stanza_t * +stanza_disable_carbons(xmpp_ctx_t *ctx){ + xmpp_stanza_t *iq = xmpp_stanza_new(ctx); + char *id = create_unique_id(NULL); + + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_SET); + xmpp_stanza_set_id(iq, id); + free(id); + + xmpp_stanza_t *carbons_disable = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(carbons_disable, STANZA_NAME_DISABLE); + xmpp_stanza_set_ns(carbons_disable, STANZA_NS_CARBONS); + + xmpp_stanza_add_child(iq, carbons_disable); return iq; } diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 0c5a2b01..e4f3ce57 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -78,6 +78,7 @@ #define STANZA_NAME_DESTROY "destroy" #define STANZA_NAME_ACTOR "actor" #define STANZA_NAME_ENABLE "enable" +#define STANZA_NAME_DISABLE "disable" // error conditions #define STANZA_NAME_BAD_REQUEST "bad-request" @@ -183,6 +184,8 @@ xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx); xmpp_stanza_t * stanza_enable_carbons(xmpp_ctx_t *ctx); +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); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 41355e30..1fc32665 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -173,6 +173,7 @@ gboolean presence_sub_request_exists(const char * const bare_jid); // iq functions void iq_enable_carbons(); +void iq_disable_carbons(); void iq_send_software_version(const char * const fulljid); void iq_room_list_request(gchar *conferencejid); void iq_disco_info_request(gchar *jid); From a89e04b9d5ef8b65181ddcd1bc3c3ad261406e1a Mon Sep 17 00:00:00 2001 From: Olivier LE MOAL Date: Tue, 3 Feb 2015 15:48:19 +0100 Subject: [PATCH 3/7] Fix help for message carbons --- src/command/command.c | 3 +-- src/config/preferences.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index f44a21f5..d22786af 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -864,8 +864,7 @@ static struct cmd_t command_defs[] = { "/carbons on|off", "---------------", "Enable or disable message carbons.", - "", - "Example : /carbons on", + "The message carbons feature ensures that both sides of all conversations are shared with all the user's clients that implement this protocol.", NULL } } }, { "/reconnect", diff --git a/src/config/preferences.c b/src/config/preferences.c index 47ef9391..7753ad71 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -701,7 +701,7 @@ _get_default_boolean(preference_t pref) case PREF_OCCUPANTS: case PREF_MUC_PRIVILEGES: case PREF_PRESENCE: - case PREF_WRAP: + case PREF_WRAP: case PREF_INPBLOCK_DYNAMIC: return TRUE; default: From 62c1a59f388a55d6a4002e29b03d477262cbbb2d Mon Sep 17 00:00:00 2001 From: Olivier LE MOAL Date: Tue, 3 Feb 2015 18:19:04 +0100 Subject: [PATCH 4/7] Add /carbons in /help settings --- src/command/commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command/commands.c b/src/command/commands.c index 477471d5..29615913 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -730,7 +730,7 @@ cmd_help(gchar **args, struct cmd_help_t help) } else if (strcmp(args[0], "settings") == 0) { gchar *filter[] = { "/account", "/autoaway", "/autoping", "/autoconnect", "/beep", - "/chlog", "/flash", "/gone", "/grlog", "/history", "/intype", + "/carbons", "/chlog", "/flash", "/gone", "/grlog", "/history", "/intype", "/log", "/mouse", "/notify", "/outtype", "/prefs", "/priority", "/reconnect", "/roster", "/splash", "/states", "/statuses", "/theme", "/titlebar", "/vercheck", "/privileges", "/occupants", "/presence", "/wrap" }; From ecfc2a3904c6e2bb4053df42203a359bab1d51be Mon Sep 17 00:00:00 2001 From: Olivier LE MOAL Date: Tue, 3 Feb 2015 18:52:31 +0100 Subject: [PATCH 5/7] Add declarations to tests headers --- tests/ui/stub_ui.c | 1 + tests/xmpp/stub_xmpp.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tests/ui/stub_ui.c b/tests/ui/stub_ui.c index 51b82d42..fe650921 100644 --- a/tests/ui/stub_ui.c +++ b/tests/ui/stub_ui.c @@ -457,6 +457,7 @@ void cons_outtype_setting(void) {} void cons_intype_setting(void) {} void cons_gone_setting(void) {} void cons_history_setting(void) {} +void cons_carbons_setting(void) {} void cons_log_setting(void) {} void cons_chlog_setting(void) {} void cons_grlog_setting(void) {} diff --git a/tests/xmpp/stub_xmpp.c b/tests/xmpp/stub_xmpp.c index 281857f0..02c0acf8 100644 --- a/tests/xmpp/stub_xmpp.c +++ b/tests/xmpp/stub_xmpp.c @@ -119,6 +119,8 @@ gboolean presence_sub_request_exists(const char * const bare_jid) } // iq functions +void iq_disable_carbons(); +void iq_enable_carbons(); void iq_send_software_version(const char * const fulljid) {} void iq_room_list_request(gchar *conferencejid) From 89f472512f3ea88337bcfbee51431f1f7a1934b9 Mon Sep 17 00:00:00 2001 From: Olivier LE MOAL Date: Tue, 3 Feb 2015 19:09:37 +0100 Subject: [PATCH 6/7] Fix stub --- tests/xmpp/stub_xmpp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/xmpp/stub_xmpp.c b/tests/xmpp/stub_xmpp.c index 02c0acf8..dc9a258e 100644 --- a/tests/xmpp/stub_xmpp.c +++ b/tests/xmpp/stub_xmpp.c @@ -119,8 +119,8 @@ gboolean presence_sub_request_exists(const char * const bare_jid) } // iq functions -void iq_disable_carbons(); -void iq_enable_carbons(); +void iq_disable_carbons() {}; +void iq_enable_carbons() {}; void iq_send_software_version(const char * const fulljid) {} void iq_room_list_request(gchar *conferencejid) From 3eeafa2277c6e3002d5f8cc1aa645701527942c8 Mon Sep 17 00:00:00 2001 From: Olivier Le Moal Date: Sat, 21 Feb 2015 22:22:21 +0100 Subject: [PATCH 7/7] fix segfault on self sent message carbon --- src/xmpp/message.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 4f341f6a..b264df54 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -434,6 +434,11 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, gchar *to = xmpp_stanza_get_attribute(message, STANZA_ATTR_TO); gchar *from = xmpp_stanza_get_attribute(message, STANZA_ATTR_FROM); + // happens when receive a carbon of a self sent message + if(to == NULL) { + to = from; + } + Jid *jid_from = jid_create(from); Jid *jid_to = jid_create(to); Jid *my_jid = jid_create(jabber_get_fulljid());