Mercurial > pidgin.yaz
comparison libpurple/protocols/jabber/disco.c @ 26329:f5e613e05332
Applied disco-2.patch from nops with some modifications:
* Alphabetized includes and Makefiles
* Removed purple_disco_set_ui_ops(NULL) in finch; ops is NULL by default.
* A few string changes
* Removed DISCO_PREF_LAST_SERVER. Default to our server, but store
the last requested in the JabberStream* and use it if available.
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sun, 29 Mar 2009 19:29:22 +0000 |
parents | 5f9a24d1c25e |
children | f19c214201db |
comparison
equal
deleted
inserted
replaced
26328:c422c7b1bde7 | 26329:f5e613e05332 |
---|---|
1 /* | 1 /* |
2 * purple - Jabber Protocol Plugin | 2 * purple - Jabber Service Discovery |
3 * | 3 * |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | 4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> |
5 * | 5 * |
6 * This program is free software; you can redistribute it and/or modify | 6 * This program is free software; you can redistribute it and/or modify |
7 * it under the terms of the GNU General Public License as published by | 7 * it under the terms of the GNU General Public License as published by |
20 */ | 20 */ |
21 | 21 |
22 #include "internal.h" | 22 #include "internal.h" |
23 #include "prefs.h" | 23 #include "prefs.h" |
24 #include "debug.h" | 24 #include "debug.h" |
25 #include "request.h" | |
26 #include "notify.h" | |
25 | 27 |
26 #include "buddy.h" | 28 #include "buddy.h" |
27 #include "google.h" | 29 #include "google.h" |
28 #include "iq.h" | 30 #include "iq.h" |
29 #include "disco.h" | 31 #include "disco.h" |
30 #include "jabber.h" | 32 #include "jabber.h" |
31 #include "presence.h" | 33 #include "presence.h" |
32 #include "roster.h" | 34 #include "roster.h" |
33 #include "pep.h" | 35 #include "pep.h" |
34 #include "adhoccommands.h" | 36 #include "adhoccommands.h" |
35 | 37 #include "xdata.h" |
38 #include "libpurple/disco.h" | |
36 | 39 |
37 struct _jabber_disco_info_cb_data { | 40 struct _jabber_disco_info_cb_data { |
38 gpointer data; | 41 gpointer data; |
39 JabberDiscoInfoCallback *callback; | 42 JabberDiscoInfoCallback *callback; |
40 }; | 43 }; |
266 capabilities |= JABBER_CAP_IQ_SEARCH; | 269 capabilities |= JABBER_CAP_IQ_SEARCH; |
267 else if(!strcmp(var, "jabber:iq:register")) | 270 else if(!strcmp(var, "jabber:iq:register")) |
268 capabilities |= JABBER_CAP_IQ_REGISTER; | 271 capabilities |= JABBER_CAP_IQ_REGISTER; |
269 else if(!strcmp(var, "http://www.xmpp.org/extensions/xep-0199.html#ns")) | 272 else if(!strcmp(var, "http://www.xmpp.org/extensions/xep-0199.html#ns")) |
270 capabilities |= JABBER_CAP_PING; | 273 capabilities |= JABBER_CAP_PING; |
274 else if(!strcmp(var, "http://jabber.org/protocol/disco#items")) | |
275 capabilities |= JABBER_CAP_ITEMS; | |
271 else if(!strcmp(var, "http://jabber.org/protocol/commands")) { | 276 else if(!strcmp(var, "http://jabber.org/protocol/commands")) { |
272 capabilities |= JABBER_CAP_ADHOC; | 277 capabilities |= JABBER_CAP_ADHOC; |
273 } | 278 } |
274 else if(!strcmp(var, "http://jabber.org/protocol/ibb")) { | 279 else if(!strcmp(var, "http://jabber.org/protocol/ibb")) { |
275 purple_debug_info("jabber", "remote supports IBB\n"); | 280 purple_debug_info("jabber", "remote supports IBB\n"); |
309 jdicd->callback(js, from, capabilities, jdicd->data); | 314 jdicd->callback(js, from, capabilities, jdicd->data); |
310 g_hash_table_remove(js->disco_callbacks, from); | 315 g_hash_table_remove(js->disco_callbacks, from); |
311 } | 316 } |
312 } | 317 } |
313 | 318 |
314 void jabber_disco_items_parse(JabberStream *js, xmlnode *packet) { | 319 void jabber_disco_items_parse(JabberStream *js, xmlnode *packet) |
320 { | |
315 const char *from = xmlnode_get_attrib(packet, "from"); | 321 const char *from = xmlnode_get_attrib(packet, "from"); |
316 const char *type = xmlnode_get_attrib(packet, "type"); | 322 const char *type = xmlnode_get_attrib(packet, "type"); |
317 | 323 |
318 if(type && !strcmp(type, "get")) { | 324 if(type && !strcmp(type, "get")) { |
319 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, | 325 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, |
393 | 399 |
394 g_strfreev(ft_proxy_list); | 400 g_strfreev(ft_proxy_list); |
395 } | 401 } |
396 | 402 |
397 } | 403 } |
404 | |
405 struct _disco_data { | |
406 PurpleDiscoList *list; | |
407 PurpleDiscoService *parent; | |
408 char *node; | |
409 }; | |
398 | 410 |
399 static void | 411 static void |
400 jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data) | 412 jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data) |
401 { | 413 { |
402 xmlnode *query, *child; | 414 xmlnode *query, *child; |
556 xmlnode_set_attrib(iq->node, "to", who); | 568 xmlnode_set_attrib(iq->node, "to", who); |
557 | 569 |
558 jabber_iq_send(iq); | 570 jabber_iq_send(iq); |
559 } | 571 } |
560 | 572 |
561 | 573 static PurpleDiscoServiceCategory |
574 jabber_disco_category_from_string(const gchar *str) | |
575 { | |
576 if (!strcasecmp(str, "gateway")) | |
577 return PURPLE_DISCO_SERVICE_CAT_GATEWAY; | |
578 else if (!strcasecmp(str, "directory")) | |
579 return PURPLE_DISCO_SERVICE_CAT_DIRECTORY; | |
580 else if (!strcasecmp(str, "conference")) | |
581 return PURPLE_DISCO_SERVICE_CAT_MUC; | |
582 | |
583 return PURPLE_DISCO_SERVICE_CAT_NONE; | |
584 } | |
585 | |
586 static PurpleDiscoServiceType | |
587 jabber_disco_type_from_string(const gchar *str) | |
588 { | |
589 if (!strcasecmp(str, "xmpp")) | |
590 return PURPLE_DISCO_SERVICE_TYPE_XMPP; | |
591 else if (!strcasecmp(str, "icq")) | |
592 return PURPLE_DISCO_SERVICE_TYPE_ICQ; | |
593 else if (!strcasecmp(str, "mrim")) | |
594 return PURPLE_DISCO_SERVICE_TYPE_MAIL; | |
595 else if (!strcasecmp(str, "user")) | |
596 return PURPLE_DISCO_SERVICE_TYPE_USER; | |
597 else if (!strcasecmp(str, "yahoo")) | |
598 return PURPLE_DISCO_SERVICE_TYPE_YAHOO; | |
599 else if (!strcasecmp(str, "irc")) | |
600 return PURPLE_DISCO_SERVICE_TYPE_IRC; | |
601 else if (!strcasecmp(str, "gadu-gadu")) | |
602 return PURPLE_DISCO_SERVICE_TYPE_GG; | |
603 else if (!strcasecmp(str, "aim")) | |
604 return PURPLE_DISCO_SERVICE_TYPE_AIM; | |
605 else if (!strcasecmp(str, "qq")) | |
606 return PURPLE_DISCO_SERVICE_TYPE_QQ; | |
607 else if (!strcasecmp(str, "msn")) | |
608 return PURPLE_DISCO_SERVICE_TYPE_MSN; | |
609 | |
610 return PURPLE_DISCO_SERVICE_TYPE_NONE; | |
611 } | |
612 | |
613 static void | |
614 jabber_disco_service_info_cb(JabberStream *js, xmlnode *packet, gpointer data); | |
615 | |
616 static void | |
617 jabber_disco_service_items_cb(JabberStream *js, xmlnode *packet, gpointer data) | |
618 { | |
619 struct _disco_data *disco_data = data; | |
620 PurpleDiscoList *list = disco_data->list; | |
621 PurpleDiscoService *parent = disco_data->parent; | |
622 const char *parent_node = disco_data->node; | |
623 xmlnode *query = xmlnode_get_child(packet, "query"); | |
624 const char *from = xmlnode_get_attrib(packet, "from"); | |
625 const char *result = xmlnode_get_attrib(packet, "type"); | |
626 xmlnode *child; | |
627 gboolean has_items = FALSE; | |
628 | |
629 purple_disco_list_set_fetch_count(list, purple_disco_list_get_fetch_count(list) - 1); | |
630 | |
631 if (!from || !result || !query || (strcmp(result, "result") | |
632 || !purple_disco_list_get_proto_data(list))) { | |
633 if (!purple_disco_list_get_fetch_count(list)) | |
634 purple_disco_set_in_progress(list, FALSE); | |
635 | |
636 purple_disco_list_unref(list); | |
637 return; | |
638 } | |
639 | |
640 query = xmlnode_get_child(packet, "query"); | |
641 | |
642 for(child = xmlnode_get_child(query, "item"); child; | |
643 child = xmlnode_get_next_twin(child)) { | |
644 JabberIq *iq; | |
645 xmlnode *q; | |
646 const char *jid, *node; | |
647 struct _disco_data *disco_data; | |
648 char *full_node; | |
649 | |
650 if(!(jid = xmlnode_get_attrib(child, "jid")) || !purple_disco_list_get_proto_data(list)) | |
651 continue; | |
652 | |
653 node = xmlnode_get_attrib(child, "node"); | |
654 | |
655 if (parent_node) { | |
656 if (node) { | |
657 full_node = g_new0(char, strlen(parent_node) + 1 + strlen(node) + 1); | |
658 strcat(full_node, parent_node); | |
659 strcat(full_node, "/"); | |
660 strcat(full_node, node); | |
661 } else { | |
662 continue; | |
663 } | |
664 } else { | |
665 full_node = g_strdup(node); | |
666 } | |
667 | |
668 disco_data = g_new0(struct _disco_data, 1); | |
669 disco_data->list = list; | |
670 disco_data->parent = parent; | |
671 disco_data->node = full_node; | |
672 | |
673 has_items = TRUE; | |
674 purple_disco_list_set_fetch_count(list, purple_disco_list_get_fetch_count(list) + 1); | |
675 purple_disco_list_ref(list); | |
676 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); | |
677 xmlnode_set_attrib(iq->node, "to", jid); | |
678 if (full_node && (q = xmlnode_get_child(iq->node, "query"))) | |
679 xmlnode_set_attrib(q, "node", full_node); | |
680 jabber_iq_set_callback(iq, jabber_disco_service_info_cb, disco_data); | |
681 | |
682 jabber_iq_send(iq); | |
683 } | |
684 | |
685 if (!purple_disco_list_get_fetch_count(list)) | |
686 purple_disco_set_in_progress(list, FALSE); | |
687 purple_disco_list_unref(list); | |
688 | |
689 g_free(disco_data->node); | |
690 g_free(disco_data); | |
691 } | |
692 | |
693 static void | |
694 jabber_disco_service_info_cb(JabberStream *js, xmlnode *packet, gpointer data) | |
695 { | |
696 struct _disco_data *disco_data = data; | |
697 PurpleDiscoList *list = disco_data->list; | |
698 PurpleDiscoService *parent = disco_data->parent; | |
699 char *node = g_strdup(disco_data->node); | |
700 xmlnode *query, *ident, *child; | |
701 const char *from = xmlnode_get_attrib(packet, "from"); | |
702 const char *result = xmlnode_get_attrib(packet, "type"); | |
703 const char *acat, *atype, *adesc, *anode; | |
704 char *aname; | |
705 PurpleDiscoService *s; | |
706 PurpleDiscoServiceCategory cat; | |
707 PurpleDiscoServiceType type; | |
708 int flags = PURPLE_DISCO_FLAG_ADD; | |
709 | |
710 g_free(disco_data->node); | |
711 g_free(disco_data); | |
712 purple_disco_list_set_fetch_count(list, purple_disco_list_get_fetch_count(list) - 1); | |
713 | |
714 if (!from || !result || (strcmp(result, "result") || !purple_disco_list_get_proto_data(list)) | |
715 || (!(query = xmlnode_get_child(packet, "query"))) | |
716 || (!(ident = xmlnode_get_child(query, "identity")))) { | |
717 if (!purple_disco_list_get_fetch_count(list)) | |
718 purple_disco_set_in_progress(list, FALSE); | |
719 | |
720 purple_disco_list_unref(list); | |
721 return; | |
722 } | |
723 | |
724 acat = xmlnode_get_attrib(ident, "category"); | |
725 atype = xmlnode_get_attrib(ident, "type"); | |
726 adesc = xmlnode_get_attrib(ident, "name"); | |
727 anode = xmlnode_get_attrib(query, "node"); | |
728 | |
729 if (anode) { | |
730 aname = g_new0(char, strlen(from) + strlen(anode) + 1); | |
731 strcat(aname, from); | |
732 strcat(aname, anode); | |
733 } else { | |
734 aname = g_strdup(from); | |
735 } | |
736 | |
737 cat = jabber_disco_category_from_string(acat); | |
738 type = jabber_disco_type_from_string(atype); | |
739 | |
740 for (child = xmlnode_get_child(query, "feature"); child; | |
741 child = xmlnode_get_next_twin(child)) { | |
742 const char *var; | |
743 | |
744 if (!(var = xmlnode_get_attrib(child, "var"))) | |
745 continue; | |
746 | |
747 if (!strcmp(var, "jabber:iq:register")) | |
748 flags |= PURPLE_DISCO_FLAG_REGISTER; | |
749 | |
750 if (!strcmp(var, "http://jabber.org/protocol/disco#items")) | |
751 flags |= PURPLE_DISCO_FLAG_BROWSE; | |
752 | |
753 if (!strcmp(var, "http://jabber.org/protocol/muc")) | |
754 cat = PURPLE_DISCO_SERVICE_CAT_MUC; | |
755 } | |
756 | |
757 purple_debug_info("disco", "service %s, category %s (%d), type %s (%d), description %s, flags %04x\n", | |
758 aname, | |
759 acat, cat, | |
760 atype, type, | |
761 adesc, flags); | |
762 | |
763 s = purple_disco_list_service_new(cat, aname, type, adesc, flags); | |
764 purple_disco_list_service_add(list, s, parent); | |
765 | |
766 /* if (flags & PURPLE_DISCO_FLAG_BROWSE) - not all browsable services has this future */ | |
767 { | |
768 xmlnode *q; | |
769 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items"); | |
770 | |
771 purple_disco_list_set_fetch_count(list, purple_disco_list_get_fetch_count(list) + 1); | |
772 purple_disco_list_ref(list); | |
773 disco_data = g_new0(struct _disco_data, 1); | |
774 disco_data->list = list; | |
775 disco_data->parent = s; | |
776 | |
777 xmlnode_set_attrib(iq->node, "to", from); | |
778 jabber_iq_set_callback(iq, jabber_disco_service_items_cb, disco_data); | |
779 if (anode && (q = xmlnode_get_child(iq->node, "query"))) | |
780 xmlnode_set_attrib(q, "node", node); | |
781 jabber_iq_send(iq); | |
782 } | |
783 | |
784 if (!purple_disco_list_get_fetch_count(list)) | |
785 purple_disco_set_in_progress(list, FALSE); | |
786 | |
787 purple_disco_list_unref(list); | |
788 | |
789 g_free(aname); | |
790 g_free(node); | |
791 } | |
792 | |
793 static void | |
794 jabber_disco_server_items_cb(JabberStream *js, xmlnode *packet, gpointer data) | |
795 { | |
796 PurpleDiscoList *list = data; | |
797 xmlnode *query, *child; | |
798 const char *from = xmlnode_get_attrib(packet, "from"); | |
799 const char *type = xmlnode_get_attrib(packet, "type"); | |
800 gboolean has_items = FALSE; | |
801 | |
802 if (!from || !type) | |
803 return; | |
804 | |
805 if (strcmp(type, "result")) | |
806 return; | |
807 | |
808 query = xmlnode_get_child(packet, "query"); | |
809 | |
810 for(child = xmlnode_get_child(query, "item"); child; | |
811 child = xmlnode_get_next_twin(child)) { | |
812 JabberIq *iq; | |
813 const char *jid; | |
814 struct _disco_data *disco_data; | |
815 | |
816 if(!(jid = xmlnode_get_attrib(child, "jid")) || !purple_disco_list_get_proto_data(list)) | |
817 continue; | |
818 | |
819 disco_data = g_new0(struct _disco_data, 1); | |
820 disco_data->list = list; | |
821 | |
822 has_items = TRUE; | |
823 purple_disco_list_set_fetch_count(list, purple_disco_list_get_fetch_count(list) + 1); | |
824 purple_disco_list_ref(list); | |
825 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); | |
826 xmlnode_set_attrib(iq->node, "to", jid); | |
827 jabber_iq_set_callback(iq, jabber_disco_service_info_cb, disco_data); | |
828 | |
829 jabber_iq_send(iq); | |
830 } | |
831 | |
832 if (!has_items) | |
833 purple_disco_set_in_progress(list, FALSE); | |
834 | |
835 purple_disco_list_unref(list); | |
836 } | |
837 | |
838 static void | |
839 jabber_disco_server_info_cb(JabberStream *js, const char *who, JabberCapabilities caps, gpointer data) | |
840 { | |
841 PurpleDiscoList *list = data; | |
842 JabberIq *iq; | |
843 | |
844 if (caps & JABBER_CAP_ITEMS) { | |
845 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items"); | |
846 xmlnode_set_attrib(iq->node, "to", who); | |
847 jabber_iq_set_callback(iq, jabber_disco_server_items_cb, list); | |
848 | |
849 if (purple_disco_list_get_proto_data(list)) | |
850 jabber_iq_send(iq); | |
851 else | |
852 purple_disco_list_unref(list); | |
853 | |
854 } else { | |
855 purple_notify_error(NULL, _("Error"), _("Server doesn't support service discovery"), NULL); | |
856 purple_disco_set_in_progress(list, FALSE); | |
857 purple_disco_list_unref(list); | |
858 } | |
859 } | |
860 | |
861 static void | |
862 jabber_disco_server_cb(PurpleDiscoList *list, PurpleRequestFields *fields) | |
863 { | |
864 JabberStream *js; | |
865 const char *server_name; | |
866 | |
867 server_name = purple_request_fields_get_string(fields, "server"); | |
868 | |
869 js = purple_disco_list_get_proto_data(list); | |
870 if (!js) { | |
871 purple_debug_error("jabber", "Service discovery requested for %s " | |
872 "without proto_data", server_name); | |
873 return; | |
874 } | |
875 | |
876 purple_disco_set_in_progress(list, TRUE); | |
877 purple_debug_misc("jabber", "Service discovery for %s\n", server_name); | |
878 if (js->last_disco_server) | |
879 g_free(js->last_disco_server); | |
880 js->last_disco_server = g_strdup(server_name); | |
881 | |
882 jabber_disco_info_do(js, server_name, jabber_disco_server_info_cb, list); | |
883 } | |
884 | |
885 void | |
886 jabber_disco_get_list(PurpleConnection *gc, PurpleDiscoList *list) | |
887 { | |
888 PurpleRequestFields *fields; | |
889 PurpleRequestFieldGroup *g; | |
890 PurpleRequestField *f; | |
891 JabberStream *js; | |
892 const char *last_server; | |
893 | |
894 purple_debug_misc("disco.c", "get_list\n"); | |
895 | |
896 js = purple_connection_get_protocol_data(gc); | |
897 purple_disco_list_set_proto_data(list, js); | |
898 | |
899 last_server = js->last_disco_server; | |
900 if (last_server == NULL) | |
901 last_server = js->user->domain; | |
902 | |
903 | |
904 fields = purple_request_fields_new(); | |
905 g = purple_request_field_group_new(NULL); | |
906 f = purple_request_field_string_new("server", _("Server"), | |
907 last_server ? last_server : js->user->domain, FALSE); | |
908 | |
909 purple_request_field_group_add_field(g, f); | |
910 purple_request_fields_add_group(fields, g); | |
911 | |
912 purple_disco_list_ref(list); | |
913 | |
914 purple_request_fields(gc, | |
915 _("Server name request"), | |
916 _("Enter server name"), | |
917 NULL, | |
918 fields, | |
919 _("OK"), G_CALLBACK(jabber_disco_server_cb), | |
920 _("Cancel"), NULL, | |
921 purple_connection_get_account(gc), NULL, NULL, list); | |
922 } | |
923 | |
924 void | |
925 jabber_disco_cancel(PurpleDiscoList *list) | |
926 { | |
927 purple_disco_list_set_proto_data(list, NULL); | |
928 purple_disco_set_in_progress(list, FALSE); | |
929 } | |
930 | |
931 int | |
932 jabber_disco_service_register(PurpleConnection *gc, PurpleDiscoService *service) | |
933 { | |
934 JabberStream *js = gc->proto_data; | |
935 | |
936 jabber_register_gateway(js, service->name); | |
937 | |
938 return 0; | |
939 } | |
940 |