Mercurial > hg
diff mcabber/src/jabglue.c @ 987:f47e312560af
Improve JEP22 + JEP85 support
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Mon, 30 Oct 2006 20:18:00 +0100 |
parents | ed697234bd39 |
children | 6e2bfd1ffded |
line wrap: on
line diff
--- a/mcabber/src/jabglue.c Sun Oct 29 11:43:00 2006 +0100 +++ b/mcabber/src/jabglue.c Mon Oct 30 20:18:00 2006 +0100 @@ -416,6 +416,13 @@ { xmlnode x; gchar *strtype; +#if defined JEP0022 || defined JEP0085 + xmlnode event; + char *rname, *barejid; + GSList *sl_buddy; + guint which_jep = 0; /* 0: none, 1: 85, 2: 22 */ + struct jep0085 *jep85 = NULL; +#endif if (!online) return; @@ -431,20 +438,49 @@ xmlnode_insert_cdata(y, subject, (unsigned) -1); } - // TODO: insert event notifications request -#undef USE_JEP_85 -#ifdef USE_JEP_85 -#define NS_CHAT_STATES "http://jabber.org/features/chatstates" - // JEP-85 - xmlnode event = xmlnode_insert_tag(x, "composing"); - xmlnode_put_attrib(event, "xmlns", NS_CHAT_STATES); -#else - // JEP-22 - xmlnode event = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(event, "xmlns", NS_EVENT); - xmlnode_insert_tag(event, "composing"); +#if defined JEP0022 || defined JEP0085 + rname = strchr(jid, JID_RESOURCE_SEPARATOR); + barejid = jidtodisp(jid); + sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); + g_free(barejid); + + // If we can get a resource name, we use it. Else we use NULL, + // which hopefully will give us the most likely resource. + if (rname) + rname++; + if (sl_buddy) + jep85 = buddy_resource_jep85(sl_buddy->data, rname); #endif +#ifdef JEP0085 + /* JEP-0085 5.1 + * "Until receiving a reply to the initial content message (or a standalone + * notification) from the Contact, the User MUST NOT send subsequent chat + * state notifications to the Contact." + * In our implementation support is initially "unknown", they it's "probed" + * and can become "ok". + */ + if (jep85 && (jep85->support == CHATSTATES_SUPPORT_OK || + jep85->support == CHATSTATES_SUPPORT_UNKNOWN)) { + event = xmlnode_insert_tag(x, "active"); + xmlnode_put_attrib(event, "xmlns", NS_CHATSTATES); + if (jep85->support == CHATSTATES_SUPPORT_UNKNOWN) + jep85->support = CHATSTATES_SUPPORT_PROBED; + else + which_jep = 1; + } +#endif +#ifdef JEP0022 + /* JEP-22 + * If the Contact supports JEP-0085, we do not use JEP-0022. + * If not, we try to fall back to JEP-0022. + */ + if (!which_jep) { + event = xmlnode_insert_tag(x, "x"); + xmlnode_put_attrib(event, "xmlns", NS_EVENT); + xmlnode_insert_tag(event, "composing"); + } +#endif jab_send(jc, x); xmlnode_free(x); @@ -1039,10 +1075,8 @@ x = xmlnode_get_firstchild(xmldata); for ( ; x; x = xmlnode_get_nextsibling(x)) { - if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) - if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, xmlns)) { - break; - } + if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, xmlns)) + break; } return x; } @@ -1392,7 +1426,7 @@ { char *p, *r, *s; xmlnode x; - char *body=NULL; + char *body = NULL; char *enc = NULL; char *tmp = NULL; time_t timestamp = 0; @@ -1459,50 +1493,111 @@ g_free(tmp); } -void handle_state_events(char* from, xmlnode xmldata) +void handle_state_events(char *from, xmlnode xmldata) { - xmlnode x = NULL; - char *rname = strchr(from, JID_RESOURCE_SEPARATOR) + 1; - char *jid = jidtodisp(from); - GSList *slist = roster_find(jid, jidsearch, ROSTER_TYPE_USER); - if (slist == NULL) return; - int jep85 = 0; +#if defined JEP0022 || defined JEP0085 + xmlnode state_ns; + const char *body; + char *rname, *jid; + GSList *sl_buddy; + guint events; + guint which_jep = 0; /* 0: none, 1: 85, 2: 22 */ + struct jep0022 *jep22; + struct jep0085 *jep85; + + rname = strchr(from, JID_RESOURCE_SEPARATOR); + jid = jidtodisp(from); + sl_buddy = roster_find(jid, jidsearch, ROSTER_TYPE_USER); + + /* XXX Actually that's wrong, since it filters out server "offline" + messages (for JEP-0022) */ + if (!sl_buddy || !rname++) { + g_free(jid); + return; + } - guint events = buddy_resource_getevents(slist->data, rname); + events = buddy_resource_getevents(sl_buddy->data, rname); + + jep85 = buddy_resource_jep85(sl_buddy->data, rname); + if (jep85) { + state_ns = xml_get_xmlns(xmldata, NS_CHATSTATES); + if (state_ns) + which_jep = 1; + } - x = xml_get_xmlns(xmldata, NS_EVENT); - if (x == NULL) { - x = xmldata; - jep85 = 1; + if (which_jep != 1) { /* Fall back to JEP-0022 */ + jep22 = buddy_resource_jep22(sl_buddy->data, rname); + if (jep22) { + state_ns = xml_get_xmlns(xmldata, NS_EVENT); + if (state_ns) + which_jep = 2; + } + } + + if (!which_jep) { /* Sender does not use chat states */ + g_free(jid); + return; } - xmlnode tag = xmlnode_get_tag(x, "composing"); - if (tag != NULL) { - events |= ROSTER_EVENT_COMPOSING; - } else if (!jep85) { - events &= ~ROSTER_EVENT_COMPOSING; - } + body = xmlnode_get_tag_data(xmldata, "body"); + + if (which_jep == 1) { /* JEP-0085 */ + const char *p; + jep85->support = CHATSTATES_SUPPORT_OK; + + p = xmlnode_get_name(state_ns); + if (!strcmp(p, "composing")) { + jep85->last_state_rcvd = ROSTER_EVENT_COMPOSING; + } else if (!strcmp(p, "active")) { + jep85->last_state_rcvd = ROSTER_EVENT_ACTIVE; + } else if (!strcmp(p, "paused")) { + jep85->last_state_rcvd = ROSTER_EVENT_PAUSED; + } else if (!strcmp(p, "inactive")) { + jep85->last_state_rcvd = ROSTER_EVENT_INACTIVE; + } else if (!strcmp(p, "gone")) { + jep85->last_state_rcvd = ROSTER_EVENT_GONE; + } - if (jep85) { - tag = xmlnode_get_tag(x, "paused"); - if (tag != NULL) { + if (jep85->last_state_rcvd == ROSTER_EVENT_COMPOSING) + events = ROSTER_EVENT_COMPOSING; + else + events = ROSTER_EVENT_NONE; + } else { /* JEP-0022 */ + const char *msgid; + jep22->support = CHATSTATES_SUPPORT_OK; + jep22->last_state_rcvd = ROSTER_EVENT_NONE; + + msgid = xmlnode_get_attrib(xmldata, "id"); + + if (xmlnode_get_tag(state_ns, "composing")) { + // Clear composing if the message contains a body + if (body) events &= ~ROSTER_EVENT_COMPOSING; - } + else + events |= ROSTER_EVENT_COMPOSING; + jep22->last_state_rcvd |= ROSTER_EVENT_COMPOSING; + + } else { + events &= ~ROSTER_EVENT_COMPOSING; + } + + if (xmlnode_get_tag(state_ns, "delivered")) + jep22->last_state_rcvd |= ROSTER_EVENT_DELIVERED; + + // Cache the message id + g_free(jep22->last_msgid_rcvd); + if (msgid) + jep22->last_msgid_rcvd = g_strdup(msgid); + else + jep22->last_msgid_rcvd = NULL; } - // clear composing and set new message event - // if message contains message body - if (xmlnode_get_tag_data(xmldata, "body") != NULL) { - events |= ROSTER_EVENT_MSG; - events &= ~ROSTER_EVENT_COMPOSING; - } + buddy_resource_setevents(sl_buddy->data, rname, events); - buddy_resource_setevents(slist->data, rname, events); - - scr_UpdateBuddyWindow(); - scr_DrawRoster(); + update_roster = TRUE; g_free(jid); +#endif } static void evscallback_subscription(eviqs *evp, guint evcontext) @@ -1643,10 +1738,6 @@ static void packethandler(jconn conn, jpacket packet) { char *p; - /* - char *r, *s; - const char *m; - */ char *from=NULL, *type=NULL; jb_reset_keepalive(); // reset keepalive timeout @@ -1664,7 +1755,7 @@ if (p) from = p; if (!from && packet->type != JPACKET_IQ) { - scr_LogPrint(LPRINT_LOGNORM, "Error in packet (could be UTF8-related)"); + scr_LogPrint(LPRINT_LOGNORM, "Error in stream packet"); return; }