Mercurial > ~mikael > mcabber > hg
comparison 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 |
comparison
equal
deleted
inserted
replaced
1212:3b21353e4ad3 | 1213:4a7db2870685 |
---|---|
170 // If this is a timeout, xml_result should be NULL. | 170 // If this is a timeout, xml_result should be NULL. |
171 // Return 0 in case of success, -1 if the iqid hasn't been found. | 171 // Return 0 in case of success, -1 if the iqid hasn't been found. |
172 int iqs_callback(const char *iqid, xmlnode xml_result, guint iqcontext) | 172 int iqs_callback(const char *iqid, xmlnode xml_result, guint iqcontext) |
173 { | 173 { |
174 eviqs *i; | 174 eviqs *i; |
175 int retval = 0; | |
175 | 176 |
176 i = iqs_find(iqid); | 177 i = iqs_find(iqid); |
177 if (!i) return -1; | 178 if (!i) return -1; |
178 | 179 |
179 // IQ processing | 180 // IQ processing |
180 // Note: If xml_result is NULL, this is a timeout | 181 // Note: If xml_result is NULL, this is a timeout |
181 if (i->callback) | 182 if (i->callback) |
182 (*i->callback)(i, xml_result, iqcontext); | 183 retval = (*i->callback)(i, xml_result, iqcontext); |
183 | 184 |
184 iqs_del(iqid); | 185 iqs_del(iqid); |
185 return 0; | 186 return retval; |
186 } | 187 } |
187 | 188 |
188 void iqs_check_timeout(time_t now_t) | 189 void iqs_check_timeout(time_t now_t) |
189 { | 190 { |
190 GSList *p; | 191 GSList *p; |
286 update_roster = TRUE; | 287 update_roster = TRUE; |
287 if (need_refresh) | 288 if (need_refresh) |
288 scr_UpdateBuddyWindow(); | 289 scr_UpdateBuddyWindow(); |
289 } | 290 } |
290 | 291 |
291 static void iqscallback_version(eviqs *iqp, xmlnode xml_result, guint iqcontext) | 292 static int iqscallback_version(eviqs *iqp, xmlnode xml_result, guint iqcontext) |
292 { | 293 { |
293 xmlnode ansqry; | 294 xmlnode ansqry; |
294 char *p; | 295 char *p; |
295 char *bjid; | 296 char *bjid; |
296 char *buf; | 297 char *buf; |
297 | 298 |
298 // Leave now if we cannot process xml_result | 299 // Leave now if we cannot process xml_result |
299 if (!xml_result || iqcontext) return; | 300 if (!xml_result || iqcontext) return -1; |
300 | 301 |
301 ansqry = xmlnode_get_tag(xml_result, "query"); | 302 ansqry = xmlnode_get_tag(xml_result, "query"); |
302 if (!ansqry) { | 303 if (!ansqry) { |
303 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result!"); | 304 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result!"); |
304 return; | 305 return 0; |
305 } | 306 } |
306 // Display IQ result sender... | 307 // Display IQ result sender... |
307 p = xmlnode_get_attrib(xml_result, "from"); | 308 p = xmlnode_get_attrib(xml_result, "from"); |
308 if (!p) { | 309 if (!p) { |
309 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result (no sender name)."); | 310 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result (no sender name)."); |
310 return; | 311 return 0; |
311 } | 312 } |
312 bjid = p; | 313 bjid = p; |
313 | 314 |
314 buf = g_strdup_printf("Received IQ:version result from <%s>", bjid); | 315 buf = g_strdup_printf("Received IQ:version result from <%s>", bjid); |
315 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); | 316 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); |
338 if (p) { | 339 if (p) { |
339 buf = g_strdup_printf("OS: %s", p); | 340 buf = g_strdup_printf("OS: %s", p); |
340 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_NONE); | 341 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_NONE); |
341 g_free(buf); | 342 g_free(buf); |
342 } | 343 } |
344 return 0; | |
343 } | 345 } |
344 | 346 |
345 void request_version(const char *fulljid) | 347 void request_version(const char *fulljid) |
346 { | 348 { |
347 eviqs *iqn; | 349 eviqs *iqn; |
350 xmlnode_put_attrib(iqn->xmldata, "to", fulljid); | 352 xmlnode_put_attrib(iqn->xmldata, "to", fulljid); |
351 iqn->callback = &iqscallback_version; | 353 iqn->callback = &iqscallback_version; |
352 jab_send(jc, iqn->xmldata); | 354 jab_send(jc, iqn->xmldata); |
353 } | 355 } |
354 | 356 |
355 static void iqscallback_time(eviqs *iqp, xmlnode xml_result, guint iqcontext) | 357 static int iqscallback_time(eviqs *iqp, xmlnode xml_result, guint iqcontext) |
356 { | 358 { |
357 xmlnode ansqry; | 359 xmlnode ansqry; |
358 char *p; | 360 char *p; |
359 char *bjid; | 361 char *bjid; |
360 char *buf; | 362 char *buf; |
361 | 363 |
362 // Leave now if we cannot process xml_result | 364 // Leave now if we cannot process xml_result |
363 if (!xml_result || iqcontext) return; | 365 if (!xml_result || iqcontext) return -1; |
364 | 366 |
365 ansqry = xmlnode_get_tag(xml_result, "query"); | 367 ansqry = xmlnode_get_tag(xml_result, "query"); |
366 if (!ansqry) { | 368 if (!ansqry) { |
367 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result!"); | 369 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result!"); |
368 return; | 370 return 0; |
369 } | 371 } |
370 // Display IQ result sender... | 372 // Display IQ result sender... |
371 p = xmlnode_get_attrib(xml_result, "from"); | 373 p = xmlnode_get_attrib(xml_result, "from"); |
372 if (!p) { | 374 if (!p) { |
373 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result (no sender name)."); | 375 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result (no sender name)."); |
374 return; | 376 return 0; |
375 } | 377 } |
376 bjid = p; | 378 bjid = p; |
377 | 379 |
378 buf = g_strdup_printf("Received IQ:time result from <%s>", bjid); | 380 buf = g_strdup_printf("Received IQ:time result from <%s>", bjid); |
379 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); | 381 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); |
402 if (p) { | 404 if (p) { |
403 buf = g_strdup_printf("Time: %s", p); | 405 buf = g_strdup_printf("Time: %s", p); |
404 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_NONE); | 406 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_NONE); |
405 g_free(buf); | 407 g_free(buf); |
406 } | 408 } |
409 return 0; | |
407 } | 410 } |
408 | 411 |
409 void request_time(const char *fulljid) | 412 void request_time(const char *fulljid) |
410 { | 413 { |
411 eviqs *iqn; | 414 eviqs *iqn; |
414 xmlnode_put_attrib(iqn->xmldata, "to", fulljid); | 417 xmlnode_put_attrib(iqn->xmldata, "to", fulljid); |
415 iqn->callback = &iqscallback_time; | 418 iqn->callback = &iqscallback_time; |
416 jab_send(jc, iqn->xmldata); | 419 jab_send(jc, iqn->xmldata); |
417 } | 420 } |
418 | 421 |
419 static void iqscallback_last(eviqs *iqp, xmlnode xml_result, guint iqcontext) | 422 static int iqscallback_last(eviqs *iqp, xmlnode xml_result, guint iqcontext) |
420 { | 423 { |
421 xmlnode ansqry; | 424 xmlnode ansqry; |
422 char *p; | 425 char *p; |
423 char *bjid; | 426 char *bjid; |
424 char *buf; | 427 char *buf; |
425 | 428 |
426 // Leave now if we cannot process xml_result | 429 // Leave now if we cannot process xml_result |
427 if (!xml_result || iqcontext) return; | 430 if (!xml_result || iqcontext) return -1; |
428 | 431 |
429 ansqry = xmlnode_get_tag(xml_result, "query"); | 432 ansqry = xmlnode_get_tag(xml_result, "query"); |
430 if (!ansqry) { | 433 if (!ansqry) { |
431 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result!"); | 434 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result!"); |
432 return; | 435 return 0; |
433 } | 436 } |
434 // Display IQ result sender... | 437 // Display IQ result sender... |
435 p = xmlnode_get_attrib(xml_result, "from"); | 438 p = xmlnode_get_attrib(xml_result, "from"); |
436 if (!p) { | 439 if (!p) { |
437 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result (no sender name)."); | 440 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result (no sender name)."); |
438 return; | 441 return 0; |
439 } | 442 } |
440 bjid = p; | 443 bjid = p; |
441 | 444 |
442 buf = g_strdup_printf("Received IQ:last result from <%s>", bjid); | 445 buf = g_strdup_printf("Received IQ:last result from <%s>", bjid); |
443 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); | 446 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); |
475 if (p) { | 478 if (p) { |
476 buf = g_strdup_printf("Status message: %s", p); | 479 buf = g_strdup_printf("Status message: %s", p); |
477 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO); | 480 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO); |
478 g_free(buf); | 481 g_free(buf); |
479 } | 482 } |
483 return 0; | |
480 } | 484 } |
481 | 485 |
482 void request_last(const char *fulljid) | 486 void request_last(const char *fulljid) |
483 { | 487 { |
484 eviqs *iqn; | 488 eviqs *iqn; |
598 } | 602 } |
599 } | 603 } |
600 } | 604 } |
601 } | 605 } |
602 | 606 |
603 static void iqscallback_vcard(eviqs *iqp, xmlnode xml_result, guint iqcontext) | 607 static int iqscallback_vcard(eviqs *iqp, xmlnode xml_result, guint iqcontext) |
604 { | 608 { |
605 xmlnode ansqry; | 609 xmlnode ansqry; |
606 char *p; | 610 char *p; |
607 char *bjid; | 611 char *bjid; |
608 char *buf; | 612 char *buf; |
609 | 613 |
610 // Leave now if we cannot process xml_result | 614 // Leave now if we cannot process xml_result |
611 if (!xml_result || iqcontext) return; | 615 if (!xml_result || iqcontext) return -1; |
612 | 616 |
613 // Display IQ result sender... | 617 // Display IQ result sender... |
614 p = xmlnode_get_attrib(xml_result, "from"); | 618 p = xmlnode_get_attrib(xml_result, "from"); |
615 if (!p) { | 619 if (!p) { |
616 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:vCard result (no sender name)."); | 620 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:vCard result (no sender name)."); |
617 return; | 621 return 0; |
618 } | 622 } |
619 bjid = p; | 623 bjid = p; |
620 | 624 |
621 buf = g_strdup_printf("Received IQ:vCard result from <%s>", bjid); | 625 buf = g_strdup_printf("Received IQ:vCard result from <%s>", bjid); |
622 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); | 626 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); |
623 | 627 |
624 // Get the vCard node | 628 // Get the vCard node |
625 ansqry = xmlnode_get_tag(xml_result, "vCard"); | 629 ansqry = xmlnode_get_tag(xml_result, "vCard"); |
626 if (!ansqry) { | 630 if (!ansqry) { |
627 scr_LogPrint(LPRINT_LOGNORM, "Empty IQ:vCard result!"); | 631 scr_LogPrint(LPRINT_LOGNORM, "Empty IQ:vCard result!"); |
628 return; | 632 return 0; |
629 } | 633 } |
630 | 634 |
631 // bjid should really be the "bare JID", let's strip the resource | 635 // bjid should really be the "bare JID", let's strip the resource |
632 p = strchr(bjid, JID_RESOURCE_SEPARATOR); | 636 p = strchr(bjid, JID_RESOURCE_SEPARATOR); |
633 if (p) *p = '\0'; | 637 if (p) *p = '\0'; |
635 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO); | 639 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO); |
636 g_free(buf); | 640 g_free(buf); |
637 | 641 |
638 // Get result data... | 642 // Get result data... |
639 handle_vcard_node(bjid, ansqry); | 643 handle_vcard_node(bjid, ansqry); |
644 return 0; | |
640 } | 645 } |
641 | 646 |
642 void request_vcard(const char *bjid) | 647 void request_vcard(const char *bjid) |
643 { | 648 { |
644 eviqs *iqn; | 649 eviqs *iqn; |
705 g_free(tmpnick); | 710 g_free(tmpnick); |
706 } | 711 } |
707 g_free(bjid); | 712 g_free(bjid); |
708 } | 713 } |
709 | 714 |
710 static void iqscallback_storage_bookmarks(eviqs *iqp, xmlnode xml_result, | 715 static int iqscallback_storage_bookmarks(eviqs *iqp, xmlnode xml_result, |
711 guint iqcontext) | 716 guint iqcontext) |
712 { | 717 { |
713 xmlnode x, ansqry; | 718 xmlnode x, ansqry; |
714 char *p; | 719 char *p; |
715 | 720 |
721 if (iqcontext == IQS_CONTEXT_ERROR) { | |
722 // No server support, or no bookmarks? | |
723 p = xmlnode_get_name(xmlnode_get_firstchild(xml_result)); | |
724 if (p && !strcmp(p, "item-not-found")) { | |
725 // item-no-found means the server has Private Storage, but it's | |
726 // currently empty. | |
727 xmlnode_free(bookmarks); | |
728 bookmarks = xmlnode_new_tag("storage"); | |
729 xmlnode_put_attrib(bookmarks, "xmlns", "storage:bookmarks"); | |
730 // We return 0 so that the IQ error message be | |
731 // not displayed, as it isn't a real error. | |
732 return 0; | |
733 } | |
734 return -1; // Unhandled error | |
735 } | |
736 | |
716 // Leave now if we cannot process xml_result | 737 // Leave now if we cannot process xml_result |
717 if (!xml_result || iqcontext) return; | 738 if (!xml_result || iqcontext) return 0; |
718 | 739 |
719 ansqry = xmlnode_get_tag(xml_result, "query"); | 740 ansqry = xmlnode_get_tag(xml_result, "query"); |
720 ansqry = xmlnode_get_tag(ansqry, "storage"); | 741 ansqry = xmlnode_get_tag(ansqry, "storage"); |
721 if (!ansqry) { | 742 if (!ansqry) { |
722 scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! (storage:bookmarks)"); | 743 scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! (storage:bookmarks)"); |
723 return; | 744 return 0; |
724 } | 745 } |
725 | 746 |
726 // Walk through the storage tags | 747 // Walk through the storage tags |
727 x = xmlnode_get_firstchild(ansqry); | 748 x = xmlnode_get_firstchild(ansqry); |
728 for ( ; x; x = xmlnode_get_nextsibling(x)) { | 749 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
732 storage_bookmarks_parse_conference(x); | 753 storage_bookmarks_parse_conference(x); |
733 } | 754 } |
734 // Copy the bookmarks node | 755 // Copy the bookmarks node |
735 xmlnode_free(bookmarks); | 756 xmlnode_free(bookmarks); |
736 bookmarks = xmlnode_dup(ansqry); | 757 bookmarks = xmlnode_dup(ansqry); |
758 return 0; | |
737 } | 759 } |
738 | 760 |
739 static void request_storage_bookmarks(void) | 761 static void request_storage_bookmarks(void) |
740 { | 762 { |
741 eviqs *iqn; | 763 eviqs *iqn; |
748 | 770 |
749 iqn->callback = &iqscallback_storage_bookmarks; | 771 iqn->callback = &iqscallback_storage_bookmarks; |
750 jab_send(jc, iqn->xmldata); | 772 jab_send(jc, iqn->xmldata); |
751 } | 773 } |
752 | 774 |
753 static void iqscallback_storage_rosternotes(eviqs *iqp, xmlnode xml_result, | 775 static int iqscallback_storage_rosternotes(eviqs *iqp, xmlnode xml_result, |
754 guint iqcontext) | 776 guint iqcontext) |
755 { | 777 { |
756 xmlnode ansqry; | 778 xmlnode ansqry; |
757 | 779 |
780 if (iqcontext == IQS_CONTEXT_ERROR) { | |
781 const char *p; | |
782 // No server support, or no roster notes? | |
783 p = xmlnode_get_name(xmlnode_get_firstchild(xml_result)); | |
784 if (p && !strcmp(p, "item-not-found")) { | |
785 // item-no-found means the server has Private Storage, but it's | |
786 // currently empty. | |
787 xmlnode_free(rosternotes); | |
788 rosternotes = xmlnode_new_tag("storage"); | |
789 xmlnode_put_attrib(rosternotes, "xmlns", "storage:rosternotes"); | |
790 // We return 0 so that the IQ error message be | |
791 // not displayed, as it isn't a real error. | |
792 return 0; | |
793 } | |
794 return -1; // Unhandled error | |
795 } | |
796 | |
758 // Leave now if we cannot process xml_result | 797 // Leave now if we cannot process xml_result |
759 if (!xml_result || iqcontext) return; | 798 if (!xml_result || iqcontext) return 0; |
760 | 799 |
761 ansqry = xmlnode_get_tag(xml_result, "query"); | 800 ansqry = xmlnode_get_tag(xml_result, "query"); |
762 ansqry = xmlnode_get_tag(ansqry, "storage"); | 801 ansqry = xmlnode_get_tag(ansqry, "storage"); |
763 if (!ansqry) { | 802 if (!ansqry) { |
764 scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! " | 803 scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! " |
765 "(storage:rosternotes)"); | 804 "(storage:rosternotes)"); |
766 return; | 805 return 0; |
767 } | 806 } |
768 // Copy the rosternotes node | 807 // Copy the rosternotes node |
769 xmlnode_free(rosternotes); | 808 xmlnode_free(rosternotes); |
770 rosternotes = xmlnode_dup(ansqry); | 809 rosternotes = xmlnode_dup(ansqry); |
810 return 0; | |
771 } | 811 } |
772 | 812 |
773 static void request_storage_rosternotes(void) | 813 static void request_storage_rosternotes(void) |
774 { | 814 { |
775 eviqs *iqn; | 815 eviqs *iqn; |
782 | 822 |
783 iqn->callback = &iqscallback_storage_rosternotes; | 823 iqn->callback = &iqscallback_storage_rosternotes; |
784 jab_send(jc, iqn->xmldata); | 824 jab_send(jc, iqn->xmldata); |
785 } | 825 } |
786 | 826 |
787 void iqscallback_auth(eviqs *iqp, xmlnode xml_result) | 827 int iqscallback_auth(eviqs *iqp, xmlnode xml_result) |
788 { | 828 { |
789 if (jstate == STATE_GETAUTH) { | 829 if (jstate == STATE_GETAUTH) { |
790 eviqs *iqn; | 830 eviqs *iqn; |
791 | 831 |
792 if (xml_result) { | 832 if (xml_result) { |
804 request_roster(); | 844 request_roster(); |
805 request_storage_bookmarks(); | 845 request_storage_bookmarks(); |
806 request_storage_rosternotes(); | 846 request_storage_rosternotes(); |
807 jstate = STATE_LOGGED; | 847 jstate = STATE_LOGGED; |
808 } | 848 } |
849 return 0; | |
809 } | 850 } |
810 | 851 |
811 static void handle_iq_result(jconn conn, char *from, xmlnode xmldata) | 852 static void handle_iq_result(jconn conn, char *from, xmlnode xmldata) |
812 { | 853 { |
813 xmlnode x; | 854 xmlnode x; |
1427 } else if (!strcmp(type, "get")) { | 1468 } else if (!strcmp(type, "get")) { |
1428 handle_iq_get(conn, from, xmldata); | 1469 handle_iq_get(conn, from, xmldata); |
1429 } else if (!strcmp(type, "set")) { | 1470 } else if (!strcmp(type, "set")) { |
1430 handle_iq_set(conn, from, xmldata); | 1471 handle_iq_set(conn, from, xmldata); |
1431 } else if (!strcmp(type, TMSG_ERROR)) { | 1472 } else if (!strcmp(type, TMSG_ERROR)) { |
1473 // Display a message only if the error isn't caught by a callback. | |
1432 xmlnode x = xmlnode_get_tag(xmldata, TMSG_ERROR); | 1474 xmlnode x = xmlnode_get_tag(xmldata, TMSG_ERROR); |
1433 if (x) | 1475 if (iqs_callback(xmlnode_get_attrib(xmldata, "id"), x, IQS_CONTEXT_ERROR)) |
1434 display_server_error(x); | 1476 display_server_error(x); |
1435 iqs_callback(xmlnode_get_attrib(xmldata, "id"), NULL, IQS_CONTEXT_ERROR); | |
1436 } | 1477 } |
1437 } | 1478 } |
1438 | 1479 |
1439 // send_storage_bookmarks() | 1480 // send_storage_bookmarks() |
1440 // Send the current bookmarks node to update the server. | 1481 // Send the current bookmarks node to update the server. |