| 194 if (condition & GAIM_READ_COND) |
194 if (condition & GAIM_READ_COND) |
| 195 gaim_cond |= GAIM_INPUT_READ; |
195 gaim_cond |= GAIM_INPUT_READ; |
| 196 if (condition & GAIM_WRITE_COND) |
196 if (condition & GAIM_WRITE_COND) |
| 197 gaim_cond |= GAIM_INPUT_WRITE; |
197 gaim_cond |= GAIM_INPUT_WRITE; |
| 198 |
198 |
| 199 /* |
199 #if 0 |
| 200 gaim_debug(GAIM_DEBUG_MISC, "proxy", |
200 gaim_debug(GAIM_DEBUG_MISC, "proxy", |
| 201 "CLOSURE: callback for %d, fd is %d\n", |
201 "CLOSURE: callback for %d, fd is %d\n", |
| 202 closure->result, g_io_channel_unix_get_fd(source)); |
202 closure->result, g_io_channel_unix_get_fd(source)); |
| 203 */ |
203 #endif |
| 204 |
204 |
| 205 closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); |
205 closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); |
| 206 |
206 |
| 207 return TRUE; |
207 return TRUE; |
| 208 } |
208 } |
| 223 |
223 |
| 224 channel = g_io_channel_unix_new(source); |
224 channel = g_io_channel_unix_new(source); |
| 225 closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, |
225 closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, |
| 226 gaim_io_invoke, closure, gaim_io_destroy); |
226 gaim_io_invoke, closure, gaim_io_destroy); |
| 227 |
227 |
| 228 /* |
228 #if 0 |
| 229 gaim_debug(GAIM_DEBUG_MISC, "proxy", |
229 gaim_debug(GAIM_DEBUG_MISC, "proxy", |
| 230 "CLOSURE: adding input watcher %d for fd %d\n", |
230 "CLOSURE: adding input watcher %d for fd %d\n", |
| 231 closure->result, source); |
231 closure->result, source); |
| 232 */ |
232 #endif |
| 233 |
233 |
| 234 g_io_channel_unref(channel); |
234 g_io_channel_unref(channel); |
| 235 return closure->result; |
235 return closure->result; |
| 236 } |
236 } |
| 237 |
237 |
| 935 |
935 |
| 936 return TRUE; |
936 return TRUE; |
| 937 } |
937 } |
| 938 #endif |
938 #endif |
| 939 |
939 |
| |
940 |
| |
941 static void |
| |
942 http_complete(struct PHB *phb, gint source) |
| |
943 { |
| |
944 gaim_debug(GAIM_DEBUG_INFO, "http proxy", "proxy connection established\n"); |
| |
945 if(!phb->account || phb->account->gc) |
| |
946 phb->func(phb->data, source, GAIM_INPUT_READ); |
| |
947 g_free(phb->host); |
| |
948 g_free(phb); |
| |
949 } |
| |
950 |
| |
951 |
| |
952 /* read the response to the CONNECT request, if we are requesting a non-port-80 tunnel */ |
| 940 static void |
953 static void |
| 941 http_canread(gpointer data, gint source, GaimInputCondition cond) |
954 http_canread(gpointer data, gint source, GaimInputCondition cond) |
| 942 { |
955 { |
| 943 int nlc = 0; |
956 int nlc = 0; |
| 944 int pos = 0; |
957 int pos = 0; |
| 979 close(source); |
992 close(source); |
| 980 source=-1; |
993 source=-1; |
| 981 } |
994 } |
| 982 else if(status!=200) { |
995 else if(status!=200) { |
| 983 gaim_debug(GAIM_DEBUG_ERROR, "proxy", |
996 gaim_debug(GAIM_DEBUG_ERROR, "proxy", |
| 984 "Proxy server replied: (%s)\n", p); |
997 "Proxy server replied with:\n%s\n", p); |
| 985 close(source); |
998 close(source); |
| 986 source=-1; |
999 source = -1; |
| 987 } |
1000 |
| 988 |
1001 if ( status == 403 /* Forbidden */ ) |
| 989 if(!phb->account || phb->account->gc) |
1002 gaim_connection_error(phb->account->gc, _("Access denied: proxy server forbids port 80 tunnelling.")); |
| 990 phb->func(phb->data, source, GAIM_INPUT_READ); |
1003 else { |
| 991 g_free(phb->host); |
1004 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); |
| 992 g_free(phb); |
1005 gaim_connection_error(phb->account->gc, msg); |
| |
1006 g_free(msg); |
| |
1007 } |
| |
1008 |
| |
1009 } else { |
| |
1010 http_complete(phb, source); |
| |
1011 } |
| |
1012 |
| 993 return; |
1013 return; |
| 994 } |
1014 } |
| 995 |
1015 |
| 996 static void |
1016 static void |
| 997 http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
1017 http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
| 1020 |
1040 |
| 1021 g_free(phb->host); |
1041 g_free(phb->host); |
| 1022 g_free(phb); |
1042 g_free(phb); |
| 1023 return; |
1043 return; |
| 1024 } |
1044 } |
| |
1045 |
| |
1046 gaim_debug(GAIM_DEBUG_INFO, "proxy", "using CONNECT tunnelling for %s:%d\n", phb->host, phb->port); |
| 1025 request_len = g_snprintf(request, sizeof(request), |
1047 request_len = g_snprintf(request, sizeof(request), |
| 1026 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", |
1048 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", |
| 1027 phb->host, phb->port, phb->host, phb->port); |
1049 phb->host, phb->port, phb->host, phb->port); |
| 1028 |
1050 |
| 1029 if (gaim_proxy_info_get_username(phb->gpi) != NULL) { |
1051 if (gaim_proxy_info_get_username(phb->gpi) != NULL) { |
| 1030 char *t1, *t2; |
1052 char *t1, *t2; |
| 1031 t1 = g_strdup_printf("%s:%s", |
1053 t1 = g_strdup_printf("%s:%s", |
| 1032 gaim_proxy_info_get_username(phb->gpi), |
1054 gaim_proxy_info_get_username(phb->gpi), |
| 1033 gaim_proxy_info_get_password(phb->gpi) ? |
1055 gaim_proxy_info_get_password(phb->gpi) ? |
| 1034 gaim_proxy_info_get_password(phb->gpi) : ""); |
1056 gaim_proxy_info_get_password(phb->gpi) : ""); |
| 1035 t2 = gaim_base64_encode(t1, strlen(t1)); |
1057 t2 = gaim_base64_encode(t1, strlen(t1)); |
| 1036 g_free(t1); |
1058 g_free(t1); |
| 1037 g_return_if_fail(request_len < sizeof(request)); |
1059 g_return_if_fail(request_len < sizeof(request)); |
| 1038 request_len += g_snprintf(request + request_len, |
1060 request_len += g_snprintf(request + request_len, |
| 1039 sizeof(request) - request_len, |
1061 sizeof(request) - request_len, |
| 1040 "Proxy-Authorization: Basic %s\r\n", t2); |
1062 "Proxy-Authorization: Basic %s\r\n", t2); |
| 1041 g_free(t2); |
1063 g_free(t2); |
| 1042 } |
1064 } |
| 1043 |
1065 |
| 1044 g_return_if_fail(request_len < sizeof(request)); |
1066 g_return_if_fail(request_len < sizeof(request)); |
| 1045 strcpy(request + request_len, "\r\n"); |
1067 strcpy(request + request_len, "\r\n"); |
| 1057 g_free(phb->host); |
1079 g_free(phb->host); |
| 1058 g_free(phb); |
1080 g_free(phb); |
| 1059 return; |
1081 return; |
| 1060 } |
1082 } |
| 1061 |
1083 |
| |
1084 /* register the response handler for the CONNECT request */ |
| 1062 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); |
1085 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); |
| 1063 } |
1086 } |
| 1064 |
1087 |
| 1065 static int |
1088 static int |
| 1066 proxy_connect_http(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) |
1089 proxy_connect_http(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) |
| 1081 |
1104 |
| 1082 if (connect(fd, addr, addrlen) < 0) { |
1105 if (connect(fd, addr, addrlen) < 0) { |
| 1083 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
1106 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1084 gaim_debug(GAIM_DEBUG_WARNING, "http proxy", |
1107 gaim_debug(GAIM_DEBUG_WARNING, "http proxy", |
| 1085 "Connect would have blocked.\n"); |
1108 "Connect would have blocked.\n"); |
| 1086 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, |
1109 |
| 1087 http_canwrite, phb); |
1110 if (phb->port != 80) { |
| |
1111 /* we need to do CONNECT first */ |
| |
1112 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, |
| |
1113 http_canwrite, phb); |
| |
1114 } else { |
| |
1115 http_complete(phb, fd); |
| |
1116 } |
| 1088 } else { |
1117 } else { |
| 1089 close(fd); |
1118 close(fd); |
| 1090 return -1; |
1119 return -1; |
| 1091 } |
1120 } |
| 1092 } |
1121 } |