# HG changeset patch # User Mikael Berthe # Date 1178036171 -7200 # Node ID 4a7db2870685c1a173d86f4e3409758a5a7d8930 # Parent 3b21353e4ad332c05c131878a66e09a9efd0c66e 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. diff -r 3b21353e4ad3 -r 4a7db2870685 mcabber/src/events.c --- a/mcabber/src/events.c Tue May 01 16:33:26 2007 +0200 +++ b/mcabber/src/events.c Tue May 01 18:16:11 2007 +0200 @@ -110,7 +110,7 @@ // IQ processing // Note: If xml_result is NULL, this is a timeout if (i->callback) - (*i->callback)(i, evcontext); + (void)(*i->callback)(i, evcontext); evs_del(evid); return 0; diff -r 3b21353e4ad3 -r 4a7db2870685 mcabber/src/events.h --- a/mcabber/src/events.h Tue May 01 16:33:26 2007 +0200 +++ b/mcabber/src/events.h Tue May 01 18:16:11 2007 +0200 @@ -23,7 +23,7 @@ time_t ts_expire; guint8 type; gpointer data; - void (*callback)(); + int (*callback)(); xmlnode xmldata; char *desc; } eviqs; diff -r 3b21353e4ad3 -r 4a7db2870685 mcabber/src/jab_iq.c --- 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); } } diff -r 3b21353e4ad3 -r 4a7db2870685 mcabber/src/jab_priv.h --- a/mcabber/src/jab_priv.h Tue May 01 16:33:26 2007 +0200 +++ b/mcabber/src/jab_priv.h Tue May 01 18:16:11 2007 +0200 @@ -41,7 +41,7 @@ int iqs_del(const char *iqid); int iqs_callback(const char *iqid, xmlnode xml_result, guint iqcontext); void iqs_check_timeout(time_t now_t); -void iqscallback_auth(eviqs *iqp, xmlnode xml_result); +int iqscallback_auth(eviqs *iqp, xmlnode xml_result); void request_version(const char *fulljid); void request_time(const char *fulljid); void request_last(const char *fulljid); diff -r 3b21353e4ad3 -r 4a7db2870685 mcabber/src/jabglue.c --- a/mcabber/src/jabglue.c Tue May 01 16:33:26 2007 +0200 +++ b/mcabber/src/jabglue.c Tue May 01 18:16:11 2007 +0200 @@ -58,7 +58,7 @@ static void packethandler(jconn, jpacket); static void handle_state_events(char* from, xmlnode xmldata); -static void evscallback_invitation(eviqs *evp, guint evcontext); +static int evscallback_invitation(eviqs *evp, guint evcontext); static void logger(jconn j, int io, const char *buf) { @@ -1746,6 +1746,8 @@ char *s; const char *p; + if (!x) return; + /* RFC3920: * The element: * o MUST contain a child element corresponding to one of the defined @@ -2142,8 +2144,8 @@ if (type && !strcmp(type, TMSG_ERROR)) { xmlnode x; scr_LogPrint(LPRINT_LOGNORM, "Error presence packet from <%s>", r); - if ((x = xmlnode_get_tag(xmldata, TMSG_ERROR)) != NULL) - display_server_error(x); + x = xmlnode_get_tag(xmldata, TMSG_ERROR); + display_server_error(x); // Let's check it isn't a nickname conflict. // XXX Note: We should handle the string condition. @@ -2331,8 +2333,8 @@ timestamp = xml_get_timestamp(xmldata); if (type && !strcmp(type, TMSG_ERROR)) { - if ((x = xmlnode_get_tag(xmldata, TMSG_ERROR)) != NULL) - display_server_error(x); + x = xmlnode_get_tag(xmldata, TMSG_ERROR); + display_server_error(x); #if defined JEP0022 || defined JEP0085 // If the JEP85/22 support is probed, set it back to unknown so that // we probe it again. @@ -2467,7 +2469,7 @@ #endif } -static void evscallback_subscription(eviqs *evp, guint evcontext) +static int evscallback_subscription(eviqs *evp, guint evcontext) { char *barejid; char *buf; @@ -2475,20 +2477,20 @@ if (evcontext == EVS_CONTEXT_TIMEOUT) { scr_LogPrint(LPRINT_LOGNORM, "Event %s timed out, cancelled.", evp->id); - return; + return 0; } if (evcontext == EVS_CONTEXT_CANCEL) { scr_LogPrint(LPRINT_LOGNORM, "Event %s cancelled.", evp->id); - return; + return 0; } if (!(evcontext & EVS_CONTEXT_USER)) - return; + return 0; // Sanity check if (!evp->data) { // Shouldn't happen, data should be set to the barejid. scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); - return; + return 0; } // Ok, let's work now. @@ -2514,6 +2516,7 @@ scr_WriteIncomingMessage(barejid, buf, 0, HBB_PREFIX_INFO); scr_LogPrint(LPRINT_LOGNORM, "%s", buf); g_free(buf); + return 0; } static void decline_invitation(event_muc_invitation *invitation, char *reason) @@ -2542,7 +2545,7 @@ jb_reset_keepalive(); } -static void evscallback_invitation(eviqs *evp, guint evcontext) +static int evscallback_invitation(eviqs *evp, guint evcontext) { event_muc_invitation *invitation = evp->data; @@ -2550,7 +2553,7 @@ if (!invitation) { // Shouldn't happen. scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); - return; + return 0; } if (evcontext == EVS_CONTEXT_TIMEOUT) { @@ -2582,6 +2585,7 @@ g_free(invitation->reason); g_free(invitation); evp->data = NULL; + return 0; } static void handle_packet_s10n(jconn conn, char *type, char *from,