Changeset fa8f57b


Ignore:
Timestamp:
2015-11-21T03:01:05Z (4 years ago)
Author:
dequis <dx@…>
Branches:
master
Children:
2f8e3ca
Parents:
8fdeaa5
git-author:
dequis <dx@…> (21-11-15 02:04:06)
git-committer:
dequis <dx@…> (21-11-15 03:01:05)
Message:

jabber: Implement carbons (XEP-0280)

"Message carbons" (XEP-0280) is a server feature to get copies of
outgoing messages sent from other clients connected to the same account.
It's not widely supported by most public XMPP servers (easier if you
host your own), but this will probably change in the next few years.

This is enabled by default if the server supports it. It can also be
disabled with the "carbons" account setting.

Loosely based on a patch by kormat from trac ticket 1021. (Thanks!)
I moved stuff around, simplified things, fixed a few bugs, and used the
new self-messages feature.

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • doc/user-guide/commands.xml

    r8fdeaa5 rfa8f57b  
    789789        </bitlbee-setting>
    790790
     791        <bitlbee-setting name="carbons" type="boolean" scope="account">
     792                <default>true</default>
     793
     794                <description>
     795                        <para>
     796                                Jabber specific. "Message carbons" (XEP-0280) is a server feature to get copies of outgoing messages sent from other clients connected to the same account. It's not widely supported by most public XMPP servers (easier if you host your own), but this will probably change in the next few years.
     797                        </para>
     798                        <para>
     799                                This defaults to true, which will enable it if the server supports it, or fail silently if it's not. This setting only exists to allow disabling the feature if anyone considers it undesirable.
     800                        </para>
     801                        <para>
     802                                See also the <emphasis>self_messages</emphasis> setting.
     803                        </para>
     804                </description>
     805        </bitlbee-setting>
     806
    791807        <bitlbee-setting name="charset" type="string" scope="global">
    792808                <default>utf-8</default>
  • protocols/jabber/iq.c

    r8fdeaa5 rfa8f57b  
    2828static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    2929static xt_status jabber_gmail_handle_new(struct im_connection *ic, struct xt_node *node);
     30static xt_status jabber_iq_carbons_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    3031
    3132xt_status jabber_pkt_iq(struct xt_node *node, gpointer data)
     
    118119                                                   XMLNS_BYTESTREAMS,
    119120                                                   XMLNS_FILETRANSFER,
     121                                                   XMLNS_CARBONS,
    120122                                                   NULL };
    121123                        const char **f;
     
    10041006{
    10051007        struct jabber_data *jd = ic->proto_data;
    1006         struct xt_node *id;
    1007 
    1008         if ((id = xt_find_path(node, "query/identity"))) {
     1008        struct xt_node *query, *id;
     1009
     1010        if (!(query = xt_find_node(node->children, "query"))) {
     1011                return XT_HANDLED;
     1012        }
     1013
     1014        if (xt_find_node_by_attr(query->children, "feature", "var", XMLNS_CARBONS) &&
     1015            set_getbool(&ic->acc->set, "carbons")) {
     1016
     1017                struct xt_node *enable, *iq;
     1018
     1019                enable = xt_new_node("enable", NULL, NULL);
     1020                xt_add_attr(enable, "xmlns", XMLNS_CARBONS);
     1021                iq = jabber_make_packet("iq", "set", NULL, enable);
     1022
     1023                jabber_cache_add(ic, iq, jabber_iq_carbons_response);
     1024                jabber_write_packet(ic, iq);
     1025        }
     1026
     1027        if ((id = xt_find_node(query->children, "identity"))) {
    10091028                char *cat, *type, *name;
    10101029
     
    10231042        return XT_HANDLED;
    10241043}
     1044
     1045static xt_status jabber_iq_carbons_response(struct im_connection *ic,
     1046                                            struct xt_node *node, struct xt_node *orig)
     1047{
     1048        struct jabber_error *err;
     1049
     1050        if ((err = jabber_error_parse(xt_find_node(node->children, "error"), XMLNS_STANZA_ERROR))) {
     1051                imcb_error(ic, "Error enabling carbons: %s%s%s",
     1052                           err->code, err->text ? ": " : "", err->text ? err->text : "");
     1053                jabber_error_free(err);
     1054        } else {
     1055                imcb_log(ic, "Carbons enabled");
     1056        }
     1057
     1058        return XT_HANDLED;
     1059}
  • protocols/jabber/jabber.c

    r8fdeaa5 rfa8f57b  
    113113        s = set_add(&acc->set, "mail_notifications_handle", NULL, NULL, acc);
    114114        s->flags |= ACC_SET_OFFLINE_ONLY | SET_NULL_OK;
     115
     116        s = set_add(&acc->set, "carbons", "true", set_eval_bool, acc);
     117        s->flags |= ACC_SET_OFFLINE_ONLY;
    115118
    116119        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE |
  • protocols/jabber/jabber.h

    r8fdeaa5 rfa8f57b  
    228228#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
    229229#define XMLNS_GMAILNOTIFY  "google:mail:notify"                                  /* Not a XEP */
     230#define XMLNS_CARBONS      "urn:xmpp:carbons:2"                                  /* XEP-0280 */
     231#define XMLNS_FORWARDING   "urn:xmpp:forward:0"                                  /* XEP-0297 */
    230232#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
    231233#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
  • protocols/jabber/message.c

    r8fdeaa5 rfa8f57b  
    2424#include "jabber.h"
    2525
    26 xt_status jabber_pkt_message(struct xt_node *node, gpointer data)
     26static xt_status jabber_pkt_message_normal(struct xt_node *node, gpointer data, gboolean carbons_sent)
    2727{
    2828        struct im_connection *ic = data;
    29         char *from = xt_find_attr(node, "from");
     29        char *from = xt_find_attr(node, carbons_sent ? "to" : "from");
    3030        char *type = xt_find_attr(node, "type");
    3131        char *id = xt_find_attr(node, "id");
     
    3939        }
    4040
    41         if (request && id && g_strcmp0(type, "groupchat") != 0) {
     41        if (request && id && g_strcmp0(type, "groupchat") != 0 && !carbons_sent) {
    4242                /* Send a message receipt (XEP-0184), looking like this:
    4343                 * <message from='...' id='...' to='...'>
     
    128128                if (fullmsg->len > 0) {
    129129                        imcb_buddy_msg(ic, from, fullmsg->str,
    130                                        0, jabber_get_timestamp(node));
     130                                       carbons_sent ? OPT_SELFMESSAGE : 0, jabber_get_timestamp(node));
    131131                }
    132132                if (room) {
     
    137137
    138138                /* Handling of incoming typing notifications. */
    139                 if (bud == NULL) {
    140                         /* Can't handle these for unknown buddies. */
     139                if (bud == NULL || carbons_sent) {
     140                        /* Can't handle these for unknown buddies.
     141                           And ignore them if it's just carbons */
    141142                } else if (xt_find_node(node->children, "composing")) {
    142143                        bud->flags |= JBFLAG_DOES_XEP85;
     
    162163        return XT_HANDLED;
    163164}
     165
     166static xt_status jabber_carbons_message(struct xt_node *node, gpointer data)
     167{
     168        struct im_connection *ic = data;
     169        struct xt_node *wrap, *fwd, *msg;
     170        gboolean carbons_sent;
     171
     172        if ((wrap = xt_find_node(node->children, "received"))) {
     173                carbons_sent = FALSE;
     174        } else if ((wrap = xt_find_node(node->children, "sent"))) {
     175                carbons_sent = TRUE;
     176        }
     177
     178        if (wrap == NULL || g_strcmp0(xt_find_attr(wrap, "xmlns"), XMLNS_CARBONS) != 0) {
     179                return XT_NEXT;
     180        }
     181
     182        if (!(fwd = xt_find_node(wrap->children, "forwarded")) ||
     183             (g_strcmp0(xt_find_attr(fwd, "xmlns"), XMLNS_FORWARDING) != 0) ||
     184            !(msg = xt_find_node(fwd->children, "message"))) {
     185                imcb_log(ic, "Error: Invalid carbons message received");
     186                return XT_ABORT;
     187        }
     188
     189        return jabber_pkt_message_normal(msg, data, carbons_sent);
     190}
     191
     192xt_status jabber_pkt_message(struct xt_node *node, gpointer data)
     193{
     194        struct im_connection *ic = data;
     195        struct jabber_data *jd = ic->proto_data;
     196        char *from = xt_find_attr(node, "from");
     197
     198        if (jabber_compare_jid(jd->me, from)) {    /* Probably a Carbons message */
     199                xt_status st = jabber_carbons_message(node, data);
     200                if (st == XT_HANDLED || st == XT_ABORT) {
     201                        return st;
     202                }
     203        }
     204        return jabber_pkt_message_normal(node, data, FALSE);
     205}
Note: See TracChangeset for help on using the changeset viewer.