Mercurial > pidgin
comparison libpurple/protocols/jabber/buddy.c @ 27590:a08e84032814
merge of '2348ff22f0ff3453774b8b25b36238465580c609'
and 'e76f11543c2a4aa05bdf584f087cbe3439029661'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sun, 12 Jul 2009 05:43:38 +0000 |
parents | 95c56191d26c |
children | a12574d982a1 |
comparison
equal
deleted
inserted
replaced
27104:048bcf41deef | 27590:a08e84032814 |
---|---|
159 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); | 159 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); |
160 if(!jbr) { | 160 if(!jbr) { |
161 jbr = g_new0(JabberBuddyResource, 1); | 161 jbr = g_new0(JabberBuddyResource, 1); |
162 jbr->jb = jb; | 162 jbr->jb = jb; |
163 jbr->name = g_strdup(resource); | 163 jbr->name = g_strdup(resource); |
164 jbr->capabilities = JABBER_CAP_XHTML; | 164 jbr->capabilities = JABBER_CAP_NONE; |
165 jbr->tz_off = PURPLE_NO_TZ_OFF; | 165 jbr->tz_off = PURPLE_NO_TZ_OFF; |
166 jb->resources = g_list_append(jb->resources, jbr); | 166 jb->resources = g_list_append(jb->resources, jbr); |
167 } | 167 } |
168 jbr->priority = priority; | 168 jbr->priority = priority; |
169 jbr->state = state; | 169 jbr->state = state; |
648 g_free(jbi->last_message); | 648 g_free(jbi->last_message); |
649 purple_notify_user_info_destroy(jbi->user_info); | 649 purple_notify_user_info_destroy(jbi->user_info); |
650 g_free(jbi); | 650 g_free(jbi); |
651 } | 651 } |
652 | 652 |
653 static void | |
654 add_jbr_info(JabberBuddyInfo *jbi, const char *resource, | |
655 JabberBuddyResource *jbr) | |
656 { | |
657 JabberBuddyInfoResource *jbir; | |
658 PurpleNotifyUserInfo *user_info; | |
659 | |
660 jbir = g_hash_table_lookup(jbi->resources, resource); | |
661 user_info = jbi->user_info; | |
662 | |
663 if (jbr && jbr->client.name) { | |
664 char *tmp = | |
665 g_strdup_printf("%s%s%s", jbr->client.name, | |
666 (jbr->client.version ? " " : ""), | |
667 (jbr->client.version ? jbr->client.version : "")); | |
668 purple_notify_user_info_prepend_pair(user_info, _("Client"), tmp); | |
669 g_free(tmp); | |
670 | |
671 if (jbr->client.os) | |
672 purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os); | |
673 } | |
674 | |
675 if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) { | |
676 time_t now_t; | |
677 struct tm *now; | |
678 char *timestamp; | |
679 time(&now_t); | |
680 now_t += jbr->tz_off; | |
681 now = gmtime(&now_t); | |
682 | |
683 timestamp = | |
684 g_strdup_printf("%s %c%02d%02d", purple_time_format(now), | |
685 jbr->tz_off < 0 ? '-' : '+', | |
686 abs(jbr->tz_off / (60*60)), | |
687 abs((jbr->tz_off % (60*60)) / 60)); | |
688 purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); | |
689 g_free(timestamp); | |
690 } | |
691 | |
692 if (jbir && jbir->idle_seconds > 0) { | |
693 char *idle = purple_str_seconds_to_string(jbir->idle_seconds); | |
694 purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle); | |
695 g_free(idle); | |
696 } | |
697 | |
698 if (jbr) { | |
699 char *purdy = NULL; | |
700 char *tmp; | |
701 char priority[12]; | |
702 const char *status_name = jabber_buddy_state_get_name(jbr->state); | |
703 | |
704 if (jbr->status) { | |
705 purdy = purple_strdup_withhtml(jbr->status); | |
706 | |
707 if (purple_strequal(status_name, purdy)) | |
708 status_name = NULL; | |
709 } | |
710 | |
711 tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""), | |
712 ((status_name && purdy) ? ": " : ""), | |
713 (purdy ? purdy : "")); | |
714 purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp); | |
715 | |
716 g_snprintf(priority, sizeof(priority), "%d", jbr->priority); | |
717 purple_notify_user_info_prepend_pair(user_info, _("Priority"), priority); | |
718 | |
719 g_free(tmp); | |
720 g_free(purdy); | |
721 } else { | |
722 purple_notify_user_info_prepend_pair(user_info, _("Status"), _("Unknown")); | |
723 } | |
724 } | |
725 | |
653 static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi) | 726 static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi) |
654 { | 727 { |
655 char *resource_name, *tmp; | 728 char *resource_name; |
656 JabberBuddyResource *jbr; | 729 JabberBuddyResource *jbr; |
657 JabberBuddyInfoResource *jbir = NULL; | |
658 GList *resources; | 730 GList *resources; |
659 PurpleNotifyUserInfo *user_info; | 731 PurpleNotifyUserInfo *user_info; |
660 | 732 |
661 /* not yet */ | 733 /* not yet */ |
662 if(jbi->ids) | 734 if (jbi->ids) |
663 return; | 735 return; |
664 | 736 |
665 user_info = jbi->user_info; | 737 user_info = jbi->user_info; |
666 resource_name = jabber_get_resource(jbi->jid); | 738 resource_name = jabber_get_resource(jbi->jid); |
667 | 739 |
668 /* If we have one or more pairs from the vcard, put a section break above it */ | 740 /* If we have one or more pairs from the vcard, put a section break above it */ |
669 if (purple_notify_user_info_get_entries(user_info)) | 741 if (purple_notify_user_info_get_entries(user_info)) |
670 purple_notify_user_info_prepend_section_break(user_info); | 742 purple_notify_user_info_prepend_section_break(user_info); |
671 | 743 |
672 /* Prepend the primary buddy info to user_info so that it goes before the vcard. */ | 744 /* Add the information about the user's resource(s) */ |
673 if(resource_name) { | 745 if (resource_name) { |
674 jbr = jabber_buddy_find_resource(jbi->jb, resource_name); | 746 jbr = jabber_buddy_find_resource(jbi->jb, resource_name); |
675 jbir = g_hash_table_lookup(jbi->resources, resource_name); | 747 add_jbr_info(jbi, resource_name, jbr); |
676 if(jbr && jbr->client.name) { | |
677 tmp = g_strdup_printf("%s%s%s", jbr->client.name, | |
678 (jbr->client.version ? " " : ""), | |
679 (jbr->client.version ? jbr->client.version : "")); | |
680 purple_notify_user_info_add_pair(user_info, _("Client"), tmp); | |
681 g_free(tmp); | |
682 | |
683 if(jbr->client.os) { | |
684 purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os); | |
685 } | |
686 } | |
687 if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) { | |
688 time_t now_t; | |
689 struct tm *now; | |
690 char *timestamp; | |
691 time(&now_t); | |
692 now_t += jbr->tz_off; | |
693 now = gmtime(&now_t); | |
694 | |
695 timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now), | |
696 jbr->tz_off < 0 ? '-' : '+', | |
697 abs(jbr->tz_off / (60*60)), | |
698 abs((jbr->tz_off % (60*60)) / 60)); | |
699 purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); | |
700 g_free(timestamp); | |
701 } | |
702 if(jbir) { | |
703 if(jbir->idle_seconds > 0) { | |
704 char *idle = purple_str_seconds_to_string(jbir->idle_seconds); | |
705 purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle); | |
706 g_free(idle); | |
707 } | |
708 } | |
709 if(jbr) { | |
710 char *purdy = NULL; | |
711 const char *status_name = jabber_buddy_state_get_name(jbr->state); | |
712 if(jbr->status) | |
713 purdy = purple_strdup_withhtml(jbr->status); | |
714 if(status_name && purdy && !strcmp(status_name, purdy)) | |
715 status_name = NULL; | |
716 | |
717 tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""), | |
718 ((status_name && purdy) ? ": " : ""), | |
719 (purdy ? purdy : "")); | |
720 purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp); | |
721 g_free(tmp); | |
722 g_free(purdy); | |
723 } else { | |
724 purple_notify_user_info_prepend_pair(user_info, _("Status"), _("Unknown")); | |
725 } | |
726 #if 0 | |
727 /* #if 0 this for now; I think this would be far more useful if we limited this to a particular set of features | |
728 * of particular interest (-vv jumps out as one). As it is now, I don't picture people getting all excited: "Oh sweet crap! | |
729 * So-and-so supports 'jabber:x:data' AND 'Collaborative Data Objects'!" | |
730 */ | |
731 | |
732 if(jbr && jbr->caps) { | |
733 GString *tmp = g_string_new(""); | |
734 GList *iter; | |
735 for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) { | |
736 const char *feature = iter->data; | |
737 | |
738 if(!strcmp(feature, "jabber:iq:last")) | |
739 feature = _("Last Activity"); | |
740 else if(!strcmp(feature, "http://jabber.org/protocol/disco#info")) | |
741 feature = _("Service Discovery Info"); | |
742 else if(!strcmp(feature, "http://jabber.org/protocol/disco#items")) | |
743 feature = _("Service Discovery Items"); | |
744 else if(!strcmp(feature, "http://jabber.org/protocol/address")) | |
745 feature = _("Extended Stanza Addressing"); | |
746 else if(!strcmp(feature, "http://jabber.org/protocol/muc")) | |
747 feature = _("Multi-User Chat"); | |
748 else if(!strcmp(feature, "http://jabber.org/protocol/muc#user")) | |
749 feature = _("Multi-User Chat Extended Presence Information"); | |
750 else if(!strcmp(feature, "http://jabber.org/protocol/ibb")) | |
751 feature = _("In-Band Bytestreams"); | |
752 else if(!strcmp(feature, "http://jabber.org/protocol/commands")) | |
753 feature = _("Ad-Hoc Commands"); | |
754 else if(!strcmp(feature, "http://jabber.org/protocol/pubsub")) | |
755 feature = _("PubSub Service"); | |
756 else if(!strcmp(feature, "http://jabber.org/protocol/bytestreams")) | |
757 feature = _("SOCKS5 Bytestreams"); | |
758 else if(!strcmp(feature, "jabber:x:oob")) | |
759 feature = _("Out of Band Data"); | |
760 else if(!strcmp(feature, "http://jabber.org/protocol/xhtml-im")) | |
761 feature = _("XHTML-IM"); | |
762 else if(!strcmp(feature, "jabber:iq:register")) | |
763 feature = _("In-Band Registration"); | |
764 else if(!strcmp(feature, "http://jabber.org/protocol/geoloc")) | |
765 feature = _("User Location"); | |
766 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0084.html")) | |
767 feature = _("User Avatar"); | |
768 else if(!strcmp(feature, "http://jabber.org/protocol/chatstates")) | |
769 feature = _("Chat State Notifications"); | |
770 else if(!strcmp(feature, "jabber:iq:version")) | |
771 feature = _("Software Version"); | |
772 else if(!strcmp(feature, "http://jabber.org/protocol/si")) | |
773 feature = _("Stream Initiation"); | |
774 else if(!strcmp(feature, "http://jabber.org/protocol/si/profile/file-transfer")) | |
775 feature = _("File Transfer"); | |
776 else if(!strcmp(feature, "http://jabber.org/protocol/mood")) | |
777 feature = _("User Mood"); | |
778 else if(!strcmp(feature, "http://jabber.org/protocol/activity")) | |
779 feature = _("User Activity"); | |
780 else if(!strcmp(feature, "http://jabber.org/protocol/caps")) | |
781 feature = _("Entity Capabilities"); | |
782 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html")) | |
783 feature = _("Encrypted Session Negotiations"); | |
784 else if(!strcmp(feature, "http://jabber.org/protocol/tune")) | |
785 feature = _("User Tune"); | |
786 else if(!strcmp(feature, "http://jabber.org/protocol/rosterx")) | |
787 feature = _("Roster Item Exchange"); | |
788 else if(!strcmp(feature, "http://jabber.org/protocol/reach")) | |
789 feature = _("Reachability Address"); | |
790 else if(!strcmp(feature, "http://jabber.org/protocol/profile")) | |
791 feature = _("User Profile"); | |
792 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0166.html#ns")) | |
793 feature = _("Jingle"); | |
794 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0167.html#ns")) | |
795 feature = _("Jingle Audio"); | |
796 else if(!strcmp(feature, "http://jabber.org/protocol/nick")) | |
797 feature = _("User Nickname"); | |
798 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-udp")) | |
799 feature = _("Jingle ICE UDP"); | |
800 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-tcp")) | |
801 feature = _("Jingle ICE TCP"); | |
802 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0177.html#ns")) | |
803 feature = _("Jingle Raw UDP"); | |
804 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0180.html#ns")) | |
805 feature = _("Jingle Video"); | |
806 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0181.html#ns")) | |
807 feature = _("Jingle DTMF"); | |
808 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0184.html#ns")) | |
809 feature = _("Message Receipts"); | |
810 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0189.html#ns")) | |
811 feature = _("Public Key Publishing"); | |
812 else if(!strcmp(feature, "http://jabber.org/protocol/chatting")) | |
813 feature = _("User Chatting"); | |
814 else if(!strcmp(feature, "http://jabber.org/protocol/browsing")) | |
815 feature = _("User Browsing"); | |
816 else if(!strcmp(feature, "http://jabber.org/protocol/gaming")) | |
817 feature = _("User Gaming"); | |
818 else if(!strcmp(feature, "http://jabber.org/protocol/viewing")) | |
819 feature = _("User Viewing"); | |
820 else if(!strcmp(feature, "urn:xmpp:ping")) | |
821 feature = _("Ping"); | |
822 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns")) | |
823 feature = _("Stanza Encryption"); | |
824 else if(!strcmp(feature, "urn:xmpp:time")) | |
825 feature = _("Entity Time"); | |
826 else if(!strcmp(feature, "urn:xmpp:delay")) | |
827 feature = _("Delayed Delivery"); | |
828 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0204.html#ns")) | |
829 feature = _("Collaborative Data Objects"); | |
830 else if(!strcmp(feature, "http://jabber.org/protocol/fileshare")) | |
831 feature = _("File Repository and Sharing"); | |
832 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0215.html#ns")) | |
833 feature = _("STUN Service Discovery for Jingle"); | |
834 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html#ns")) | |
835 feature = _("Simplified Encrypted Session Negotiation"); | |
836 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0219.html#ns")) | |
837 feature = _("Hop Check"); | |
838 else if(g_str_has_suffix(feature, "+notify")) | |
839 feature = NULL; | |
840 if(feature) | |
841 g_string_append_printf(tmp, "%s<br/>", feature); | |
842 } | |
843 | |
844 if(strlen(tmp->str) > 0) | |
845 purple_notify_user_info_prepend_pair(user_info, _("Capabilities"), tmp->str); | |
846 | |
847 g_string_free(tmp, TRUE); | |
848 } | |
849 #endif | |
850 } else { | 748 } else { |
851 gboolean multiple_resources = jbi->jb->resources && jbi->jb->resources->next; | 749 for (resources = jbi->jb->resources; resources; resources = resources->next) { |
852 | |
853 for(resources = jbi->jb->resources; resources; resources = resources->next) { | |
854 char *purdy = NULL; | |
855 const char *status_name = NULL; | |
856 | |
857 jbr = resources->data; | 750 jbr = resources->data; |
858 | 751 |
859 /* put a section break between resources, this is not needed if | 752 /* put a section break between resources, this is not needed if |
860 we are at the first, because one was already added for the vcard | 753 we are at the first, because one was already added for the vcard |
861 section */ | 754 section */ |
862 if (resources != jbi->jb->resources) { | 755 if (resources != jbi->jb->resources) |
863 purple_notify_user_info_prepend_section_break(user_info); | 756 purple_notify_user_info_prepend_section_break(user_info); |
864 } | 757 |
865 | 758 add_jbr_info(jbi, jbr->name, jbr); |
866 if(jbr->client.name) { | 759 |
867 tmp = g_strdup_printf("%s%s%s", jbr->client.name, | 760 if (jbr->name) |
868 (jbr->client.version ? " " : ""), | |
869 (jbr->client.version ? jbr->client.version : "")); | |
870 purple_notify_user_info_prepend_pair(user_info, | |
871 _("Client"), tmp); | |
872 g_free(tmp); | |
873 | |
874 if(jbr->client.os) { | |
875 purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os); | |
876 } | |
877 } | |
878 | |
879 if (jbr->tz_off != PURPLE_NO_TZ_OFF) { | |
880 time_t now_t; | |
881 struct tm *now; | |
882 char *timestamp; | |
883 time(&now_t); | |
884 now_t += jbr->tz_off; | |
885 now = gmtime(&now_t); | |
886 | |
887 timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now), | |
888 jbr->tz_off < 0 ? '-' : '+', | |
889 abs(jbr->tz_off / (60*60)), | |
890 abs((jbr->tz_off % (60*60)) / 60)); | |
891 purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); | |
892 g_free(timestamp); | |
893 } | |
894 | |
895 if(jbr->name && (jbir = g_hash_table_lookup(jbi->resources, jbr->name))) { | |
896 if(jbir->idle_seconds > 0) { | |
897 char *idle = purple_str_seconds_to_string(jbir->idle_seconds); | |
898 purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle); | |
899 g_free(idle); | |
900 } | |
901 } | |
902 | |
903 status_name = jabber_buddy_state_get_name(jbr->state); | |
904 if(jbr->status) | |
905 purdy = purple_strdup_withhtml(jbr->status); | |
906 if(status_name && purdy && !strcmp(status_name, purdy)) | |
907 status_name = NULL; | |
908 | |
909 tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""), | |
910 ((status_name && purdy) ? ": " : ""), | |
911 (purdy ? purdy : "")); | |
912 purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp); | |
913 g_free(tmp); | |
914 g_free(purdy); | |
915 | |
916 if(multiple_resources) { | |
917 tmp = g_strdup_printf("%d", jbr->priority); | |
918 purple_notify_user_info_prepend_pair(user_info, _("Priority"), tmp); | |
919 g_free(tmp); | |
920 } | |
921 | |
922 if(jbr->name) | |
923 purple_notify_user_info_prepend_pair(user_info, _("Resource"), jbr->name); | 761 purple_notify_user_info_prepend_pair(user_info, _("Resource"), jbr->name); |
924 #if 0 | |
925 if(jbr && jbr->caps) { | |
926 GString *tmp = g_string_new(""); | |
927 GList *iter; | |
928 for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) { | |
929 const char *feature = iter->data; | |
930 | |
931 if(!strcmp(feature, "jabber:iq:last")) | |
932 feature = _("Last Activity"); | |
933 else if(!strcmp(feature, "http://jabber.org/protocol/disco#info")) | |
934 feature = _("Service Discovery Info"); | |
935 else if(!strcmp(feature, "http://jabber.org/protocol/disco#items")) | |
936 feature = _("Service Discovery Items"); | |
937 else if(!strcmp(feature, "http://jabber.org/protocol/address")) | |
938 feature = _("Extended Stanza Addressing"); | |
939 else if(!strcmp(feature, "http://jabber.org/protocol/muc")) | |
940 feature = _("Multi-User Chat"); | |
941 else if(!strcmp(feature, "http://jabber.org/protocol/muc#user")) | |
942 feature = _("Multi-User Chat Extended Presence Information"); | |
943 else if(!strcmp(feature, "http://jabber.org/protocol/ibb")) | |
944 feature = _("In-Band Bytestreams"); | |
945 else if(!strcmp(feature, "http://jabber.org/protocol/commands")) | |
946 feature = _("Ad-Hoc Commands"); | |
947 else if(!strcmp(feature, "http://jabber.org/protocol/pubsub")) | |
948 feature = _("PubSub Service"); | |
949 else if(!strcmp(feature, "http://jabber.org/protocol/bytestreams")) | |
950 feature = _("SOCKS5 Bytestreams"); | |
951 else if(!strcmp(feature, "jabber:x:oob")) | |
952 feature = _("Out of Band Data"); | |
953 else if(!strcmp(feature, "http://jabber.org/protocol/xhtml-im")) | |
954 feature = _("XHTML-IM"); | |
955 else if(!strcmp(feature, "jabber:iq:register")) | |
956 feature = _("In-Band Registration"); | |
957 else if(!strcmp(feature, "http://jabber.org/protocol/geoloc")) | |
958 feature = _("User Location"); | |
959 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0084.html")) | |
960 feature = _("User Avatar"); | |
961 else if(!strcmp(feature, "http://jabber.org/protocol/chatstates")) | |
962 feature = _("Chat State Notifications"); | |
963 else if(!strcmp(feature, "jabber:iq:version")) | |
964 feature = _("Software Version"); | |
965 else if(!strcmp(feature, "http://jabber.org/protocol/si")) | |
966 feature = _("Stream Initiation"); | |
967 else if(!strcmp(feature, "http://jabber.org/protocol/si/profile/file-transfer")) | |
968 feature = _("File Transfer"); | |
969 else if(!strcmp(feature, "http://jabber.org/protocol/mood")) | |
970 feature = _("User Mood"); | |
971 else if(!strcmp(feature, "http://jabber.org/protocol/activity")) | |
972 feature = _("User Activity"); | |
973 else if(!strcmp(feature, "http://jabber.org/protocol/caps")) | |
974 feature = _("Entity Capabilities"); | |
975 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html")) | |
976 feature = _("Encrypted Session Negotiations"); | |
977 else if(!strcmp(feature, "http://jabber.org/protocol/tune")) | |
978 feature = _("User Tune"); | |
979 else if(!strcmp(feature, "http://jabber.org/protocol/rosterx")) | |
980 feature = _("Roster Item Exchange"); | |
981 else if(!strcmp(feature, "http://jabber.org/protocol/reach")) | |
982 feature = _("Reachability Address"); | |
983 else if(!strcmp(feature, "http://jabber.org/protocol/profile")) | |
984 feature = _("User Profile"); | |
985 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0166.html#ns")) | |
986 feature = _("Jingle"); | |
987 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0167.html#ns")) | |
988 feature = _("Jingle Audio"); | |
989 else if(!strcmp(feature, "http://jabber.org/protocol/nick")) | |
990 feature = _("User Nickname"); | |
991 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-udp")) | |
992 feature = _("Jingle ICE UDP"); | |
993 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-tcp")) | |
994 feature = _("Jingle ICE TCP"); | |
995 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0177.html#ns")) | |
996 feature = _("Jingle Raw UDP"); | |
997 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0180.html#ns")) | |
998 feature = _("Jingle Video"); | |
999 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0181.html#ns")) | |
1000 feature = _("Jingle DTMF"); | |
1001 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0184.html#ns")) | |
1002 feature = _("Message Receipts"); | |
1003 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0189.html#ns")) | |
1004 feature = _("Public Key Publishing"); | |
1005 else if(!strcmp(feature, "http://jabber.org/protocol/chatting")) | |
1006 feature = _("User Chatting"); | |
1007 else if(!strcmp(feature, "http://jabber.org/protocol/browsing")) | |
1008 feature = _("User Browsing"); | |
1009 else if(!strcmp(feature, "http://jabber.org/protocol/gaming")) | |
1010 feature = _("User Gaming"); | |
1011 else if(!strcmp(feature, "http://jabber.org/protocol/viewing")) | |
1012 feature = _("User Viewing"); | |
1013 else if(!strcmp(feature, "urn:xmpp:ping")) | |
1014 feature = _("Ping"); | |
1015 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns")) | |
1016 feature = _("Stanza Encryption"); | |
1017 else if(!strcmp(feature, "urn:xmpp:time")) | |
1018 feature = _("Entity Time"); | |
1019 else if(!strcmp(feature, "urn:xmpp:delay")) | |
1020 feature = _("Delayed Delivery"); | |
1021 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0204.html#ns")) | |
1022 feature = _("Collaborative Data Objects"); | |
1023 else if(!strcmp(feature, "http://jabber.org/protocol/fileshare")) | |
1024 feature = _("File Repository and Sharing"); | |
1025 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0215.html#ns")) | |
1026 feature = _("STUN Service Discovery for Jingle"); | |
1027 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html#ns")) | |
1028 feature = _("Simplified Encrypted Session Negotiation"); | |
1029 else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0219.html#ns")) | |
1030 feature = _("Hop Check"); | |
1031 else if(g_str_has_suffix(feature, "+notify")) | |
1032 feature = NULL; | |
1033 | |
1034 if(feature) | |
1035 g_string_append_printf(tmp, "%s\n", feature); | |
1036 } | |
1037 if(strlen(tmp->str) > 0) | |
1038 purple_notify_user_info_prepend_pair(user_info, _("Capabilities"), tmp->str); | |
1039 | |
1040 g_string_free(tmp, TRUE); | |
1041 } | |
1042 #endif | |
1043 } | 762 } |
1044 } | 763 } |
1045 | 764 |
1046 if (!jbi->jb->resources) { | 765 if (!jbi->jb->resources) { |
1047 /* the buddy is offline */ | 766 /* the buddy is offline */ |
1048 gchar *status = | 767 gchar *status = |
1049 g_strdup_printf("%s%s%s", _("Offline"), | 768 g_strdup_printf("%s%s%s", _("Offline"), |
1050 jbi->last_message ? ": " : "", | 769 jbi->last_message ? ": " : "", |
1051 jbi->last_message ? jbi->last_message : ""); | 770 jbi->last_message ? jbi->last_message : ""); |
1052 if (jbi->last_seconds > 0) { | 771 if (jbi->last_seconds > 0) { |
1053 char *last = purple_str_seconds_to_string(jbi->last_seconds); | 772 char *last = purple_str_seconds_to_string(jbi->last_seconds); |
1054 gchar *message = g_strdup_printf(_("%s ago"), last); | 773 gchar *message = g_strdup_printf(_("%s ago"), last); |
1055 purple_notify_user_info_prepend_pair(user_info, | 774 purple_notify_user_info_prepend_pair(user_info, |
1056 _("Logged off"), message); | 775 _("Logged Off"), message); |
1057 g_free(last); | 776 g_free(last); |
1058 g_free(message); | 777 g_free(message); |
1059 } | 778 } |
1060 purple_notify_user_info_prepend_pair(user_info, _("Status"), status); | 779 purple_notify_user_info_prepend_pair(user_info, _("Status"), status); |
1061 g_free(status); | 780 g_free(status); |
1063 | 782 |
1064 g_free(resource_name); | 783 g_free(resource_name); |
1065 | 784 |
1066 purple_notify_userinfo(jbi->js->gc, jbi->jid, user_info, NULL, NULL); | 785 purple_notify_userinfo(jbi->js->gc, jbi->jid, user_info, NULL, NULL); |
1067 | 786 |
1068 while(jbi->vcard_imgids) { | 787 while (jbi->vcard_imgids) { |
1069 purple_imgstore_unref_by_id(GPOINTER_TO_INT(jbi->vcard_imgids->data)); | 788 purple_imgstore_unref_by_id(GPOINTER_TO_INT(jbi->vcard_imgids->data)); |
1070 jbi->vcard_imgids = g_slist_delete_link(jbi->vcard_imgids, jbi->vcard_imgids); | 789 jbi->vcard_imgids = g_slist_delete_link(jbi->vcard_imgids, jbi->vcard_imgids); |
1071 } | 790 } |
1072 | 791 |
1073 jbi->js->pending_buddy_info_requests = g_slist_remove(jbi->js->pending_buddy_info_requests, jbi); | 792 jbi->js->pending_buddy_info_requests = g_slist_remove(jbi->js->pending_buddy_info_requests, jbi); |
1100 { | 819 { |
1101 xmlnode *vcard, *photo, *binval; | 820 xmlnode *vcard, *photo, *binval; |
1102 char *txt, *vcard_hash = NULL; | 821 char *txt, *vcard_hash = NULL; |
1103 | 822 |
1104 if (type == JABBER_IQ_ERROR) { | 823 if (type == JABBER_IQ_ERROR) { |
1105 purple_debug_warning("jabber", "Server returned error while retrieving vCard"); | 824 xmlnode *error; |
1106 return; | 825 purple_debug_warning("jabber", "Server returned error while retrieving vCard\n"); |
826 | |
827 error = xmlnode_get_child(packet, "error"); | |
828 if (!error || !xmlnode_get_child(error, "item-not-found")) | |
829 return; | |
1107 } | 830 } |
1108 | 831 |
1109 if((vcard = xmlnode_get_child(packet, "vCard")) || | 832 if((vcard = xmlnode_get_child(packet, "vCard")) || |
1110 (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) | 833 (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) |
1111 { | 834 { |
1654 } | 1377 } |
1655 | 1378 |
1656 return FALSE; | 1379 return FALSE; |
1657 } | 1380 } |
1658 | 1381 |
1382 static void | |
1383 dispatch_queries_for_resource(JabberStream *js, JabberBuddyInfo *jbi, | |
1384 gboolean is_bare_jid, const char *jid, | |
1385 JabberBuddyResource *jbr) | |
1386 { | |
1387 JabberIq *iq; | |
1388 JabberBuddyInfoResource *jbir; | |
1389 char *full_jid = NULL; | |
1390 const char *to; | |
1391 | |
1392 g_return_if_fail(jbr->name != NULL); | |
1393 | |
1394 if (is_bare_jid) { | |
1395 full_jid = g_strdup_printf("%s/%s", jid, jbr->name); | |
1396 to = full_jid; | |
1397 } else | |
1398 to = jid; | |
1399 | |
1400 jbir = g_new0(JabberBuddyInfoResource, 1); | |
1401 g_hash_table_insert(jbi->resources, g_strdup(jbr->name), jbir); | |
1402 | |
1403 if(!jbr->client.name) { | |
1404 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:version"); | |
1405 xmlnode_set_attrib(iq->node, "to", to); | |
1406 jabber_iq_set_callback(iq, jabber_version_parse, jbi); | |
1407 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | |
1408 jabber_iq_send(iq); | |
1409 } | |
1410 | |
1411 /* this is to fix the feeling of irritation I get when trying | |
1412 * to get info on a friend running Trillian, which doesn't | |
1413 * respond (with an error or otherwise) to jabber:iq:last | |
1414 * requests. There are a number of Trillian users in my | |
1415 * office. */ | |
1416 if(!_client_is_blacklisted(jbr, "jabber:iq:last")) { | |
1417 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:last"); | |
1418 xmlnode_set_attrib(iq->node, "to", to); | |
1419 jabber_iq_set_callback(iq, jabber_last_parse, jbi); | |
1420 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | |
1421 jabber_iq_send(iq); | |
1422 } | |
1423 | |
1424 if (jbr->tz_off == PURPLE_NO_TZ_OFF && | |
1425 (!jbr->caps.info || | |
1426 jabber_resource_has_capability(jbr, "urn:xmpp:time"))) { | |
1427 xmlnode *child; | |
1428 iq = jabber_iq_new(js, JABBER_IQ_GET); | |
1429 xmlnode_set_attrib(iq->node, "to", to); | |
1430 child = xmlnode_new_child(iq->node, "time"); | |
1431 xmlnode_set_namespace(child, "urn:xmpp:time"); | |
1432 jabber_iq_set_callback(iq, jabber_time_parse, jbi); | |
1433 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | |
1434 jabber_iq_send(iq); | |
1435 } | |
1436 | |
1437 g_free(full_jid); | |
1438 } | |
1439 | |
1659 static void jabber_buddy_get_info_for_jid(JabberStream *js, const char *jid) | 1440 static void jabber_buddy_get_info_for_jid(JabberStream *js, const char *jid) |
1660 { | 1441 { |
1661 JabberIq *iq; | 1442 JabberIq *iq; |
1662 xmlnode *vcard; | 1443 xmlnode *vcard; |
1663 GList *resources; | 1444 GList *resources; |
1664 JabberBuddy *jb; | 1445 JabberBuddy *jb; |
1665 JabberBuddyInfo *jbi; | 1446 JabberBuddyInfo *jbi; |
1447 const char *slash; | |
1448 gboolean is_bare_jid; | |
1666 | 1449 |
1667 jb = jabber_buddy_find(js, jid, TRUE); | 1450 jb = jabber_buddy_find(js, jid, TRUE); |
1668 | 1451 |
1669 /* invalid JID */ | 1452 /* invalid JID */ |
1670 if(!jb) | 1453 if(!jb) |
1671 return; | 1454 return; |
1455 | |
1456 slash = strchr(jid, '/'); | |
1457 is_bare_jid = (slash == NULL); | |
1672 | 1458 |
1673 jbi = g_new0(JabberBuddyInfo, 1); | 1459 jbi = g_new0(JabberBuddyInfo, 1); |
1674 jbi->jid = g_strdup(jid); | 1460 jbi->jid = g_strdup(jid); |
1675 jbi->js = js; | 1461 jbi->js = js; |
1676 jbi->jb = jb; | 1462 jbi->jb = jb; |
1686 jabber_iq_set_callback(iq, jabber_vcard_parse, jbi); | 1472 jabber_iq_set_callback(iq, jabber_vcard_parse, jbi); |
1687 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | 1473 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); |
1688 | 1474 |
1689 jabber_iq_send(iq); | 1475 jabber_iq_send(iq); |
1690 | 1476 |
1691 for(resources = jb->resources; resources; resources = resources->next) | 1477 if (is_bare_jid) { |
1692 { | 1478 for(resources = jb->resources; resources; resources = resources->next) { |
1693 JabberBuddyResource *jbr = resources->data; | 1479 JabberBuddyResource *jbr = resources->data; |
1694 JabberBuddyInfoResource *jbir; | 1480 dispatch_queries_for_resource(js, jbi, is_bare_jid, jid, jbr); |
1695 char *full_jid; | 1481 } |
1696 | 1482 } else { |
1697 if ((strchr(jid, '/') == NULL) && (jbr->name != NULL)) { | 1483 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, slash + 1); |
1698 full_jid = g_strdup_printf("%s/%s", jid, jbr->name); | 1484 if (jbr) |
1699 } else { | 1485 dispatch_queries_for_resource(js, jbi, is_bare_jid, jid, jbr); |
1700 full_jid = g_strdup(jid); | 1486 else |
1701 } | 1487 purple_debug_warning("jabber", "jabber_buddy_get_info_for_jid() " |
1702 | 1488 "was passed JID %s, but there is no corresponding " |
1703 if (jbr->name != NULL) | 1489 "JabberBuddyResource!\n", jid); |
1704 { | 1490 } |
1705 jbir = g_new0(JabberBuddyInfoResource, 1); | 1491 |
1706 g_hash_table_insert(jbi->resources, g_strdup(jbr->name), jbir); | 1492 if (!jb->resources && is_bare_jid) { |
1707 } | |
1708 | |
1709 if(!jbr->client.name) { | |
1710 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:version"); | |
1711 xmlnode_set_attrib(iq->node, "to", full_jid); | |
1712 jabber_iq_set_callback(iq, jabber_version_parse, jbi); | |
1713 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | |
1714 jabber_iq_send(iq); | |
1715 } | |
1716 | |
1717 /* this is to fix the feeling of irritation I get when trying | |
1718 * to get info on a friend running Trillian, which doesn't | |
1719 * respond (with an error or otherwise) to jabber:iq:last | |
1720 * requests. There are a number of Trillian users in my | |
1721 * office. */ | |
1722 if(!_client_is_blacklisted(jbr, "jabber:iq:last")) { | |
1723 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:last"); | |
1724 xmlnode_set_attrib(iq->node, "to", full_jid); | |
1725 jabber_iq_set_callback(iq, jabber_last_parse, jbi); | |
1726 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | |
1727 jabber_iq_send(iq); | |
1728 } | |
1729 | |
1730 if (jbr->tz_off == PURPLE_NO_TZ_OFF && | |
1731 (!jbr->caps.info || | |
1732 jabber_resource_has_capability(jbr, "urn:xmpp:time"))) { | |
1733 xmlnode *child; | |
1734 iq = jabber_iq_new(js, JABBER_IQ_GET); | |
1735 xmlnode_set_attrib(iq->node, "to", full_jid); | |
1736 child = xmlnode_new_child(iq->node, "time"); | |
1737 xmlnode_set_namespace(child, "urn:xmpp:time"); | |
1738 jabber_iq_set_callback(iq, jabber_time_parse, jbi); | |
1739 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | |
1740 jabber_iq_send(iq); | |
1741 } | |
1742 | |
1743 g_free(full_jid); | |
1744 } | |
1745 | |
1746 if (!jb->resources && strchr(jid, '/') == NULL) { | |
1747 /* user is offline, send a jabber:iq:last to find out last time online */ | 1493 /* user is offline, send a jabber:iq:last to find out last time online */ |
1748 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:last"); | 1494 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:last"); |
1749 xmlnode_set_attrib(iq->node, "to", jid); | 1495 xmlnode_set_attrib(iq->node, "to", jid); |
1750 jabber_iq_set_callback(iq, jabber_last_offline_parse, jbi); | 1496 jabber_iq_set_callback(iq, jabber_last_offline_parse, jbi); |
1751 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); | 1497 jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); |
2072 return JABBER_BUDDY_STATE_ERROR; | 1818 return JABBER_BUDDY_STATE_ERROR; |
2073 | 1819 |
2074 return JABBER_BUDDY_STATE_UNKNOWN; | 1820 return JABBER_BUDDY_STATE_UNKNOWN; |
2075 } | 1821 } |
2076 | 1822 |
2077 JabberBuddyState jabber_buddy_show_get_state(const char *id) { | 1823 const struct { |
2078 if(!id) | 1824 const char *name; |
2079 return JABBER_BUDDY_STATE_UNKNOWN; | 1825 JabberBuddyState state; |
2080 if(!strcmp(id, "available")) | 1826 } show_state_pairs[] = { |
2081 return JABBER_BUDDY_STATE_ONLINE; | 1827 { "available", JABBER_BUDDY_STATE_ONLINE }, |
2082 if(!strcmp(id, "chat")) | 1828 { "chat", JABBER_BUDDY_STATE_CHAT }, |
2083 return JABBER_BUDDY_STATE_CHAT; | 1829 { "away", JABBER_BUDDY_STATE_AWAY }, |
2084 if(!strcmp(id, "away")) | 1830 { "xa", JABBER_BUDDY_STATE_XA }, |
2085 return JABBER_BUDDY_STATE_AWAY; | 1831 { "dnd", JABBER_BUDDY_STATE_DND }, |
2086 if(!strcmp(id, "xa")) | 1832 { "offline", JABBER_BUDDY_STATE_UNAVAILABLE }, |
2087 return JABBER_BUDDY_STATE_XA; | 1833 { "error", JABBER_BUDDY_STATE_ERROR }, |
2088 if(!strcmp(id, "dnd")) | 1834 { NULL, JABBER_BUDDY_STATE_UNKNOWN } |
2089 return JABBER_BUDDY_STATE_DND; | 1835 }; |
2090 if(!strcmp(id, "offline")) | 1836 |
2091 return JABBER_BUDDY_STATE_UNAVAILABLE; | 1837 JabberBuddyState jabber_buddy_show_get_state(const char *id) |
2092 if(!strcmp(id, "error")) | 1838 { |
2093 return JABBER_BUDDY_STATE_ERROR; | 1839 int i; |
2094 | 1840 |
1841 g_return_val_if_fail(id != NULL, JABBER_BUDDY_STATE_UNKNOWN); | |
1842 | |
1843 for (i = 0; show_state_pairs[i].name; ++i) | |
1844 if (g_str_equal(id, show_state_pairs[i].name)) | |
1845 return show_state_pairs[i].state; | |
1846 | |
1847 purple_debug_warning("jabber", "Invalid value of presence <show/> " | |
1848 "attribute: %s\n", id); | |
2095 return JABBER_BUDDY_STATE_UNKNOWN; | 1849 return JABBER_BUDDY_STATE_UNKNOWN; |
2096 } | 1850 } |
2097 | 1851 |
2098 const char *jabber_buddy_state_get_show(JabberBuddyState state) { | 1852 const char * |
2099 switch(state) { | 1853 jabber_buddy_state_get_show(JabberBuddyState state) |
2100 case JABBER_BUDDY_STATE_CHAT: | 1854 { |
2101 return "chat"; | 1855 int i; |
2102 case JABBER_BUDDY_STATE_AWAY: | 1856 |
2103 return "away"; | 1857 for (i = 0; show_state_pairs[i].name; ++i) |
2104 case JABBER_BUDDY_STATE_XA: | 1858 if (state == show_state_pairs[i].state) |
2105 return "xa"; | 1859 return show_state_pairs[i].name; |
2106 case JABBER_BUDDY_STATE_DND: | 1860 |
2107 return "dnd"; | 1861 /* purple_debug_warning("jabber", "Unknown buddy state: %d\n", state); */ |
2108 case JABBER_BUDDY_STATE_ONLINE: | |
2109 return "available"; | |
2110 case JABBER_BUDDY_STATE_UNKNOWN: | |
2111 case JABBER_BUDDY_STATE_ERROR: | |
2112 return NULL; | |
2113 case JABBER_BUDDY_STATE_UNAVAILABLE: | |
2114 return "offline"; | |
2115 } | |
2116 return NULL; | 1862 return NULL; |
2117 } | 1863 } |
2118 | 1864 |
2119 const char *jabber_buddy_state_get_status_id(JabberBuddyState state) { | 1865 const char *jabber_buddy_state_get_status_id(JabberBuddyState state) { |
2120 switch(state) { | 1866 switch(state) { |
2478 { | 2224 { |
2479 const GList *node = NULL; | 2225 const GList *node = NULL; |
2480 const JabberCapsNodeExts *exts; | 2226 const JabberCapsNodeExts *exts; |
2481 | 2227 |
2482 if (!jbr->caps.info) { | 2228 if (!jbr->caps.info) { |
2483 purple_debug_error("jabber", | 2229 purple_debug_info("jabber", |
2484 "Unable to find caps: nothing known about buddy\n"); | 2230 "Unable to find caps: nothing known about buddy\n"); |
2485 return FALSE; | 2231 return FALSE; |
2486 } | 2232 } |
2487 | 2233 |
2488 node = g_list_find_custom(jbr->caps.info->features, cap, (GCompareFunc)strcmp); | 2234 node = g_list_find_custom(jbr->caps.info->features, cap, (GCompareFunc)strcmp); |
2496 if (features) | 2242 if (features) |
2497 node = g_list_find_custom(features, cap, (GCompareFunc)strcmp); | 2243 node = g_list_find_custom(features, cap, (GCompareFunc)strcmp); |
2498 } | 2244 } |
2499 } | 2245 } |
2500 | 2246 |
2501 /* TODO: Are these messages actually useful? */ | |
2502 if (node) | |
2503 purple_debug_info("jabber", "Found cap: %s\n", cap); | |
2504 else | |
2505 purple_debug_info("jabber", "Cap %s not found\n", cap); | |
2506 | |
2507 return (node != NULL); | 2247 return (node != NULL); |
2508 } | 2248 } |
2509 | 2249 |
2510 gboolean | 2250 gboolean |
2511 jabber_buddy_has_capability(const JabberBuddy *jb, const gchar *cap) | 2251 jabber_buddy_has_capability(const JabberBuddy *jb, const gchar *cap) |