diff options
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/jabber/iq.c | 39 | ||||
-rw-r--r-- | protocols/jabber/jabber.c | 3 | ||||
-rw-r--r-- | protocols/jabber/jabber.h | 2 | ||||
-rw-r--r-- | protocols/jabber/message.c | 54 |
4 files changed, 90 insertions, 8 deletions
diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index b3fe4206..d5ed8f21 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -27,6 +27,7 @@ static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); static xt_status jabber_gmail_handle_new(struct im_connection *ic, struct xt_node *node); +static xt_status jabber_iq_carbons_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); xt_status jabber_pkt_iq(struct xt_node *node, gpointer data) { @@ -117,6 +118,7 @@ xt_status jabber_pkt_iq(struct xt_node *node, gpointer data) XMLNS_SI, XMLNS_BYTESTREAMS, XMLNS_FILETRANSFER, + XMLNS_CARBONS, NULL }; const char **f; @@ -1003,9 +1005,26 @@ static xt_status jabber_iq_disco_server_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct jabber_data *jd = ic->proto_data; - struct xt_node *id; + struct xt_node *query, *id; - if ((id = xt_find_path(node, "query/identity"))) { + if (!(query = xt_find_node(node->children, "query"))) { + return XT_HANDLED; + } + + if (xt_find_node_by_attr(query->children, "feature", "var", XMLNS_CARBONS) && + set_getbool(&ic->acc->set, "carbons")) { + + struct xt_node *enable, *iq; + + enable = xt_new_node("enable", NULL, NULL); + xt_add_attr(enable, "xmlns", XMLNS_CARBONS); + iq = jabber_make_packet("iq", "set", NULL, enable); + + jabber_cache_add(ic, iq, jabber_iq_carbons_response); + jabber_write_packet(ic, iq); + } + + if ((id = xt_find_node(query->children, "identity"))) { char *cat, *type, *name; if (!(cat = xt_find_attr(id, "category")) || @@ -1022,3 +1041,19 @@ static xt_status jabber_iq_disco_server_response(struct im_connection *ic, return XT_HANDLED; } + +static xt_status jabber_iq_carbons_response(struct im_connection *ic, + struct xt_node *node, struct xt_node *orig) +{ + struct jabber_error *err; + + if ((err = jabber_error_parse(xt_find_node(node->children, "error"), XMLNS_STANZA_ERROR))) { + imcb_error(ic, "Error enabling carbons: %s%s%s", + err->code, err->text ? ": " : "", err->text ? err->text : ""); + jabber_error_free(err); + } else { + imcb_log(ic, "Carbons enabled"); + } + + return XT_HANDLED; +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 0dbcfa4e..35cf0c90 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -113,6 +113,9 @@ static void jabber_init(account_t *acc) s = set_add(&acc->set, "mail_notifications_handle", NULL, NULL, acc); s->flags |= ACC_SET_OFFLINE_ONLY | SET_NULL_OK; + s = set_add(&acc->set, "carbons", "true", set_eval_bool, acc); + s->flags |= ACC_SET_OFFLINE_ONLY; + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE | ACC_FLAG_HANDLE_DOMAINS; } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 37c99ff0..75bd123f 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -227,6 +227,8 @@ struct jabber_transfer { #define XMLNS_DELAY "urn:xmpp:delay" /* XEP-0203 */ #define XMLNS_XDATA "jabber:x:data" /* XEP-0004 */ #define XMLNS_GMAILNOTIFY "google:mail:notify" /* Not a XEP */ +#define XMLNS_CARBONS "urn:xmpp:carbons:2" /* XEP-0280 */ +#define XMLNS_FORWARDING "urn:xmpp:forward:0" /* XEP-0297 */ #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* XEP-0085 */ #define XMLNS_DISCO_INFO "http://jabber.org/protocol/disco#info" /* XEP-0030 */ #define XMLNS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" /* XEP-0030 */ diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 94ef8014..c57e6337 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -23,10 +23,10 @@ #include "jabber.h" -xt_status jabber_pkt_message(struct xt_node *node, gpointer data) +static xt_status jabber_pkt_message_normal(struct xt_node *node, gpointer data, gboolean carbons_sent) { struct im_connection *ic = data; - char *from = xt_find_attr(node, "from"); + char *from = xt_find_attr(node, carbons_sent ? "to" : "from"); char *type = xt_find_attr(node, "type"); char *id = xt_find_attr(node, "id"); struct xt_node *body = xt_find_node(node->children, "body"), *c; @@ -38,7 +38,7 @@ xt_status jabber_pkt_message(struct xt_node *node, gpointer data) return XT_HANDLED; /* Consider this packet corrupted. */ } - if (request && id && g_strcmp0(type, "groupchat") != 0) { + if (request && id && g_strcmp0(type, "groupchat") != 0 && !carbons_sent) { /* Send a message receipt (XEP-0184), looking like this: * <message from='...' id='...' to='...'> * <received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/> @@ -127,7 +127,7 @@ xt_status jabber_pkt_message(struct xt_node *node, gpointer data) if (fullmsg->len > 0) { imcb_buddy_msg(ic, from, fullmsg->str, - 0, jabber_get_timestamp(node)); + carbons_sent ? OPT_SELFMESSAGE : 0, jabber_get_timestamp(node)); } if (room) { imcb_chat_invite(ic, room, from, reason); @@ -136,8 +136,9 @@ xt_status jabber_pkt_message(struct xt_node *node, gpointer data) g_string_free(fullmsg, TRUE); /* Handling of incoming typing notifications. */ - if (bud == NULL) { - /* Can't handle these for unknown buddies. */ + if (bud == NULL || carbons_sent) { + /* Can't handle these for unknown buddies. + And ignore them if it's just carbons */ } else if (xt_find_node(node->children, "composing")) { bud->flags |= JBFLAG_DOES_XEP85; imcb_buddy_typing(ic, from, OPT_TYPING); @@ -161,3 +162,44 @@ xt_status jabber_pkt_message(struct xt_node *node, gpointer data) return XT_HANDLED; } + +static xt_status jabber_carbons_message(struct xt_node *node, gpointer data) +{ + struct im_connection *ic = data; + struct xt_node *wrap, *fwd, *msg; + gboolean carbons_sent; + + if ((wrap = xt_find_node(node->children, "received"))) { + carbons_sent = FALSE; + } else if ((wrap = xt_find_node(node->children, "sent"))) { + carbons_sent = TRUE; + } + + if (wrap == NULL || g_strcmp0(xt_find_attr(wrap, "xmlns"), XMLNS_CARBONS) != 0) { + return XT_NEXT; + } + + if (!(fwd = xt_find_node(wrap->children, "forwarded")) || + (g_strcmp0(xt_find_attr(fwd, "xmlns"), XMLNS_FORWARDING) != 0) || + !(msg = xt_find_node(fwd->children, "message"))) { + imcb_log(ic, "Error: Invalid carbons message received"); + return XT_ABORT; + } + + return jabber_pkt_message_normal(msg, data, carbons_sent); +} + +xt_status jabber_pkt_message(struct xt_node *node, gpointer data) +{ + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; + char *from = xt_find_attr(node, "from"); + + if (jabber_compare_jid(jd->me, from)) { /* Probably a Carbons message */ + xt_status st = jabber_carbons_message(node, data); + if (st == XT_HANDLED || st == XT_ABORT) { + return st; + } + } + return jabber_pkt_message_normal(node, data, FALSE); +} |