aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/jabber
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/jabber')
-rw-r--r--protocols/jabber/iq.c39
-rw-r--r--protocols/jabber/jabber.c3
-rw-r--r--protocols/jabber/jabber.h2
-rw-r--r--protocols/jabber/message.c54
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);
+}