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.