comparison libpurple/protocols/jabber/jabber.c @ 27711:7fbf964c6c6c

Move the IDN support into the DNS routines. This turned out to be cleaner than I first thought, so here we go. All libpurple DNS routines support IDN when built against GNU libidn.
author Paul Aurich <paul@darkrain42.org>
date Sun, 19 Jul 2009 23:45:13 +0000
parents 5f17bfa9dc70
children e1cd44c7c7af 96c38fe2cb00 776a9b5bd50c
comparison
equal deleted inserted replaced
27710:91333c6c16ef 27711:7fbf964c6c6c
655 if (source < 0) { 655 if (source < 0) {
656 if (js->srv_rec != NULL) { 656 if (js->srv_rec != NULL) {
657 purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record.\n", error); 657 purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record.\n", error);
658 try_srv_connect(js); 658 try_srv_connect(js);
659 } else { 659 } else {
660 char *ascii_domain = jabber_try_idna_to_ascii(js->user->domain);
661 purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); 660 purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
662 js->srv_query_data = purple_txt_resolve("_xmppconnect", 661 js->srv_query_data = purple_txt_resolve("_xmppconnect",
663 ascii_domain, txt_resolved_cb, js); 662 js->user->domain, txt_resolved_cb, js);
664 g_free(ascii_domain);
665 } 663 }
666 return; 664 return;
667 } 665 }
668 666
669 g_free(js->srv_rec); 667 g_free(js->srv_rec);
702 js->gsc = purple_ssl_connect_with_host_fd(js->gc->account, js->fd, 700 js->gsc = purple_ssl_connect_with_host_fd(js->gc->account, js->fd,
703 jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc); 701 jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc);
704 } 702 }
705 703
706 static gboolean jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port, 704 static gboolean jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port,
707 gboolean fatal_failure, gboolean use_domain) 705 gboolean fatal_failure)
708 { 706 {
709 /* host should be used in preference to domain to 707 /* host should be used in preference to domain to
710 * allow SASL authentication to work with FQDN of the server, 708 * allow SASL authentication to work with FQDN of the server,
711 * but we use domain as fallback for when users enter IP address 709 * but we use domain as fallback for when users enter IP address
712 * in connect server. 710 * in connect server */
713 * We also want to use the domain if the hostname is the result of the
714 * IDNA ToASCII operation.
715 */
716 g_free(js->serverFQDN); 711 g_free(js->serverFQDN);
717 if (use_domain || purple_ip_address_is_valid(host)) 712 if (purple_ip_address_is_valid(host))
718 js->serverFQDN = g_strdup(domain); 713 js->serverFQDN = g_strdup(domain);
719 else 714 else
720 js->serverFQDN = g_strdup(host); 715 js->serverFQDN = g_strdup(host);
721 716
722 if (purple_proxy_connect(js->gc, purple_connection_get_account(js->gc), 717 if (purple_proxy_connect(js->gc, purple_connection_get_account(js->gc),
733 return TRUE; 728 return TRUE;
734 } 729 }
735 730
736 static void try_srv_connect(JabberStream *js) 731 static void try_srv_connect(JabberStream *js)
737 { 732 {
738 char *ascii_domain;
739
740 while (js->srv_rec != NULL && js->srv_rec_idx < js->max_srv_rec_idx) { 733 while (js->srv_rec != NULL && js->srv_rec_idx < js->max_srv_rec_idx) {
741 PurpleSrvResponse *tmp_resp = js->srv_rec + (js->srv_rec_idx++); 734 PurpleSrvResponse *tmp_resp = js->srv_rec + (js->srv_rec_idx++);
742 if (jabber_login_connect(js, tmp_resp->hostname, tmp_resp->hostname, tmp_resp->port, FALSE, FALSE)) 735 if (jabber_login_connect(js, tmp_resp->hostname, tmp_resp->hostname, tmp_resp->port, FALSE))
743 return; 736 return;
744 } 737 }
745 738
746 g_free(js->srv_rec); 739 g_free(js->srv_rec);
747 js->srv_rec = NULL; 740 js->srv_rec = NULL;
748 741
749 ascii_domain = jabber_try_idna_to_ascii(js->user->domain);
750 /* Fall back to the defaults (I'm not sure if we should actually do this) */ 742 /* Fall back to the defaults (I'm not sure if we should actually do this) */
751 jabber_login_connect(js, js->user->domain, ascii_domain, 743 jabber_login_connect(js, js->user->domain, js->user->domain,
752 purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222), 744 purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
753 TRUE, TRUE); 745 TRUE);
754 g_free(ascii_domain);
755 } 746 }
756 747
757 static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data) 748 static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data)
758 { 749 {
759 JabberStream *js = data; 750 JabberStream *js = data;
763 js->srv_rec = resp; 754 js->srv_rec = resp;
764 js->srv_rec_idx = 0; 755 js->srv_rec_idx = 0;
765 js->max_srv_rec_idx = results; 756 js->max_srv_rec_idx = results;
766 try_srv_connect(js); 757 try_srv_connect(js);
767 } else { 758 } else {
768 char *ascii_domain = jabber_try_idna_to_ascii(js->user->domain); 759 jabber_login_connect(js, js->user->domain, js->user->domain,
769 jabber_login_connect(js, js->user->domain, ascii_domain,
770 purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222), 760 purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
771 TRUE, TRUE); 761 TRUE);
772 g_free(ascii_domain);
773 } 762 }
774 } 763 }
775 764
776 static JabberStream * 765 static JabberStream *
777 jabber_stream_new(PurpleAccount *account) 766 jabber_stream_new(PurpleAccount *account)
858 PurpleAccount *account = purple_connection_get_account(gc); 847 PurpleAccount *account = purple_connection_get_account(gc);
859 const char *connect_server = purple_account_get_string(account, 848 const char *connect_server = purple_account_get_string(account,
860 "connect_server", ""); 849 "connect_server", "");
861 const char *bosh_url = purple_account_get_string(account, 850 const char *bosh_url = purple_account_get_string(account,
862 "bosh_url", ""); 851 "bosh_url", "");
863 char *ascii_domain;
864 852
865 jabber_stream_set_state(js, JABBER_STREAM_CONNECTING); 853 jabber_stream_set_state(js, JABBER_STREAM_CONNECTING);
866 854
867 /* If both BOSH and a Connect Server are specified, we prefer BOSH. I'm not 855 /* If both BOSH and a Connect Server are specified, we prefer BOSH. I'm not
868 * attached to that choice, though. 856 * attached to that choice, though.
881 return; 869 return;
882 } 870 }
883 871
884 js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain); 872 js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
885 873
886 ascii_domain = jabber_try_idna_to_ascii(js->certificate_CN);
887 if (ascii_domain == NULL) {
888 purple_connection_error_reason(gc,
889 PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
890 _("Invalid XMPP ID"));
891 return;
892 }
893
894 /* if they've got old-ssl mode going, we probably want to ignore SRV lookups */ 874 /* if they've got old-ssl mode going, we probably want to ignore SRV lookups */
895 if(purple_account_get_bool(account, "old_ssl", FALSE)) { 875 if(purple_account_get_bool(account, "old_ssl", FALSE)) {
896 if(purple_ssl_is_supported()) { 876 if(purple_ssl_is_supported()) {
897 js->gsc = purple_ssl_connect_with_ssl_cn(account, ascii_domain, 877 js->gsc = purple_ssl_connect(account, js->certificate_CN,
898 purple_account_get_int(account, "port", 5223), 878 purple_account_get_int(account, "port", 5223),
899 jabber_login_callback_ssl, jabber_ssl_connect_failure, 879 jabber_login_callback_ssl, jabber_ssl_connect_failure, gc);
900 js->certificate_CN, gc);
901 g_free(ascii_domain);
902 if (!js->gsc) { 880 if (!js->gsc) {
903 purple_connection_error_reason(gc, 881 purple_connection_error_reason(gc,
904 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, 882 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
905 _("Unable to establish SSL connection")); 883 _("Unable to establish SSL connection"));
906 } 884 }
908 purple_connection_error_reason(gc, 886 purple_connection_error_reason(gc,
909 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, 887 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
910 _("SSL support unavailable")); 888 _("SSL support unavailable"));
911 } 889 }
912 890
913 g_free(ascii_domain);
914 return; 891 return;
915 } 892 }
916 893
917 /* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll 894 /* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll
918 * invoke the magic of SRV lookups, to figure out host and port */ 895 * invoke the magic of SRV lookups, to figure out host and port */
919 if(connect_server[0]) { 896 if(connect_server[0]) {
920 jabber_login_connect(js, js->user->domain, ascii_domain, 897 jabber_login_connect(js, js->user->domain, connect_server,
921 purple_account_get_int(account, "port", 5222), 898 purple_account_get_int(account, "port", 5222), TRUE);
922 TRUE, TRUE);
923 } else { 899 } else {
924 js->srv_query_data = purple_srv_resolve("xmpp-client", 900 js->srv_query_data = purple_srv_resolve("xmpp-client",
925 "tcp", ascii_domain, srv_resolved_cb, js); 901 "tcp", js->user->domain, srv_resolved_cb, js);
926 } 902 }
927
928 g_free(ascii_domain);
929 } 903 }
930 904
931 void 905 void
932 jabber_login(PurpleAccount *account) 906 jabber_login(PurpleAccount *account)
933 { 907 {