diff options
Diffstat (limited to 'protocols/jabber')
| -rw-r--r-- | protocols/jabber/iq.c | 135 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 12 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 4 | 
3 files changed, 151 insertions, 0 deletions
| diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 33889d32..4eef6925 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -26,6 +26,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);  xt_status jabber_pkt_iq(struct xt_node *node, gpointer data)  { @@ -140,6 +141,10 @@ xt_status jabber_pkt_iq(struct xt_node *node, gpointer data)  		    (s = xt_find_attr(c, "xmlns")) &&  		    (strcmp(s, XMLNS_SI) == 0)) {  			return jabber_si_handle_request(ic, node, c); +		} else if ((c = xt_find_node(node->children, "new-mail")) && +		           (s = xt_find_attr(c, "xmlns")) && +		           (strcmp(s, XMLNS_GMAILNOTIFY) == 0)) { +			return jabber_gmail_handle_new(ic, node);  		} else if (!(c = xt_find_node(node->children, "query")) ||  		           !(s = xt_find_attr(c, "xmlns"))) {  			return XT_HANDLED; @@ -341,6 +346,9 @@ xt_status jabber_pkt_bind_sess(struct im_connection *ic, struct xt_node *node, s  		if (!jabber_write_packet(ic, reply)) {  			return XT_ABORT;  		} +		if (jd->flags & JFLAG_GMAILNOTIFY && node == NULL) { +			jabber_iq_query_server(ic, jd->server, XMLNS_DISCO_INFO); +		}  	} else if ((jd->flags & (JFLAG_WANT_BIND | JFLAG_WANT_SESSION)) == 0) {  		if (!jabber_get_roster(ic)) {  			return XT_ABORT; @@ -370,6 +378,25 @@ int jabber_get_roster(struct im_connection *ic)  	return st;  } +xt_status jabber_iq_query_gmail(struct im_connection *ic); + +static xt_status jabber_gmail_handle_new(struct im_connection *ic, struct xt_node *node) +{ +	struct xt_node *response; +	struct jabber_data *jd = ic->proto_data; + +	response = jabber_make_packet("iq", "result", g_strdup_printf("%s@%s", jd->username, jd->server), NULL); + +	jabber_cache_add(ic, response, NULL); +	if (!jabber_write_packet(ic, response)) { +		return XT_ABORT; +	} + +	jabber_iq_query_gmail(ic); + +	return XT_HANDLED; +} +  static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig)  {  	struct jabber_data *jd = ic->proto_data; @@ -709,6 +736,34 @@ xt_status jabber_iq_parse_features(struct im_connection *ic, struct xt_node *nod  	return XT_HANDLED;  } +xt_status jabber_iq_parse_gmail(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); + +xt_status jabber_iq_query_gmail(struct im_connection *ic) +{ +	struct xt_node *node, *query; +	struct jabber_data *jd = ic->proto_data; + +	node = xt_new_node("query", NULL, NULL); +	xt_add_attr(node, "xmlns", XMLNS_GMAILNOTIFY); +	if (jd->gmail_time) { +		char *formatted = g_strdup_printf("%" G_GUINT64_FORMAT, (jd->gmail_time + 1)); +		xt_add_attr(node, "newer-than-time", formatted); +		g_free(formatted); +	} +	if (jd->gmail_tid) { +		xt_add_attr(node, "newer-than-tid", jd->gmail_tid); +	} + +	if (!(query = jabber_make_packet("iq", "get", jd->me, node))) { +		imcb_log(ic, "WARNING: Couldn't generate server query"); +		xt_free_node(node); +	} + +	jabber_cache_add(ic, query, jabber_iq_parse_gmail); + +	return jabber_write_packet(ic, query) ? XT_HANDLED : XT_ABORT; +} +  xt_status jabber_iq_parse_server_features(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);  xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmlns) @@ -730,6 +785,73 @@ xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmln  	return jabber_write_packet(ic, query) ? XT_HANDLED : XT_ABORT;  } +xt_status jabber_iq_parse_gmail(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) +{ +	struct xt_node *c; +	struct jabber_data *jd = ic->proto_data; +	char *xmlns, *from; +	guint64 l_time = 0; +	char *tid = NULL; + +	if (!(c = xt_find_node(node->children, "mailbox")) || +	    !(from = xt_find_attr(node, "from")) || +	    !(xmlns = xt_find_attr(c, "xmlns")) || +	    (g_strcmp0(xmlns, XMLNS_GMAILNOTIFY) != 0)) { +		imcb_log(ic, "WARNING: Received incomplete mailbox packet for gmail notify"); +		return XT_HANDLED; +	} + +	c = c->children; + +	while ((c = xt_find_node(c, "mail-thread-info"))) { +		struct xt_node *thread, *s; +		char *subject = NULL; +		char *snippet = NULL; +		char *msg = NULL; +		guint64 t_time; + +		t_time = g_ascii_strtoull(xt_find_attr(c, "date"), NULL, 10); +		if (t_time && t_time > l_time) { +			l_time = t_time; +			tid = xt_find_attr(c, "tid"); +		} + +		thread = c->children; + +		if ((s = xt_find_node(thread, "subject"))) { +			subject = s->text; +		} + +		if ((s = xt_find_node(thread, "snippet"))) { +			snippet = s->text; +		} + +		if (subject) { +			msg = g_strdup_printf("New mail for %s. Subj: %s", from, subject); +		} else { +			msg = g_strdup_printf("New mail for %s.", from); +		} +		imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), msg, 0, 0); + +		if (snippet) { +			imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), snippet, 0, 0); +		} + +		c = c->next; +		g_free(msg); +	} + +	if (l_time && (!jd->gmail_time || l_time > jd->gmail_time)) { +		jd->gmail_time = l_time; +		if (tid) { +			g_free(jd->gmail_tid); +			jd->gmail_tid = g_strdup(tid); +		} +	} + +	return XT_HANDLED; +} +  /*   * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info   */ @@ -780,6 +902,19 @@ xt_status jabber_iq_parse_server_features(struct im_connection *ic, struct xt_no  			c = c->next;  		} + +		if (jd->flags & JFLAG_GMAILNOTIFY) { +			/* search for gmail notification feature */ +			c = xt_find_node(node->children, "query"); +			c = c->children; +			while ((c = xt_find_node(c, "feature"))) { +				if (strcmp(xt_find_attr(c, "var"), XMLNS_GMAILNOTIFY) == 0) { +					jabber_iq_query_gmail(ic); +				} +				c = c->next; +			} +		} +  	} else if (strcmp(xmlns, XMLNS_BYTESTREAMS) == 0) {  		char *host, *jid, *port_s;  		int port; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 04db365e..184021dd 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -99,8 +99,13 @@ static void jabber_init(account_t *acc)  	s = set_add(&acc->set, "user_agent", "BitlBee", NULL, acc);  	s = set_add(&acc->set, "xmlconsole", "false", set_eval_bool, acc); + +	s = set_add(&acc->set, "gmail_notifications", "false", set_eval_bool, acc);  	s->flags |= ACC_SET_OFFLINE_ONLY; +	s = set_add(&acc->set, "notify_handle", NULL, NULL, acc); +	s->flags |= ACC_SET_OFFLINE_ONLY | SET_NULL_OK; +  	acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE |  	              ACC_FLAG_HANDLE_DOMAINS;  } @@ -258,6 +263,12 @@ void jabber_connect(struct im_connection *ic)  		   I think this shouldn't break anything. */  		imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL);  	} +	if (set_getbool(&acc->set, "gmail_notifications")) { +		jd->flags |= JFLAG_GMAILNOTIFY; +		if (set_getstr(&acc->set, "notify_handle")) { +			imcb_add_buddy(ic, set_getstr(&acc->set, "notify_handle"), NULL); +		} +	}  	jabber_generate_id_hash(jd);  } @@ -333,6 +344,7 @@ static void jabber_logout(struct im_connection *ic)  	g_free(jd->oauth2_access_token);  	g_free(jd->away_message);  	g_free(jd->internal_jid); +	g_free(jd->gmail_tid);  	g_free(jd->username);  	g_free(jd->me);  	g_free(jd); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index b8ef8b08..37c99ff0 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -45,6 +45,7 @@ typedef enum {  	                                   activates all XEP-85 related code. */  	JFLAG_XMLCONSOLE = 64,          /* If the user added an xmlconsole buddy. */  	JFLAG_STARTTLS_DONE = 128,      /* If a plaintext session was converted to TLS. */ +	JFLAG_GMAILNOTIFY = 256,        /* If gmail notification is enabled */  	JFLAG_GTALK =  0x100000,        /* Is Google Talk, as confirmed by iq discovery */  	JFLAG_HIPCHAT = 0x200000,       /* Is hipchat, because prpl->name says so */ @@ -101,6 +102,8 @@ struct jabber_data {  	   presence_send_update() to inform the server about the changes. */  	const struct jabber_away_state *away_state;  	char *away_message; +	guint64 gmail_time; +	char *gmail_tid;  	md5_state_t cached_id_prefix;  	GHashTable *node_cache; @@ -223,6 +226,7 @@ struct jabber_transfer {  #define XMLNS_DELAY_OLD    "jabber:x:delay"                                      /* XEP-0091 */  #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_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 */ | 
