Mercurial > ~mikael > mcabber > hg
diff mcabber/src/jab_iq.c @ 1213:4a7db2870685
Improve Private Storage detection.
MCabber now correctly detects Private Storage support when receiving an
item-not-found error (which doesn't mean the server has no support for P.S.,
but that it's empty).
I've added a return value to the callback functions. For now the return value
is only used for IQ error handling.
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Tue, 01 May 2007 18:16:11 +0200 |
parents | 2de8f8ba1f34 |
children | 80c095886fb5 |
line wrap: on
line diff
--- a/mcabber/src/jab_iq.c Tue May 01 16:33:26 2007 +0200 +++ b/mcabber/src/jab_iq.c Tue May 01 18:16:11 2007 +0200 @@ -172,6 +172,7 @@ int iqs_callback(const char *iqid, xmlnode xml_result, guint iqcontext) { eviqs *i; + int retval = 0; i = iqs_find(iqid); if (!i) return -1; @@ -179,10 +180,10 @@ // IQ processing // Note: If xml_result is NULL, this is a timeout if (i->callback) - (*i->callback)(i, xml_result, iqcontext); + retval = (*i->callback)(i, xml_result, iqcontext); iqs_del(iqid); - return 0; + return retval; } void iqs_check_timeout(time_t now_t) @@ -288,7 +289,7 @@ scr_UpdateBuddyWindow(); } -static void iqscallback_version(eviqs *iqp, xmlnode xml_result, guint iqcontext) +static int iqscallback_version(eviqs *iqp, xmlnode xml_result, guint iqcontext) { xmlnode ansqry; char *p; @@ -296,18 +297,18 @@ char *buf; // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return; + if (!xml_result || iqcontext) return -1; ansqry = xmlnode_get_tag(xml_result, "query"); if (!ansqry) { scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result!"); - return; + return 0; } // Display IQ result sender... p = xmlnode_get_attrib(xml_result, "from"); if (!p) { scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result (no sender name)."); - return; + return 0; } bjid = p; @@ -340,6 +341,7 @@ scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_NONE); g_free(buf); } + return 0; } void request_version(const char *fulljid) @@ -352,7 +354,7 @@ jab_send(jc, iqn->xmldata); } -static void iqscallback_time(eviqs *iqp, xmlnode xml_result, guint iqcontext) +static int iqscallback_time(eviqs *iqp, xmlnode xml_result, guint iqcontext) { xmlnode ansqry; char *p; @@ -360,18 +362,18 @@ char *buf; // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return; + if (!xml_result || iqcontext) return -1; ansqry = xmlnode_get_tag(xml_result, "query"); if (!ansqry) { scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result!"); - return; + return 0; } // Display IQ result sender... p = xmlnode_get_attrib(xml_result, "from"); if (!p) { scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result (no sender name)."); - return; + return 0; } bjid = p; @@ -404,6 +406,7 @@ scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_NONE); g_free(buf); } + return 0; } void request_time(const char *fulljid) @@ -416,7 +419,7 @@ jab_send(jc, iqn->xmldata); } -static void iqscallback_last(eviqs *iqp, xmlnode xml_result, guint iqcontext) +static int iqscallback_last(eviqs *iqp, xmlnode xml_result, guint iqcontext) { xmlnode ansqry; char *p; @@ -424,18 +427,18 @@ char *buf; // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return; + if (!xml_result || iqcontext) return -1; ansqry = xmlnode_get_tag(xml_result, "query"); if (!ansqry) { scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result!"); - return; + return 0; } // Display IQ result sender... p = xmlnode_get_attrib(xml_result, "from"); if (!p) { scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result (no sender name)."); - return; + return 0; } bjid = p; @@ -477,6 +480,7 @@ scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO); g_free(buf); } + return 0; } void request_last(const char *fulljid) @@ -600,7 +604,7 @@ } } -static void iqscallback_vcard(eviqs *iqp, xmlnode xml_result, guint iqcontext) +static int iqscallback_vcard(eviqs *iqp, xmlnode xml_result, guint iqcontext) { xmlnode ansqry; char *p; @@ -608,13 +612,13 @@ char *buf; // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return; + if (!xml_result || iqcontext) return -1; // Display IQ result sender... p = xmlnode_get_attrib(xml_result, "from"); if (!p) { scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:vCard result (no sender name)."); - return; + return 0; } bjid = p; @@ -625,7 +629,7 @@ ansqry = xmlnode_get_tag(xml_result, "vCard"); if (!ansqry) { scr_LogPrint(LPRINT_LOGNORM, "Empty IQ:vCard result!"); - return; + return 0; } // bjid should really be the "bare JID", let's strip the resource @@ -637,6 +641,7 @@ // Get result data... handle_vcard_node(bjid, ansqry); + return 0; } void request_vcard(const char *bjid) @@ -707,20 +712,36 @@ g_free(bjid); } -static void iqscallback_storage_bookmarks(eviqs *iqp, xmlnode xml_result, - guint iqcontext) +static int iqscallback_storage_bookmarks(eviqs *iqp, xmlnode xml_result, + guint iqcontext) { xmlnode x, ansqry; char *p; + if (iqcontext == IQS_CONTEXT_ERROR) { + // No server support, or no bookmarks? + p = xmlnode_get_name(xmlnode_get_firstchild(xml_result)); + if (p && !strcmp(p, "item-not-found")) { + // item-no-found means the server has Private Storage, but it's + // currently empty. + xmlnode_free(bookmarks); + bookmarks = xmlnode_new_tag("storage"); + xmlnode_put_attrib(bookmarks, "xmlns", "storage:bookmarks"); + // We return 0 so that the IQ error message be + // not displayed, as it isn't a real error. + return 0; + } + return -1; // Unhandled error + } + // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return; + if (!xml_result || iqcontext) return 0; ansqry = xmlnode_get_tag(xml_result, "query"); ansqry = xmlnode_get_tag(ansqry, "storage"); if (!ansqry) { scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! (storage:bookmarks)"); - return; + return 0; } // Walk through the storage tags @@ -734,6 +755,7 @@ // Copy the bookmarks node xmlnode_free(bookmarks); bookmarks = xmlnode_dup(ansqry); + return 0; } static void request_storage_bookmarks(void) @@ -750,24 +772,42 @@ jab_send(jc, iqn->xmldata); } -static void iqscallback_storage_rosternotes(eviqs *iqp, xmlnode xml_result, - guint iqcontext) +static int iqscallback_storage_rosternotes(eviqs *iqp, xmlnode xml_result, + guint iqcontext) { xmlnode ansqry; + if (iqcontext == IQS_CONTEXT_ERROR) { + const char *p; + // No server support, or no roster notes? + p = xmlnode_get_name(xmlnode_get_firstchild(xml_result)); + if (p && !strcmp(p, "item-not-found")) { + // item-no-found means the server has Private Storage, but it's + // currently empty. + xmlnode_free(rosternotes); + rosternotes = xmlnode_new_tag("storage"); + xmlnode_put_attrib(rosternotes, "xmlns", "storage:rosternotes"); + // We return 0 so that the IQ error message be + // not displayed, as it isn't a real error. + return 0; + } + return -1; // Unhandled error + } + // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return; + if (!xml_result || iqcontext) return 0; ansqry = xmlnode_get_tag(xml_result, "query"); ansqry = xmlnode_get_tag(ansqry, "storage"); if (!ansqry) { scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! " "(storage:rosternotes)"); - return; + return 0; } // Copy the rosternotes node xmlnode_free(rosternotes); rosternotes = xmlnode_dup(ansqry); + return 0; } static void request_storage_rosternotes(void) @@ -784,7 +824,7 @@ jab_send(jc, iqn->xmldata); } -void iqscallback_auth(eviqs *iqp, xmlnode xml_result) +int iqscallback_auth(eviqs *iqp, xmlnode xml_result) { if (jstate == STATE_GETAUTH) { eviqs *iqn; @@ -806,6 +846,7 @@ request_storage_rosternotes(); jstate = STATE_LOGGED; } + return 0; } static void handle_iq_result(jconn conn, char *from, xmlnode xmldata) @@ -1429,10 +1470,10 @@ } else if (!strcmp(type, "set")) { handle_iq_set(conn, from, xmldata); } else if (!strcmp(type, TMSG_ERROR)) { + // Display a message only if the error isn't caught by a callback. xmlnode x = xmlnode_get_tag(xmldata, TMSG_ERROR); - if (x) + if (iqs_callback(xmlnode_get_attrib(xmldata, "id"), x, IQS_CONTEXT_ERROR)) display_server_error(x); - iqs_callback(xmlnode_get_attrib(xmldata, "id"), NULL, IQS_CONTEXT_ERROR); } }