src/proxy.c

changeset 5681
514fbc5374dc
parent 5580
a5a3e6dfb409
child 5872
754c63f29b77
equal deleted inserted replaced
5680:fcf222b89d65 5681:514fbc5374dc
1 /* 1 /**
2 * @file proxy.c Proxy API
3 * @ingroup core
4 *
2 * gaim 5 * gaim
3 * 6 *
4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> 7 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
8 * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
5 * 9 *
6 * This program is free software; you can redistribute it and/or modify 10 * 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 11 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or 12 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 13 * (at your option) any later version.
45 49
46 #include <fcntl.h> 50 #include <fcntl.h>
47 #include <errno.h> 51 #include <errno.h>
48 #include "gaim.h" 52 #include "gaim.h"
49 #include "proxy.h" 53 #include "proxy.h"
54 #include "prefs.h"
50 55
51 #ifdef _WIN32 56 #ifdef _WIN32
52 #include "win32dep.h" 57 #include "win32dep.h"
53 #endif 58 #endif
54 59
55 #define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) 60 #define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR)
56 #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) 61 #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
57 62
58 struct gaim_proxy_info global_proxy_info; 63 static GaimProxyInfo *global_proxy_info = NULL;
64 static gboolean global_proxy_info_from_prefs = FALSE;
59 65
60 struct PHB { 66 struct PHB {
61 GaimInputFunction func; 67 GaimInputFunction func;
62 gpointer data; 68 gpointer data;
63 char *host; 69 char *host;
64 int port; 70 int port;
65 gint inpa; 71 gint inpa;
66 struct gaim_proxy_info *gpi; 72 GaimProxyInfo *gpi;
67 GaimAccount *account; 73 GaimAccount *account;
68 }; 74 };
69 75
70 typedef struct _GaimIOClosure { 76 typedef struct _GaimIOClosure {
71 GaimInputFunction function; 77 GaimInputFunction function;
72 guint result; 78 guint result;
73 gpointer data; 79 gpointer data;
80
74 } GaimIOClosure; 81 } GaimIOClosure;
75 82
83 /**************************************************************************
84 * Proxy structure API
85 **************************************************************************/
86 GaimProxyInfo *
87 gaim_proxy_info_new(void)
88 {
89 return g_new0(GaimProxyInfo, 1);
90 }
91
92 void
93 gaim_proxy_info_destroy(GaimProxyInfo *info)
94 {
95 g_return_if_fail(info != NULL);
96
97 if (info->host != NULL) g_free(info->host);
98 if (info->username != NULL) g_free(info->username);
99 if (info->password != NULL) g_free(info->password);
100
101 g_free(info);
102 }
103
104 void
105 gaim_proxy_info_set_type(GaimProxyInfo *info, GaimProxyType type)
106 {
107 g_return_if_fail(info != NULL);
108
109 info->type = type;
110 }
111
112 void
113 gaim_proxy_info_set_host(GaimProxyInfo *info, const char *host)
114 {
115 g_return_if_fail(info != NULL);
116
117 if (info->host != NULL)
118 g_free(info->host);
119
120 info->host = (host == NULL ? NULL : g_strdup(host));
121 }
122
123 void
124 gaim_proxy_info_set_port(GaimProxyInfo *info, int port)
125 {
126 g_return_if_fail(info != NULL);
127
128 info->port = port;
129 }
130
131 void
132 gaim_proxy_info_set_username(GaimProxyInfo *info, const char *username)
133 {
134 g_return_if_fail(info != NULL);
135
136 if (info->username != NULL)
137 g_free(info->username);
138
139 info->username = (username == NULL ? NULL : g_strdup(username));
140 }
141
142 void
143 gaim_proxy_info_set_password(GaimProxyInfo *info, const char *password)
144 {
145 g_return_if_fail(info != NULL);
146
147 if (info->password != NULL)
148 g_free(info->password);
149
150 info->password = (password == NULL ? NULL : g_strdup(password));
151 }
152
153 GaimProxyType
154 gaim_proxy_info_get_type(const GaimProxyInfo *info)
155 {
156 g_return_val_if_fail(info != NULL, GAIM_PROXY_NONE);
157
158 return info->type;
159 }
160
161 const char *
162 gaim_proxy_info_get_host(const GaimProxyInfo *info)
163 {
164 g_return_val_if_fail(info != NULL, NULL);
165
166 return info->host;
167 }
168
169 int
170 gaim_proxy_info_get_port(const GaimProxyInfo *info)
171 {
172 g_return_val_if_fail(info != NULL, 0);
173
174 return info->port;
175 }
176
177 const char *
178 gaim_proxy_info_get_username(const GaimProxyInfo *info)
179 {
180 g_return_val_if_fail(info != NULL, NULL);
181
182 return info->username;
183 }
184
185 const char *
186 gaim_proxy_info_get_password(const GaimProxyInfo *info)
187 {
188 g_return_val_if_fail(info != NULL, NULL);
189
190 return info->password;
191 }
192
193 /**************************************************************************
194 * Global Proxy API
195 **************************************************************************/
196 void
197 gaim_global_proxy_set_from_prefs(gboolean from_prefs)
198 {
199 global_proxy_info_from_prefs = from_prefs;
200 }
201
202 GaimProxyInfo *
203 gaim_global_proxy_get_info(void)
204 {
205 return global_proxy_info;
206 }
207
208 gboolean
209 gaim_global_proxy_is_from_prefs(void)
210 {
211 return global_proxy_info_from_prefs;
212 }
213
214 /**************************************************************************
215 * Proxy API
216 **************************************************************************/
76 static void gaim_io_destroy(gpointer data) 217 static void gaim_io_destroy(gpointer data)
77 { 218 {
78 g_free(data); 219 g_free(data);
79 } 220 }
80 221
577 g_free(req->addr); 718 g_free(req->addr);
578 g_free(req); 719 g_free(req);
579 return FALSE; 720 return FALSE;
580 } 721 }
581 722
582 int gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data) 723 int
724 gaim_gethostbyname_async(const char *hostname, int port,
725 dns_callback_t callback, gpointer data)
583 { 726 {
584 struct sockaddr_in sin; 727 struct sockaddr_in sin;
585 pending_dns_request_t *req; 728 pending_dns_request_t *req;
586 729
587 if (!inet_aton(hostname, &sin.sin_addr)) { 730 if (!inet_aton(hostname, &sin.sin_addr)) {
608 return 0; 751 return 0;
609 } 752 }
610 753
611 #endif 754 #endif
612 755
613 static void no_one_calls(gpointer data, gint source, GaimInputCondition cond) 756 static void
757 no_one_calls(gpointer data, gint source, GaimInputCondition cond)
614 { 758 {
615 struct PHB *phb = data; 759 struct PHB *phb = data;
616 unsigned int len; 760 unsigned int len;
617 int error=0; 761 int error=0;
618 int ret=0; 762 int ret=0;
624 ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len); 768 ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len);
625 if (ret < 0 || error != 0) { 769 if (ret < 0 || error != 0) {
626 if(ret==0) errno = error; 770 if(ret==0) errno = error;
627 close(source); 771 close(source);
628 gaim_input_remove(phb->inpa); 772 gaim_input_remove(phb->inpa);
629 if(!phb->account || phb->account->gc) 773
774 if (phb->account == NULL ||
775 gaim_account_get_connection(phb->account) != NULL) {
776
630 phb->func(phb->data, -1, GAIM_INPUT_READ); 777 phb->func(phb->data, -1, GAIM_INPUT_READ);
778 }
779
631 g_free(phb->host); 780 g_free(phb->host);
632 g_free(phb); 781 g_free(phb);
633 782
634 gaim_debug(GAIM_DEBUG_ERROR, "proxy", 783 gaim_debug(GAIM_DEBUG_ERROR, "proxy",
635 "getsockopt SO_ERROR check: %s\n", strerror(errno)); 784 "getsockopt SO_ERROR check: %s\n", strerror(errno));
636 return; 785 return;
637 } 786 }
787
638 fcntl(source, F_SETFL, 0); 788 fcntl(source, F_SETFL, 0);
639 gaim_input_remove(phb->inpa); 789 gaim_input_remove(phb->inpa);
640 if(!phb->account || phb->account->gc) 790
791 if (phb->account == NULL ||
792 gaim_account_get_connection(phb->account) != NULL) {
793
641 phb->func(phb->data, source, GAIM_INPUT_READ); 794 phb->func(phb->data, source, GAIM_INPUT_READ);
795 }
796
642 g_free(phb->host); 797 g_free(phb->host);
643 g_free(phb); 798 g_free(phb);
644 } 799 }
645 800
646 static gboolean clean_connect(gpointer data) 801 static gboolean clean_connect(gpointer data)
647 { 802 {
648 struct PHB *phb = data; 803 struct PHB *phb = data;
649 804
650 if(!phb->account || phb->account->gc) 805 if (phb->account == NULL ||
806 gaim_account_get_connection(phb->account) != NULL) {
807
651 phb->func(phb->data, phb->port, GAIM_INPUT_READ); 808 phb->func(phb->data, phb->port, GAIM_INPUT_READ);
809 }
810
652 g_free(phb->host); 811 g_free(phb->host);
653 g_free(phb); 812 g_free(phb);
654 813
655 return FALSE; 814 return FALSE;
656 } 815 }
657 816
658 817
659 static int proxy_connect_none(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) 818 static int
819 proxy_connect_none(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen)
660 { 820 {
661 int fd = -1; 821 int fd = -1;
662 822
663 gaim_debug(GAIM_DEBUG_INFO, "proxy", 823 gaim_debug(GAIM_DEBUG_INFO, "proxy",
664 "Connecting to %s:%d with no proxy\n", phb->host, phb->port); 824 "Connecting to %s:%d with no proxy\n", phb->host, phb->port);
673 if (connect(fd, (struct sockaddr *)addr, addrlen) < 0) { 833 if (connect(fd, (struct sockaddr *)addr, addrlen) < 0) {
674 if ((errno == EINPROGRESS) || (errno == EINTR)) { 834 if ((errno == EINPROGRESS) || (errno == EINTR)) {
675 gaim_debug(GAIM_DEBUG_WARNING, "proxy", 835 gaim_debug(GAIM_DEBUG_WARNING, "proxy",
676 "Connect would have blocked.\n"); 836 "Connect would have blocked.\n");
677 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, phb); 837 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, phb);
678 } else { 838 }
839 else {
679 gaim_debug(GAIM_DEBUG_ERROR, "proxy", 840 gaim_debug(GAIM_DEBUG_ERROR, "proxy",
680 "Connect failed (errno %d)\n", errno); 841 "Connect failed (errno %d)\n", errno);
681 close(fd); 842 close(fd);
682 return -1; 843 return -1;
683 } 844 }
684 } else { 845 }
846 else {
685 unsigned int len; 847 unsigned int len;
686 int error = ETIMEDOUT; 848 int error = ETIMEDOUT;
687 gaim_debug(GAIM_DEBUG_MISC, "proxy", "Connect didn't block.\n"); 849 gaim_debug(GAIM_DEBUG_MISC, "proxy", "Connect didn't block.\n");
688 len = sizeof(error); 850 len = sizeof(error);
689 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 851 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
702 } 864 }
703 865
704 #define HTTP_GOODSTRING "HTTP/1.0 200" 866 #define HTTP_GOODSTRING "HTTP/1.0 200"
705 #define HTTP_GOODSTRING2 "HTTP/1.1 200" 867 #define HTTP_GOODSTRING2 "HTTP/1.1 200"
706 868
707 static void http_canread(gpointer data, gint source, GaimInputCondition cond) 869 static void
870 http_canread(gpointer data, gint source, GaimInputCondition cond)
708 { 871 {
709 int nlc = 0; 872 int nlc = 0;
710 int pos = 0; 873 int pos = 0;
711 int minor, major, status, error=0; 874 int minor, major, status, error=0;
712 struct PHB *phb = data; 875 struct PHB *phb = data;
719 nlc++; 882 nlc++;
720 else if (inputline[pos - 1] != '\r') 883 else if (inputline[pos - 1] != '\r')
721 nlc = 0; 884 nlc = 0;
722 } 885 }
723 inputline[pos] = '\0'; 886 inputline[pos] = '\0';
724 887
725 error = strncmp(inputline, "HTTP/", 5) != 0; 888 error = strncmp(inputline, "HTTP/", 5) != 0;
726 if(!error) { 889 if(!error) {
727 p = inputline + 5; 890 p = inputline + 5;
728 major = strtol(p, &p, 10); 891 major = strtol(p, &p, 10);
729 error = (major==0) || (*p != '.'); 892 error = (major==0) || (*p != '.');
742 if(error) { 905 if(error) {
743 gaim_debug(GAIM_DEBUG_ERROR, "proxy", 906 gaim_debug(GAIM_DEBUG_ERROR, "proxy",
744 "Unable to parse proxy's response: %s\n", inputline); 907 "Unable to parse proxy's response: %s\n", inputline);
745 close(source); 908 close(source);
746 source=-1; 909 source=-1;
747 } else if(status!=200) { 910 }
911 else if(status!=200) {
748 gaim_debug(GAIM_DEBUG_ERROR, "proxy", 912 gaim_debug(GAIM_DEBUG_ERROR, "proxy",
749 "Proxy server replied: (%s)\n", p); 913 "Proxy server replied: (%s)\n", p);
750 close(source); 914 close(source);
751 source=-1; 915 source=-1;
752 } 916 }
756 g_free(phb->host); 920 g_free(phb->host);
757 g_free(phb); 921 g_free(phb);
758 return; 922 return;
759 } 923 }
760 924
761 static void http_canwrite(gpointer data, gint source, GaimInputCondition cond) 925 static void
926 http_canwrite(gpointer data, gint source, GaimInputCondition cond)
762 { 927 {
763 char request[8192]; 928 char request[8192];
764 int request_len = 0; 929 int request_len = 0;
765 struct PHB *phb = data; 930 struct PHB *phb = data;
766 unsigned int len; 931 unsigned int len;
768 933
769 gaim_debug(GAIM_DEBUG_INFO, "http proxy", "Connected.\n"); 934 gaim_debug(GAIM_DEBUG_INFO, "http proxy", "Connected.\n");
770 935
771 if (phb->inpa > 0) 936 if (phb->inpa > 0)
772 gaim_input_remove(phb->inpa); 937 gaim_input_remove(phb->inpa);
938
773 len = sizeof(error); 939 len = sizeof(error);
940
774 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 941 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
775 close(source); 942 close(source);
776 if(!phb->account || phb->account->gc) 943
944 if (phb->account == NULL ||
945 gaim_account_get_connection(phb->account) != NULL) {
946
777 phb->func(phb->data, -1, GAIM_INPUT_READ); 947 phb->func(phb->data, -1, GAIM_INPUT_READ);
948 }
949
778 g_free(phb->host); 950 g_free(phb->host);
779 g_free(phb); 951 g_free(phb);
780 return; 952 return;
781 } 953 }
782 request_len = g_snprintf(request, sizeof(request), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port, 954 request_len = g_snprintf(request, sizeof(request),
783 phb->host, phb->port); 955 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n",
784 956 phb->host, phb->port, phb->host, phb->port);
785 if (phb->gpi->proxyuser) { 957
958 if (gaim_proxy_info_get_username(phb->gpi) != NULL) {
786 char *t1, *t2; 959 char *t1, *t2;
787 t1 = g_strdup_printf("%s:%s", phb->gpi->proxyuser, phb->gpi->proxypass); 960 t1 = g_strdup_printf("%s:%s",
961 gaim_proxy_info_get_username(phb->gpi),
962 gaim_proxy_info_get_password(phb->gpi));
963
788 t2 = tobase64(t1, strlen(t1)); 964 t2 = tobase64(t1, strlen(t1));
789 g_free(t1); 965 g_free(t1);
790 g_return_if_fail(request_len < sizeof(request)); 966 g_return_if_fail(request_len < sizeof(request));
791 request_len += g_snprintf(request + request_len, sizeof(request) - request_len, "Proxy-Authorization: Basic %s\r\n", t2); 967 request_len += g_snprintf(request + request_len,
968 sizeof(request) - request_len,
969 "Proxy-Authorization: Basic %s\r\n", t2);
792 g_free(t2); 970 g_free(t2);
793 } 971 }
794 972
795 g_return_if_fail(request_len < sizeof(request)); 973 g_return_if_fail(request_len < sizeof(request));
796 strcpy(request + request_len, "\r\n"); 974 strcpy(request + request_len, "\r\n");
797 request_len += 2; 975 request_len += 2;
798 976
799 if (write(source, request, request_len) < 0) { 977 if (write(source, request, request_len) < 0) {
800 close(source); 978 close(source);
801 if(!phb->account || phb->account->gc) 979
980 if (phb->account == NULL ||
981 gaim_account_get_connection(phb->account) != NULL) {
982
802 phb->func(phb->data, -1, GAIM_INPUT_READ); 983 phb->func(phb->data, -1, GAIM_INPUT_READ);
984 }
985
803 g_free(phb->host); 986 g_free(phb->host);
804 g_free(phb); 987 g_free(phb);
805 return; 988 return;
806 } 989 }
807 990
808 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); 991 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb);
809 } 992 }
810 993
811 static int proxy_connect_http(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) 994 static int
995 proxy_connect_http(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen)
812 { 996 {
813 int fd = -1; 997 int fd = -1;
814 998
815 gaim_debug(GAIM_DEBUG_INFO, "http proxy", 999 gaim_debug(GAIM_DEBUG_INFO, "http proxy",
816 "Connecting to %s:%d via %s:%d using HTTP\n", 1000 "Connecting to %s:%d via %s:%d using HTTP\n",
817 phb->host, phb->port, phb->gpi->proxyhost, 1001 phb->host, phb->port,
818 phb->gpi->proxyport); 1002 gaim_proxy_info_get_host(phb->gpi),
1003 gaim_proxy_info_get_port(phb->gpi));
819 1004
820 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { 1005 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) {
821 return -1; 1006 return -1;
822 } 1007 }
823 1008
825 1010
826 if (connect(fd, addr, addrlen) < 0) { 1011 if (connect(fd, addr, addrlen) < 0) {
827 if ((errno == EINPROGRESS) || (errno == EINTR)) { 1012 if ((errno == EINPROGRESS) || (errno == EINTR)) {
828 gaim_debug(GAIM_DEBUG_WARNING, "http proxy", 1013 gaim_debug(GAIM_DEBUG_WARNING, "http proxy",
829 "Connect would have blocked.\n"); 1014 "Connect would have blocked.\n");
830 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, http_canwrite, phb); 1015 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE,
1016 http_canwrite, phb);
831 } else { 1017 } else {
832 close(fd); 1018 close(fd);
833 return -1; 1019 return -1;
834 } 1020 }
835 } else { 1021 }
1022 else {
836 unsigned int len; 1023 unsigned int len;
837 int error = ETIMEDOUT; 1024 int error = ETIMEDOUT;
838 1025
839 gaim_debug(GAIM_DEBUG_MISC, "http proxy", 1026 gaim_debug(GAIM_DEBUG_MISC, "http proxy",
840 "Connect didn't block.\n"); 1027 "Connect didn't block.\n");
849 } 1036 }
850 1037
851 return fd; 1038 return fd;
852 } 1039 }
853 1040
854 static void s4_canread(gpointer data, gint source, GaimInputCondition cond) 1041 static void
1042 s4_canread(gpointer data, gint source, GaimInputCondition cond)
855 { 1043 {
856 unsigned char packet[12]; 1044 unsigned char packet[12];
857 struct PHB *phb = data; 1045 struct PHB *phb = data;
858 1046
859 gaim_input_remove(phb->inpa); 1047 gaim_input_remove(phb->inpa);
860 1048
861 memset(packet, 0, sizeof(packet)); 1049 memset(packet, 0, sizeof(packet));
862 1050
863 if (read(source, packet, 9) >= 4 && packet[1] == 90) { 1051 if (read(source, packet, 9) >= 4 && packet[1] == 90) {
864 if(!phb->account || phb->account->gc) 1052 if (phb->account == NULL ||
865 phb->func(phb->data, source, GAIM_INPUT_READ); 1053 gaim_account_get_connection(phb->account) != NULL) {
1054
1055 phb->func(phb->data, -1, GAIM_INPUT_READ);
1056 }
1057
866 g_free(phb->host); 1058 g_free(phb->host);
867 g_free(phb); 1059 g_free(phb);
868 return; 1060 return;
869 } 1061 }
870 1062
871 close(source); 1063 close(source);
872 if(!phb->account || phb->account->gc) 1064
1065 if (phb->account == NULL ||
1066 gaim_account_get_connection(phb->account) != NULL) {
1067
873 phb->func(phb->data, -1, GAIM_INPUT_READ); 1068 phb->func(phb->data, -1, GAIM_INPUT_READ);
1069 }
1070
874 g_free(phb->host); 1071 g_free(phb->host);
875 g_free(phb); 1072 g_free(phb);
876 } 1073 }
877 1074
878 static void s4_canwrite(gpointer data, gint source, GaimInputCondition cond) 1075 static void
1076 s4_canwrite(gpointer data, gint source, GaimInputCondition cond)
879 { 1077 {
880 unsigned char packet[12]; 1078 unsigned char packet[12];
881 struct hostent *hp; 1079 struct hostent *hp;
882 struct PHB *phb = data; 1080 struct PHB *phb = data;
883 unsigned int len; 1081 unsigned int len;
885 1083
886 gaim_debug(GAIM_DEBUG_INFO, "s4 proxy", "Connected.\n"); 1084 gaim_debug(GAIM_DEBUG_INFO, "s4 proxy", "Connected.\n");
887 1085
888 if (phb->inpa > 0) 1086 if (phb->inpa > 0)
889 gaim_input_remove(phb->inpa); 1087 gaim_input_remove(phb->inpa);
1088
890 len = sizeof(error); 1089 len = sizeof(error);
1090
891 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 1091 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
892 close(source); 1092 close(source);
893 if(!phb->account || phb->account->gc) 1093
1094 if (phb->account == NULL ||
1095 gaim_account_get_connection(phb->account) != NULL) {
1096
894 phb->func(phb->data, -1, GAIM_INPUT_READ); 1097 phb->func(phb->data, -1, GAIM_INPUT_READ);
1098 }
1099
895 g_free(phb->host); 1100 g_free(phb->host);
896 g_free(phb); 1101 g_free(phb);
897 return; 1102 return;
898 } 1103 }
899 fcntl(source, F_SETFL, 0); 1104 fcntl(source, F_SETFL, 0);
900 1105
901 /* XXX does socks4 not support host name lookups by the proxy? */ 1106 /* XXX does socks4 not support host name lookups by the proxy? */
902 if (!(hp = gethostbyname(phb->host))) { 1107 if (!(hp = gethostbyname(phb->host))) {
903 close(source); 1108 close(source);
904 if(!phb->account || phb->account->gc) 1109
1110 if (phb->account == NULL ||
1111 gaim_account_get_connection(phb->account) != NULL) {
1112
905 phb->func(phb->data, -1, GAIM_INPUT_READ); 1113 phb->func(phb->data, -1, GAIM_INPUT_READ);
1114 }
1115
906 g_free(phb->host); 1116 g_free(phb->host);
907 g_free(phb); 1117 g_free(phb);
908 return; 1118 return;
909 } 1119 }
910 1120
918 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; 1128 packet[7] = (unsigned char)(hp->h_addr_list[0])[3];
919 packet[8] = 0; 1129 packet[8] = 0;
920 1130
921 if (write(source, packet, 9) != 9) { 1131 if (write(source, packet, 9) != 9) {
922 close(source); 1132 close(source);
923 if(!phb->account || phb->account->gc) 1133
1134 if (phb->account == NULL ||
1135 gaim_account_get_connection(phb->account) != NULL) {
1136
924 phb->func(phb->data, -1, GAIM_INPUT_READ); 1137 phb->func(phb->data, -1, GAIM_INPUT_READ);
1138 }
1139
925 g_free(phb->host); 1140 g_free(phb->host);
926 g_free(phb); 1141 g_free(phb);
927 return; 1142 return;
928 } 1143 }
929 1144
930 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s4_canread, phb); 1145 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s4_canread, phb);
931 } 1146 }
932 1147
933 static int proxy_connect_socks4(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) 1148 static int
1149 proxy_connect_socks4(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen)
934 { 1150 {
935 int fd = -1; 1151 int fd = -1;
936 1152
937 gaim_debug(GAIM_DEBUG_INFO, "socks4 proxy", 1153 gaim_debug(GAIM_DEBUG_INFO, "socks4 proxy",
938 "Connecting to %s:%d via %s:%d using SOCKS4\n", 1154 "Connecting to %s:%d via %s:%d using SOCKS4\n",
939 phb->host, phb->port, phb->gpi->proxyhost, 1155 phb->host, phb->port,
940 phb->gpi->proxyport); 1156 gaim_proxy_info_get_host(phb->gpi),
941 1157 gaim_proxy_info_get_port(phb->gpi));
942 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { 1158
1159 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0)
943 return -1; 1160 return -1;
944 }
945 1161
946 fcntl(fd, F_SETFL, O_NONBLOCK); 1162 fcntl(fd, F_SETFL, O_NONBLOCK);
1163
947 if (connect(fd, addr, addrlen) < 0) { 1164 if (connect(fd, addr, addrlen) < 0) {
948 if ((errno == EINPROGRESS) || (errno == EINTR)) { 1165 if ((errno == EINPROGRESS) || (errno == EINTR)) {
949 gaim_debug(GAIM_DEBUG_WARNING, "socks4 proxy", 1166 gaim_debug(GAIM_DEBUG_WARNING, "socks4 proxy",
950 "Connect would have blocked.\n"); 1167 "Connect would have blocked.\n");
951 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb); 1168 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb);
952 } else { 1169 }
1170 else {
953 close(fd); 1171 close(fd);
954 return -1; 1172 return -1;
955 } 1173 }
956 } else { 1174 } else {
957 unsigned int len; 1175 unsigned int len;
959 1177
960 gaim_debug(GAIM_DEBUG_MISC, "socks4 proxy", 1178 gaim_debug(GAIM_DEBUG_MISC, "socks4 proxy",
961 "Connect didn't block.\n"); 1179 "Connect didn't block.\n");
962 1180
963 len = sizeof(error); 1181 len = sizeof(error);
1182
964 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 1183 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
965 close(fd); 1184 close(fd);
966 return -1; 1185 return -1;
967 } 1186 }
1187
968 fcntl(fd, F_SETFL, 0); 1188 fcntl(fd, F_SETFL, 0);
969 s4_canwrite(phb, fd, GAIM_INPUT_WRITE); 1189 s4_canwrite(phb, fd, GAIM_INPUT_WRITE);
970 } 1190 }
971 1191
972 return fd; 1192 return fd;
973 } 1193 }
974 1194
975 static void s5_canread_again(gpointer data, gint source, GaimInputCondition cond) 1195 static void
1196 s5_canread_again(gpointer data, gint source, GaimInputCondition cond)
976 { 1197 {
977 unsigned char buf[512]; 1198 unsigned char buf[512];
978 struct PHB *phb = data; 1199 struct PHB *phb = data;
979 1200
980 gaim_input_remove(phb->inpa); 1201 gaim_input_remove(phb->inpa);
981 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read again.\n"); 1202 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read again.\n");
982 1203
983 if (read(source, buf, 10) < 10) { 1204 if (read(source, buf, 10) < 10) {
984 gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy", "or not...\n"); 1205 gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy", "or not...\n");
985 close(source); 1206 close(source);
986 if(!phb->account || phb->account->gc) 1207
1208 if (phb->account == NULL ||
1209 gaim_account_get_connection(phb->account) != NULL) {
1210
987 phb->func(phb->data, -1, GAIM_INPUT_READ); 1211 phb->func(phb->data, -1, GAIM_INPUT_READ);
1212 }
1213
988 g_free(phb->host); 1214 g_free(phb->host);
989 g_free(phb); 1215 g_free(phb);
990 return; 1216 return;
991 } 1217 }
992 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { 1218 if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
993 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Bad data.\n"); 1219 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Bad data.\n");
994 close(source); 1220 close(source);
995 if(!phb->account || phb->account->gc) 1221
1222 if (phb->account == NULL ||
1223 gaim_account_get_connection(phb->account) != NULL) {
1224
996 phb->func(phb->data, -1, GAIM_INPUT_READ); 1225 phb->func(phb->data, -1, GAIM_INPUT_READ);
1226 }
1227
997 g_free(phb->host); 1228 g_free(phb->host);
998 g_free(phb); 1229 g_free(phb);
999 return; 1230 return;
1000 } 1231 }
1001 1232
1002 if(!phb->account || phb->account->gc) 1233 if (phb->account == NULL ||
1234 gaim_account_get_connection(phb->account) != NULL) {
1235
1003 phb->func(phb->data, source, GAIM_INPUT_READ); 1236 phb->func(phb->data, source, GAIM_INPUT_READ);
1237 }
1238
1004 g_free(phb->host); 1239 g_free(phb->host);
1005 g_free(phb); 1240 g_free(phb);
1006 return; 1241 }
1007 } 1242
1008 1243 static void
1009 static void s5_sendconnect(gpointer data, gint source) 1244 s5_sendconnect(gpointer data, gint source)
1010 { 1245 {
1011 unsigned char buf[512]; 1246 unsigned char buf[512];
1012 struct PHB *phb = data; 1247 struct PHB *phb = data;
1013 int hlen = strlen(phb->host); 1248 int hlen = strlen(phb->host);
1014 1249
1021 buf[5 + strlen(phb->host)] = phb->port >> 8; 1256 buf[5 + strlen(phb->host)] = phb->port >> 8;
1022 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; 1257 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff;
1023 1258
1024 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { 1259 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
1025 close(source); 1260 close(source);
1026 if(!phb->account || phb->account->gc) 1261
1262 if (phb->account == NULL ||
1263 gaim_account_get_connection(phb->account) != NULL) {
1264
1027 phb->func(phb->data, -1, GAIM_INPUT_READ); 1265 phb->func(phb->data, -1, GAIM_INPUT_READ);
1266 }
1267
1028 g_free(phb->host); 1268 g_free(phb->host);
1029 g_free(phb); 1269 g_free(phb);
1030 return; 1270 return;
1031 } 1271 }
1032 1272
1033 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb); 1273 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);
1034 } 1274 }
1035 1275
1036 static void s5_readauth(gpointer data, gint source, GaimInputCondition cond) 1276 static void
1277 s5_readauth(gpointer data, gint source, GaimInputCondition cond)
1037 { 1278 {
1038 unsigned char buf[512]; 1279 unsigned char buf[512];
1039 struct PHB *phb = data; 1280 struct PHB *phb = data;
1040 1281
1041 gaim_input_remove(phb->inpa); 1282 gaim_input_remove(phb->inpa);
1042 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got auth response.\n"); 1283 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got auth response.\n");
1043 1284
1044 if (read(source, buf, 2) < 2) { 1285 if (read(source, buf, 2) < 2) {
1045 close(source); 1286 close(source);
1046 if(!phb->account || phb->account->gc) 1287
1288 if (phb->account == NULL ||
1289 gaim_account_get_connection(phb->account) != NULL) {
1290
1047 phb->func(phb->data, -1, GAIM_INPUT_READ); 1291 phb->func(phb->data, -1, GAIM_INPUT_READ);
1292 }
1293
1048 g_free(phb->host); 1294 g_free(phb->host);
1049 g_free(phb); 1295 g_free(phb);
1050 return; 1296 return;
1051 } 1297 }
1052 1298
1053 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { 1299 if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
1054 close(source); 1300 close(source);
1055 if(!phb->account || phb->account->gc) 1301
1302 if (phb->account == NULL ||
1303 gaim_account_get_connection(phb->account) != NULL) {
1304
1056 phb->func(phb->data, -1, GAIM_INPUT_READ); 1305 phb->func(phb->data, -1, GAIM_INPUT_READ);
1306 }
1307
1057 g_free(phb->host); 1308 g_free(phb->host);
1058 g_free(phb); 1309 g_free(phb);
1059 return; 1310 return;
1060 } 1311 }
1061 1312
1062 s5_sendconnect(phb, source); 1313 s5_sendconnect(phb, source);
1063 } 1314 }
1064 1315
1065 static void s5_canread(gpointer data, gint source, GaimInputCondition cond) 1316 static void
1317 s5_canread(gpointer data, gint source, GaimInputCondition cond)
1066 { 1318 {
1067 unsigned char buf[512]; 1319 unsigned char buf[512];
1068 struct PHB *phb = data; 1320 struct PHB *phb = data;
1069 1321
1070 gaim_input_remove(phb->inpa); 1322 gaim_input_remove(phb->inpa);
1071 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read.\n"); 1323 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read.\n");
1072 1324
1073 if (read(source, buf, 2) < 2) { 1325 if (read(source, buf, 2) < 2) {
1074 close(source); 1326 close(source);
1075 if(!phb->account || phb->account->gc) 1327
1328 if (phb->account == NULL ||
1329 gaim_account_get_connection(phb->account) != NULL) {
1330
1076 phb->func(phb->data, -1, GAIM_INPUT_READ); 1331 phb->func(phb->data, -1, GAIM_INPUT_READ);
1332 }
1333
1077 g_free(phb->host); 1334 g_free(phb->host);
1078 g_free(phb); 1335 g_free(phb);
1079 return; 1336 return;
1080 } 1337 }
1081 1338
1082 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { 1339 if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
1083 close(source); 1340 close(source);
1084 if(!phb->account || phb->account->gc) 1341
1342 if (phb->account == NULL ||
1343 gaim_account_get_connection(phb->account) != NULL) {
1344
1085 phb->func(phb->data, -1, GAIM_INPUT_READ); 1345 phb->func(phb->data, -1, GAIM_INPUT_READ);
1346 }
1347
1086 g_free(phb->host); 1348 g_free(phb->host);
1087 g_free(phb); 1349 g_free(phb);
1088 return; 1350 return;
1089 } 1351 }
1090 1352
1091 if (buf[1] == 0x02) { 1353 if (buf[1] == 0x02) {
1092 unsigned int i = strlen(phb->gpi->proxyuser), j = strlen(phb->gpi->proxypass); 1354 unsigned int i, j;
1355
1356 i = strlen(gaim_proxy_info_get_username(phb->gpi));
1357 j = strlen(gaim_proxy_info_get_password(phb->gpi));
1358
1093 buf[0] = 0x01; /* version 1 */ 1359 buf[0] = 0x01; /* version 1 */
1094 buf[1] = i; 1360 buf[1] = i;
1095 memcpy(buf + 2, phb->gpi->proxyuser, i); 1361 memcpy(buf + 2, gaim_proxy_info_get_username(phb->gpi), i);
1096 buf[2 + i] = j; 1362 buf[2 + i] = j;
1097 memcpy(buf + 2 + i + 1, phb->gpi->proxypass, j); 1363 memcpy(buf + 2 + i + 1, gaim_proxy_info_get_password(phb->gpi), j);
1098 1364
1099 if (write(source, buf, 3 + i + j) < 3 + i + j) { 1365 if (write(source, buf, 3 + i + j) < 3 + i + j) {
1100 close(source); 1366 close(source);
1101 if(!phb->account || phb->account->gc) 1367
1368 if (phb->account == NULL ||
1369 gaim_account_get_connection(phb->account) != NULL) {
1370
1102 phb->func(phb->data, -1, GAIM_INPUT_READ); 1371 phb->func(phb->data, -1, GAIM_INPUT_READ);
1372 }
1373
1103 g_free(phb->host); 1374 g_free(phb->host);
1104 g_free(phb); 1375 g_free(phb);
1105 return; 1376 return;
1106 } 1377 }
1107 1378
1108 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_readauth, phb); 1379 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_readauth, phb);
1109 } else { 1380 }
1381 else {
1110 s5_sendconnect(phb, source); 1382 s5_sendconnect(phb, source);
1111 } 1383 }
1112 } 1384 }
1113 1385
1114 static void s5_canwrite(gpointer data, gint source, GaimInputCondition cond) 1386 static void
1387 s5_canwrite(gpointer data, gint source, GaimInputCondition cond)
1115 { 1388 {
1116 unsigned char buf[512]; 1389 unsigned char buf[512];
1117 int i; 1390 int i;
1118 struct PHB *phb = data; 1391 struct PHB *phb = data;
1119 unsigned int len; 1392 unsigned int len;
1121 1394
1122 gaim_debug(GAIM_INFO, "socks5 proxy", "Connected.\n"); 1395 gaim_debug(GAIM_INFO, "socks5 proxy", "Connected.\n");
1123 1396
1124 if (phb->inpa > 0) 1397 if (phb->inpa > 0)
1125 gaim_input_remove(phb->inpa); 1398 gaim_input_remove(phb->inpa);
1399
1126 len = sizeof(error); 1400 len = sizeof(error);
1127 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 1401 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
1128 close(source); 1402 close(source);
1129 if(!phb->account || phb->account->gc) 1403 if (phb->account == NULL ||
1404 gaim_account_get_connection(phb->account) != NULL) {
1405
1130 phb->func(phb->data, -1, GAIM_INPUT_READ); 1406 phb->func(phb->data, -1, GAIM_INPUT_READ);
1407 }
1408
1131 g_free(phb->host); 1409 g_free(phb->host);
1132 g_free(phb); 1410 g_free(phb);
1133 return; 1411 return;
1134 } 1412 }
1135 fcntl(source, F_SETFL, 0); 1413 fcntl(source, F_SETFL, 0);
1136 1414
1137 i = 0; 1415 i = 0;
1138 buf[0] = 0x05; /* SOCKS version 5 */ 1416 buf[0] = 0x05; /* SOCKS version 5 */
1139 if (phb->gpi->proxyuser[0]) { 1417
1418 if (gaim_proxy_info_get_username(phb->gpi) != NULL) {
1140 buf[1] = 0x02; /* two methods */ 1419 buf[1] = 0x02; /* two methods */
1141 buf[2] = 0x00; /* no authentication */ 1420 buf[2] = 0x00; /* no authentication */
1142 buf[3] = 0x02; /* username/password authentication */ 1421 buf[3] = 0x02; /* username/password authentication */
1143 i = 4; 1422 i = 4;
1144 } else { 1423 }
1424 else {
1145 buf[1] = 0x01; 1425 buf[1] = 0x01;
1146 buf[2] = 0x00; 1426 buf[2] = 0x00;
1147 i = 3; 1427 i = 3;
1148 } 1428 }
1149 1429
1150 if (write(source, buf, i) < i) { 1430 if (write(source, buf, i) < i) {
1151 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Unable to write\n"); 1431 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Unable to write\n");
1152 close(source); 1432 close(source);
1153 if(!phb->account || phb->account->gc) 1433
1434 if (phb->account == NULL ||
1435 gaim_account_get_connection(phb->account) != NULL) {
1436
1154 phb->func(phb->data, -1, GAIM_INPUT_READ); 1437 phb->func(phb->data, -1, GAIM_INPUT_READ);
1438 }
1439
1155 g_free(phb->host); 1440 g_free(phb->host);
1156 g_free(phb); 1441 g_free(phb);
1157 return; 1442 return;
1158 } 1443 }
1159 1444
1160 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread, phb); 1445 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread, phb);
1161 } 1446 }
1162 1447
1163 static int proxy_connect_socks5(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) 1448 static int
1449 proxy_connect_socks5(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen)
1164 { 1450 {
1165 int fd = -1; 1451 int fd = -1;
1166 1452
1167 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", 1453 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy",
1168 "Connecting to %s:%d via %s:%d using SOCKS5\n", 1454 "Connecting to %s:%d via %s:%d using SOCKS5\n",
1169 phb->host, phb->port, phb->gpi->proxyhost, 1455 phb->host, phb->port,
1170 phb->gpi->proxyport); 1456 gaim_proxy_info_get_host(phb->gpi),
1171 1457 gaim_proxy_info_get_port(phb->gpi));
1172 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { 1458
1459 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0)
1173 return -1; 1460 return -1;
1174 }
1175 1461
1176 fcntl(fd, F_SETFL, O_NONBLOCK); 1462 fcntl(fd, F_SETFL, O_NONBLOCK);
1463
1177 if (connect(fd, addr, addrlen) < 0) { 1464 if (connect(fd, addr, addrlen) < 0) {
1178 if ((errno == EINPROGRESS) || (errno == EINTR)) { 1465 if ((errno == EINPROGRESS) || (errno == EINTR)) {
1179 gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy", 1466 gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy",
1180 "Connect would have blocked.\n"); 1467 "Connect would have blocked.\n");
1468
1181 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb); 1469 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb);
1182 } else { 1470 }
1471 else {
1183 close(fd); 1472 close(fd);
1184 return -1; 1473 return -1;
1185 } 1474 }
1186 } else { 1475 }
1476 else {
1187 unsigned int len; 1477 unsigned int len;
1188 int error = ETIMEDOUT; 1478 int error = ETIMEDOUT;
1189 1479
1190 gaim_debug(GAIM_DEBUG_MISC, "socks5 proxy", 1480 gaim_debug(GAIM_DEBUG_MISC, "socks5 proxy",
1191 "Connect didn't block.\n"); 1481 "Connect didn't block.\n");
1482
1192 len = sizeof(error); 1483 len = sizeof(error);
1484
1193 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 1485 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
1194 close(fd); 1486 close(fd);
1195 return -1; 1487 return -1;
1196 } 1488 }
1489
1197 fcntl(fd, F_SETFL, 0); 1490 fcntl(fd, F_SETFL, 0);
1198 s5_canwrite(phb, fd, GAIM_INPUT_WRITE); 1491 s5_canwrite(phb, fd, GAIM_INPUT_WRITE);
1199 } 1492 }
1200 1493
1201 return fd; 1494 return fd;
1202 } 1495 }
1203 1496
1204 static void connection_host_resolved(GSList *hosts, gpointer data, const char *error_message) 1497 static void
1498 connection_host_resolved(GSList *hosts, gpointer data,
1499 const char *error_message)
1205 { 1500 {
1206 struct PHB *phb = (struct PHB*)data; 1501 struct PHB *phb = (struct PHB*)data;
1207 size_t addrlen; 1502 size_t addrlen;
1208 struct sockaddr *addr; 1503 struct sockaddr *addr;
1209 int ret = -1; 1504 int ret = -1;
1210 1505
1211 while(hosts) { 1506 while (hosts) {
1212 addrlen = GPOINTER_TO_INT(hosts->data); 1507 addrlen = GPOINTER_TO_INT(hosts->data);
1213 hosts = hosts->next; 1508 hosts = hosts->next;
1214 addr = hosts->data; 1509 addr = hosts->data;
1215 hosts = hosts->next; 1510 hosts = hosts->next;
1216 1511
1217 switch(phb->gpi->proxytype) 1512 switch (gaim_proxy_info_get_type(phb->gpi))
1218 { 1513 {
1219 case PROXY_NONE: 1514 case GAIM_PROXY_NONE:
1220 ret = proxy_connect_none(phb, addr, addrlen); 1515 ret = proxy_connect_none(phb, addr, addrlen);
1221 break; 1516 break;
1222 case PROXY_HTTP: 1517
1518 case GAIM_PROXY_HTTP:
1223 ret = proxy_connect_http(phb, addr, addrlen); 1519 ret = proxy_connect_http(phb, addr, addrlen);
1224 break; 1520 break;
1225 case PROXY_SOCKS4: 1521
1522 case GAIM_PROXY_SOCKS4:
1226 ret = proxy_connect_socks4(phb, addr, addrlen); 1523 ret = proxy_connect_socks4(phb, addr, addrlen);
1227 break; 1524 break;
1228 case PROXY_SOCKS5: 1525
1526 case GAIM_PROXY_SOCKS5:
1229 ret = proxy_connect_socks5(phb, addr, addrlen); 1527 ret = proxy_connect_socks5(phb, addr, addrlen);
1230 break; 1528 break;
1231 } 1529
1530 default:
1531 break;
1532 }
1533
1232 if (ret > 0) 1534 if (ret > 0)
1233 break; 1535 break;
1234 } 1536 }
1235 if(ret < 0) { 1537
1236 if(!phb->account || phb->account->gc) 1538 if (ret < 0) {
1539 if (phb->account == NULL ||
1540 gaim_account_get_connection(phb->account) != NULL) {
1541
1237 phb->func(phb->data, -1, GAIM_INPUT_READ); 1542 phb->func(phb->data, -1, GAIM_INPUT_READ);
1543 }
1544
1238 g_free(phb->host); 1545 g_free(phb->host);
1239 g_free(phb); 1546 g_free(phb);
1240 } 1547 }
1241 } 1548 }
1242 1549
1243 int 1550 int
1244 proxy_connect(GaimAccount *account, const char *host, int port, GaimInputFunction func, gpointer data) 1551 gaim_proxy_connect(GaimAccount *account, const char *host, int port,
1552 GaimInputFunction func, gpointer data)
1245 { 1553 {
1246 const char *connecthost = host; 1554 const char *connecthost = host;
1247 int connectport = port; 1555 int connectport = port;
1248 struct PHB *phb = g_new0(struct PHB, 1); 1556 struct PHB *phb = g_new0(struct PHB, 1);
1249 if(!account || !account->gpi) 1557
1250 phb->gpi = &global_proxy_info; 1558 g_return_val_if_fail(host != NULL, -1);
1559 g_return_val_if_fail(port != 0 && port != -1, -1);
1560 g_return_val_if_fail(func != NULL, -1);
1561
1562 if (account == NULL || gaim_account_get_proxy_info(account) == NULL)
1563 phb->gpi = gaim_global_proxy_get_info();
1251 else 1564 else
1252 phb->gpi = account->gpi; 1565 phb->gpi = gaim_account_get_proxy_info(account);
1566
1253 phb->func = func; 1567 phb->func = func;
1254 phb->data = data; 1568 phb->data = data;
1255 phb->host = g_strdup(host); 1569 phb->host = g_strdup(host);
1256 phb->port = port; 1570 phb->port = port;
1257 phb->account = account; 1571 phb->account = account;
1258 1572
1259 if (!host || !port || (port == -1) || !func) { 1573 if ((gaim_proxy_info_get_type(phb->gpi) != GAIM_PROXY_NONE) &&
1260 if(host) 1574 (gaim_proxy_info_get_host(phb->gpi) == NULL ||
1261 g_free(phb->host); 1575 gaim_proxy_info_get_port(phb->gpi) == 0 ||
1262 g_free(phb); 1576 gaim_proxy_info_get_port(phb->gpi) == -1)) {
1263 return -1; 1577
1264 } 1578 gaim_proxy_info_set_type(phb->gpi, GAIM_PROXY_NONE);
1265 1579 }
1266 if ((phb->gpi->proxytype!=PROXY_NONE) && (!phb->gpi->proxyhost || !phb->gpi->proxyhost[0] || !phb->gpi->proxyport || (phb->gpi->proxyport == -1))) 1580
1267 phb->gpi->proxytype=PROXY_NONE; 1581 switch (gaim_proxy_info_get_type(phb->gpi))
1268
1269 switch(phb->gpi->proxytype)
1270 { 1582 {
1271 case PROXY_NONE: 1583 case GAIM_PROXY_NONE:
1272 break; 1584 break;
1273 case PROXY_HTTP: 1585
1274 case PROXY_SOCKS4: 1586 case GAIM_PROXY_HTTP:
1275 case PROXY_SOCKS5: 1587 case GAIM_PROXY_SOCKS4:
1276 connecthost=phb->gpi->proxyhost; 1588 case GAIM_PROXY_SOCKS5:
1277 connectport=phb->gpi->proxyport; 1589 connecthost = gaim_proxy_info_get_host(phb->gpi);
1590 connectport = gaim_proxy_info_get_port(phb->gpi);
1278 break; 1591 break;
1592
1279 default: 1593 default:
1280 g_free(phb->host); 1594 g_free(phb->host);
1281 g_free(phb); 1595 g_free(phb);
1282 return -1; 1596 return -1;
1283 } 1597 }
1284 1598
1285 return gaim_gethostbyname_async(connecthost, connectport, connection_host_resolved, phb); 1599 return gaim_gethostbyname_async(connecthost, connectport,
1286 } 1600 connection_host_resolved, phb);
1601 }
1602
1603
1604 static void
1605 proxy_pref_cb(const char *name, GaimPrefType type, gpointer value,
1606 gpointer data)
1607 {
1608 GaimProxyInfo *info = gaim_global_proxy_get_info();
1609
1610 if (!strcmp(name, "/core/proxy/type"))
1611 gaim_proxy_info_set_type(info, GPOINTER_TO_INT(value));
1612 else if (!strcmp(name, "/core/proxy/host"))
1613 gaim_proxy_info_set_host(info, value);
1614 else if (!strcmp(name, "/core/proxy/port"))
1615 gaim_proxy_info_set_port(info, GPOINTER_TO_INT(value));
1616 else if (!strcmp(name, "/core/proxy/username"))
1617 gaim_proxy_info_set_username(info, value);
1618 else if (!strcmp(name, "/core/proxy/password"))
1619 gaim_proxy_info_set_password(info, value);
1620 }
1621
1622 void
1623 gaim_proxy_init(void)
1624 {
1625 /* Initialize a default proxy info struct. */
1626 global_proxy_info = gaim_proxy_info_new();
1627
1628 /* Proxy */
1629 gaim_prefs_add_none("/core/proxy");
1630 gaim_prefs_add_string("/core/proxy/type", "none");
1631 gaim_prefs_add_string("/core/proxy/host", "");
1632 gaim_prefs_add_int("/core/proxy/port", 0);
1633 gaim_prefs_add_string("/core/proxy/username", "");
1634 gaim_prefs_add_string("/core/proxy/password", "");
1635
1636 /* Setup callbacks for the preferences. */
1637 gaim_prefs_connect_callback("/core/proxy/type",
1638 proxy_pref_cb, NULL);
1639 gaim_prefs_connect_callback("/core/proxy/host",
1640 proxy_pref_cb, NULL);
1641 gaim_prefs_connect_callback("/core/proxy/port",
1642 proxy_pref_cb, NULL);
1643 gaim_prefs_connect_callback("/core/proxy/username",
1644 proxy_pref_cb, NULL);
1645 gaim_prefs_connect_callback("/core/proxy/password",
1646 proxy_pref_cb, NULL);
1647 }

mercurial