about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2015-03-08 21:51:50 +0000
committerJames Booth <boothj5@gmail.com>2015-03-08 21:51:50 +0000
commit945f29873ec6fb275cdaac72f1e6f143650464b5 (patch)
tree08116e2b1e5505aee66b432c8863a85888fb7a51
parent232bf9b7fc80b0f2013359f002d38bc7a4d9c50f (diff)
parentd89112e13894d4d6a23846997ea7ef0c42674fe4 (diff)
downloadprofani-tty-945f29873ec6fb275cdaac72f1e6f143650464b5.tar.gz
Merge remote-tracking branch 'oliverlemoal/xep-0280' into xep-0280
-rw-r--r--src/command/command.c9
-rw-r--r--src/command/commands.c18
-rw-r--r--src/command/commands.h1
-rw-r--r--src/config/preferences.c3
-rw-r--r--src/config/preferences.h1
-rw-r--r--src/server_events.c5
-rw-r--r--src/server_events.h1
-rw-r--r--src/ui/console.c9
-rw-r--r--src/ui/ui.h1
-rw-r--r--src/xmpp/connection.c5
-rw-r--r--src/xmpp/iq.c20
-rw-r--r--src/xmpp/message.c45
-rw-r--r--src/xmpp/stanza.c38
-rw-r--r--src/xmpp/stanza.h8
-rw-r--r--src/xmpp/xmpp.h2
-rw-r--r--tests/ui/stub_ui.c1
-rw-r--r--tests/xmpp/stub_xmpp.c2
17 files changed, 167 insertions, 2 deletions
diff --git a/src/command/command.c b/src/command/command.c
index ac783303..0a571d22 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -904,6 +904,15 @@ static struct cmd_t command_defs[] =
           "shared on|off : Share logs between all instances, default: 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.",
+        "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",
         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 18f8bf69..4711c18e 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" };
@@ -3893,6 +3893,22 @@ cmd_history(gchar **args, struct cmd_help_t help)
 }
 
 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)
 {
     _update_presence(RESOURCE_AWAY, "away", args);
diff --git a/src/command/commands.h b/src/command/commands.h
index aeb34661..bbf2ba8a 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 b29d7322..eb610732 100644
--- a/src/config/preferences.c
+++ b/src/config/preferences.c
@@ -541,6 +541,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_LOG:
         case PREF_OTR_POLICY:
@@ -575,6 +576,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:
diff --git a/src/config/preferences.h b/src/config/preferences.h
index 2a23261f..61a35c8a 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/server_events.c b/src/server_events.c
index 206146e9..f6755d6a 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -297,6 +297,11 @@ handle_incoming_private_message(char *fulljid, char *message)
 }
 
 void
+handle_carbon(char *barejid, char *message){
+    ui_outgoing_chat_msg("me", barejid, message);
+}
+
+void
 handle_incoming_message(char *barejid, char *resource, char *message)
 {
 #ifdef HAVE_LIBOTR
diff --git a/src/server_events.h b/src/server_events.h
index 4e04f507..9f874ffa 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/ui/console.c b/src/ui/console.c
index eefcb380..745a12ee 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -1178,6 +1178,15 @@ cons_history_setting(void)
 }
 
 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)
 {
     cons_show("Chat preferences:");
diff --git a/src/ui/ui.h b/src/ui/ui.h
index eeaa6d8e..a0408503 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -315,6 +315,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 375dfcba..d6a492ab 100644
--- a/src/xmpp/connection.c
+++ b/src/xmpp/connection.c
@@ -466,6 +466,11 @@ _connection_handler(xmpp_conn_t * const conn,
 
         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 c0a982fa..62193c74 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -153,6 +153,26 @@ iq_room_list_request(gchar *conferencejid)
 }
 
 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_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)
 {
     xmpp_conn_t * const conn = connection_get_conn();
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index 7d504e48..df6afed6 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -423,6 +423,49 @@ _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);
+
+        // 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());
+
+        // 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);
@@ -503,4 +546,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 563aa982..f1aa9cf4 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -199,6 +199,44 @@ 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);
+    free(id);
+
+    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, 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;
+}
+
+xmpp_stanza_t *
 stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state)
 {
     xmpp_stanza_t *msg, *chat_state;
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index b61e8ab8..4291e1fd 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -77,6 +77,8 @@
 #define STANZA_NAME_VALUE "value"
 #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"
@@ -154,6 +156,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 +182,10 @@ 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_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 79bc0579..724e11c4 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -172,6 +172,8 @@ 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_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);
diff --git a/tests/ui/stub_ui.c b/tests/ui/stub_ui.c
index 2d67a543..1a0f650d 100644
--- a/tests/ui/stub_ui.c
+++ b/tests/ui/stub_ui.c
@@ -466,6 +466,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..dc9a258e 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)