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); +} | 
