Mercurial > pidgin
annotate src/protocols/msn/httpconn.c @ 12760:c5acba513363
[gaim-migrate @ 15107]
Request the public IP everytime it is used since there may be
information or a new IP.
committer: Tailor Script <tailor@pidgin.im>
author | Thomas Butter <tbutter> |
---|---|
date | Sun, 08 Jan 2006 01:16:23 +0000 |
parents | fc464a0abccc |
children | 33bef17125c2 |
rev | line source |
---|---|
10463 | 1 /** |
2 * @file httpmethod.c HTTP connection method | |
3 * | |
4 * gaim | |
5 * | |
6 * Gaim is the legal property of its developers, whose names are too numerous | |
7 * to list here. Please refer to the COPYRIGHT file distributed with this | |
8 * source distribution. | |
9 * | |
10 * This program is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 */ | |
24 #include "msn.h" | |
25 #include "debug.h" | |
26 #include "httpconn.h" | |
27 | |
28 typedef struct | |
29 { | |
30 MsnHttpConn *httpconn; | |
10481 | 31 char *data; |
10463 | 32 size_t size; |
33 | |
34 } MsnHttpQueueData; | |
35 | |
36 static void read_cb(gpointer data, gint source, GaimInputCondition cond); | |
37 void msn_httpconn_process_queue(MsnHttpConn *httpconn); | |
38 gboolean msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf, | |
39 size_t size, char **ret_buf, size_t *ret_size, | |
40 gboolean *error); | |
41 | |
42 MsnHttpConn * | |
43 msn_httpconn_new(MsnServConn *servconn) | |
44 { | |
45 MsnHttpConn *httpconn; | |
46 | |
47 g_return_val_if_fail(servconn != NULL, NULL); | |
48 | |
49 httpconn = g_new0(MsnHttpConn, 1); | |
50 | |
10481 | 51 gaim_debug_info("msn", "new httpconn (%p)\n", httpconn); |
52 | |
10463 | 53 /* TODO: Remove this */ |
54 httpconn->session = servconn->session; | |
55 | |
56 httpconn->servconn = servconn; | |
57 | |
58 return httpconn; | |
59 } | |
60 | |
61 void | |
62 msn_httpconn_destroy(MsnHttpConn *httpconn) | |
63 { | |
64 g_return_if_fail(httpconn != NULL); | |
65 | |
10481 | 66 gaim_debug_info("msn", "destroy httpconn (%p)\n", httpconn); |
67 | |
10463 | 68 if (httpconn->connected) |
69 msn_httpconn_disconnect(httpconn); | |
70 | |
10504 | 71 if (httpconn->full_session_id != NULL) |
72 g_free(httpconn->full_session_id); | |
73 | |
74 if (httpconn->session_id != NULL) | |
75 g_free(httpconn->session_id); | |
76 | |
77 if (httpconn->host != NULL) | |
78 g_free(httpconn->host); | |
79 | |
10463 | 80 g_free(httpconn); |
81 } | |
82 | |
10568 | 83 static char * |
84 msn_httpconn_proxy_auth(MsnHttpConn *httpconn) | |
85 { | |
86 GaimAccount *account; | |
87 GaimProxyInfo *gpi; | |
88 const char *username, *password; | |
89 char *auth = NULL; | |
90 | |
91 account = httpconn->session->account; | |
92 | |
93 if (gaim_account_get_proxy_info(account) == NULL) | |
94 gpi = gaim_global_proxy_get_info(); | |
95 else | |
96 gpi = gaim_account_get_proxy_info(account); | |
97 | |
98 if (gpi == NULL || !(gaim_proxy_info_get_type(gpi) == GAIM_PROXY_HTTP || | |
99 gaim_proxy_info_get_type(gpi) == GAIM_PROXY_USE_ENVVAR)) | |
100 return NULL; | |
101 | |
102 username = gaim_proxy_info_get_username(gpi); | |
103 password = gaim_proxy_info_get_password(gpi); | |
104 | |
105 if (username != NULL) { | |
106 char *tmp; | |
107 auth = g_strdup_printf("%s:%s", username, password ? password : ""); | |
11137 | 108 tmp = gaim_base64_encode((const guchar *)auth, strlen(auth)); |
10568 | 109 g_free(auth); |
110 auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp); | |
111 g_free(tmp); | |
112 } | |
113 | |
114 return auth; | |
115 } | |
116 | |
10481 | 117 static ssize_t |
118 write_raw(MsnHttpConn *httpconn, const char *header, | |
119 const char *body, size_t body_len) | |
10463 | 120 { |
10481 | 121 char *buf; |
122 size_t buf_len; | |
10463 | 123 |
124 ssize_t s; | |
125 ssize_t res; /* result of the write operation */ | |
126 | |
127 #ifdef MSN_DEBUG_HTTP | |
10481 | 128 gaim_debug_misc("msn", "Writing HTTP (header): {%s}\n", header); |
10463 | 129 #endif |
130 | |
10481 | 131 buf = g_strdup_printf("%s\r\n", header); |
132 buf_len = strlen(buf); | |
133 | |
134 if (body != NULL) | |
135 { | |
136 buf = g_realloc(buf, buf_len + body_len); | |
137 memcpy(buf + buf_len, body, body_len); | |
138 buf_len += body_len; | |
139 } | |
140 | |
10463 | 141 s = 0; |
142 | |
143 do | |
144 { | |
11340
e9d0d944b9d2
[gaim-migrate @ 13553]
Richard Laager <rlaager@wiktel.com>
parents:
11137
diff
changeset
|
145 res = write(httpconn->fd, buf + s, buf_len - s); |
10463 | 146 if (res >= 0) |
147 { | |
148 s += res; | |
149 } | |
150 else if (errno != EAGAIN) | |
151 { | |
10481 | 152 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE); |
10463 | 153 return -1; |
154 } | |
10481 | 155 } while (s < buf_len); |
156 | |
157 g_free(buf); | |
10463 | 158 |
159 return s; | |
160 } | |
161 | |
12323
fc464a0abccc
[gaim-migrate @ 14627]
Richard Laager <rlaager@wiktel.com>
parents:
12213
diff
changeset
|
162 static void |
10463 | 163 msn_httpconn_poll(MsnHttpConn *httpconn) |
164 { | |
10481 | 165 char *header; |
10568 | 166 char *auth; |
10463 | 167 int r; |
168 | |
169 g_return_if_fail(httpconn != NULL); | |
170 | |
171 if (httpconn->waiting_response || | |
172 httpconn->queue != NULL) | |
173 { | |
174 return; | |
175 } | |
176 | |
10568 | 177 auth = msn_httpconn_proxy_auth(httpconn); |
178 | |
10481 | 179 header = g_strdup_printf( |
10463 | 180 "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n" |
181 "Accept: */*\r\n" | |
182 "Accept-Language: en-us\r\n" | |
183 "User-Agent: MSMSGS\r\n" | |
184 "Host: %s\r\n" | |
185 "Proxy-Connection: Keep-Alive\r\n" | |
10568 | 186 "%s" /* Proxy auth */ |
10463 | 187 "Connection: Keep-Alive\r\n" |
188 "Pragma: no-cache\r\n" | |
189 "Content-Type: application/x-msn-messenger\r\n" | |
10481 | 190 "Content-Length: 0\r\n", |
10463 | 191 httpconn->host, |
192 httpconn->full_session_id, | |
10568 | 193 httpconn->host, |
194 auth ? auth : ""); | |
195 | |
196 if (auth != NULL) | |
197 g_free(auth); | |
10463 | 198 |
10481 | 199 r = write_raw(httpconn, header, NULL, -1); |
10463 | 200 |
10481 | 201 g_free(header); |
10463 | 202 |
203 if (r > 0) | |
204 { | |
205 httpconn->waiting_response = TRUE; | |
206 httpconn->dirty = FALSE; | |
207 } | |
208 } | |
209 | |
210 static gboolean | |
10543 | 211 do_poll(gpointer data) |
10463 | 212 { |
213 MsnHttpConn *httpconn; | |
214 | |
215 httpconn = data; | |
216 | |
10568 | 217 g_return_val_if_fail(httpconn != NULL, TRUE); |
218 | |
10463 | 219 #if 0 |
220 gaim_debug_info("msn", "polling from %s\n", httpconn->session_id); | |
221 #endif | |
222 | |
10568 | 223 if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL)) |
224 { | |
225 gaim_debug_warning("msn", "Attempted HTTP poll before session is established\n"); | |
226 return TRUE; | |
227 } | |
228 | |
10463 | 229 if (httpconn->dirty) |
230 msn_httpconn_poll(httpconn); | |
231 | |
232 return TRUE; | |
233 } | |
234 | |
235 static void | |
236 connect_cb(gpointer data, gint source, GaimInputCondition cond) | |
237 { | |
238 MsnHttpConn *httpconn = data; | |
239 | |
240 httpconn->fd = source; | |
241 | |
242 if (source > 0) | |
243 { | |
244 httpconn->inpa = gaim_input_add(httpconn->fd, GAIM_INPUT_READ, | |
245 read_cb, data); | |
246 | |
10543 | 247 httpconn->timer = gaim_timeout_add(2000, do_poll, httpconn); |
10463 | 248 |
249 httpconn->waiting_response = FALSE; | |
250 msn_httpconn_process_queue(httpconn); | |
251 } | |
252 else | |
253 { | |
254 gaim_debug_error("msn", "HTTP: Connection error\n"); | |
10481 | 255 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT); |
10463 | 256 } |
257 } | |
258 | |
259 gboolean | |
260 msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port) | |
261 { | |
262 int r; | |
263 | |
264 g_return_val_if_fail(httpconn != NULL, FALSE); | |
265 g_return_val_if_fail(host != NULL, FALSE); | |
266 g_return_val_if_fail(port > 0, FALSE); | |
267 | |
268 if (httpconn->connected) | |
269 msn_httpconn_disconnect(httpconn); | |
270 | |
271 r = gaim_proxy_connect(httpconn->session->account, | |
272 "gateway.messenger.hotmail.com", 80, connect_cb, | |
273 httpconn); | |
274 | |
275 if (r == 0) | |
276 { | |
277 httpconn->waiting_response = TRUE; | |
278 httpconn->connected = TRUE; | |
279 } | |
280 | |
281 return httpconn->connected; | |
282 } | |
283 | |
284 void | |
285 msn_httpconn_disconnect(MsnHttpConn *httpconn) | |
286 { | |
287 g_return_if_fail(httpconn != NULL); | |
10481 | 288 |
289 if (!httpconn->connected) | |
290 return; | |
10463 | 291 |
292 if (httpconn->timer) | |
293 gaim_timeout_remove(httpconn->timer); | |
294 | |
295 httpconn->timer = 0; | |
296 | |
297 if (httpconn->inpa > 0) | |
298 { | |
299 gaim_input_remove(httpconn->inpa); | |
300 httpconn->inpa = 0; | |
301 } | |
302 | |
303 close(httpconn->fd); | |
304 | |
305 httpconn->rx_buf = NULL; | |
306 httpconn->rx_len = 0; | |
307 | |
308 httpconn->connected = FALSE; | |
309 | |
310 /* msn_servconn_disconnect(httpconn->servconn); */ | |
311 } | |
312 | |
313 static void | |
314 read_cb(gpointer data, gint source, GaimInputCondition cond) | |
315 { | |
316 MsnHttpConn *httpconn; | |
317 MsnServConn *servconn; | |
318 MsnSession *session; | |
319 char buf[MSN_BUF_LEN]; | |
320 char *cur, *end, *old_rx_buf; | |
321 int len, cur_len; | |
322 char *result_msg = NULL; | |
323 size_t result_len = 0; | |
324 gboolean error; | |
325 | |
326 httpconn = data; | |
327 servconn = NULL; | |
328 session = httpconn->session; | |
329 | |
330 len = read(httpconn->fd, buf, sizeof(buf) - 1); | |
331 | |
332 if (len <= 0) | |
333 { | |
334 gaim_debug_error("msn", "HTTP: Read error\n"); | |
10481 | 335 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); |
10463 | 336 |
337 return; | |
338 } | |
339 | |
340 buf[len] = '\0'; | |
341 | |
342 httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1); | |
343 memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1); | |
344 httpconn->rx_len += len; | |
345 | |
346 if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len, | |
347 &result_msg, &result_len, &error)) | |
348 { | |
10568 | 349 /* We must wait for more input, or something went wrong */ |
350 if (error) | |
351 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); | |
10463 | 352 |
353 return; | |
354 } | |
355 | |
356 httpconn->servconn->processing = FALSE; | |
357 | |
358 servconn = httpconn->servconn; | |
359 | |
360 if (error) | |
361 { | |
362 gaim_debug_error("msn", "HTTP: Special error\n"); | |
10481 | 363 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); |
10463 | 364 |
365 return; | |
366 } | |
367 | |
10533 | 368 if (httpconn->rx_buf != NULL) |
369 g_free(httpconn->rx_buf); | |
370 httpconn->rx_buf = NULL; | |
371 httpconn->rx_len = 0; | |
372 | |
10463 | 373 if (result_len == 0) |
374 { | |
375 /* Nothing to do here */ | |
376 #if 0 | |
377 gaim_debug_info("msn", "HTTP: nothing to do here\n"); | |
378 #endif | |
10481 | 379 g_free(result_msg); |
10463 | 380 return; |
381 } | |
382 | |
10533 | 383 if (servconn->rx_buf != NULL) |
384 g_free(servconn->rx_buf); | |
10463 | 385 servconn->rx_buf = result_msg; |
386 servconn->rx_len = result_len; | |
387 | |
388 end = old_rx_buf = servconn->rx_buf; | |
389 | |
390 servconn->processing = TRUE; | |
391 | |
392 do | |
393 { | |
394 cur = end; | |
395 | |
396 if (servconn->payload_len) | |
397 { | |
398 if (servconn->payload_len > servconn->rx_len) | |
399 /* The payload is still not complete. */ | |
400 break; | |
401 | |
402 cur_len = servconn->payload_len; | |
403 end += cur_len; | |
404 } | |
405 else | |
406 { | |
407 end = strstr(cur, "\r\n"); | |
408 | |
409 if (end == NULL) | |
410 /* The command is still not complete. */ | |
411 break; | |
412 | |
413 *end = '\0'; | |
414 end += 2; | |
415 cur_len = end - cur; | |
416 } | |
417 | |
418 servconn->rx_len -= cur_len; | |
419 | |
420 if (servconn->payload_len) | |
421 { | |
422 msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len); | |
423 servconn->payload_len = 0; | |
424 } | |
425 else | |
426 { | |
427 msn_cmdproc_process_cmd_text(servconn->cmdproc, cur); | |
428 } | |
429 } while (servconn->connected && servconn->rx_len > 0); | |
430 | |
431 if (servconn->connected) | |
432 { | |
433 if (servconn->rx_len > 0) | |
434 servconn->rx_buf = g_memdup(cur, servconn->rx_len); | |
435 else | |
436 servconn->rx_buf = NULL; | |
437 } | |
438 | |
439 servconn->processing = FALSE; | |
440 | |
441 if (servconn->wasted) | |
442 msn_servconn_destroy(servconn); | |
443 | |
444 g_free(old_rx_buf); | |
445 } | |
446 | |
447 void | |
448 msn_httpconn_process_queue(MsnHttpConn *httpconn) | |
449 { | |
450 if (httpconn->queue != NULL) | |
451 { | |
452 MsnHttpQueueData *queue_data; | |
453 | |
454 queue_data = (MsnHttpQueueData *)httpconn->queue->data; | |
455 | |
456 httpconn->queue = g_list_remove(httpconn->queue, queue_data); | |
457 | |
458 msn_httpconn_write(queue_data->httpconn, | |
10481 | 459 queue_data->data, |
10463 | 460 queue_data->size); |
461 | |
10481 | 462 g_free(queue_data->data); |
10463 | 463 g_free(queue_data); |
464 } | |
465 else | |
466 { | |
467 httpconn->dirty = TRUE; | |
468 } | |
469 } | |
470 | |
471 size_t | |
10481 | 472 msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t size) |
10463 | 473 { |
474 char *params; | |
10481 | 475 char *header; |
10568 | 476 char *auth; |
10463 | 477 gboolean first; |
478 const char *server_types[] = { "NS", "SB" }; | |
479 const char *server_type; | |
480 size_t r; /* result of the write operation */ | |
481 char *host; | |
482 MsnServConn *servconn; | |
483 | |
484 /* TODO: remove http data from servconn */ | |
485 | |
486 g_return_val_if_fail(httpconn != NULL, 0); | |
10481 | 487 g_return_val_if_fail(data != NULL, 0); |
10463 | 488 g_return_val_if_fail(size > 0, 0); |
489 | |
490 servconn = httpconn->servconn; | |
491 | |
492 if (httpconn->waiting_response) | |
493 { | |
494 MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1); | |
495 | |
496 queue_data->httpconn = httpconn; | |
10481 | 497 queue_data->data = g_memdup(data, size); |
10463 | 498 queue_data->size = size; |
499 | |
500 httpconn->queue = g_list_append(httpconn->queue, queue_data); | |
501 /* httpconn->dirty = TRUE; */ | |
502 | |
503 /* servconn->processing = TRUE; */ | |
504 | |
505 return size; | |
506 } | |
507 | |
508 first = httpconn->virgin; | |
509 server_type = server_types[servconn->type]; | |
510 | |
511 if (first) | |
512 { | |
513 host = "gateway.messenger.hotmail.com"; | |
514 | |
515 /* The first time servconn->host is the host we should connect to. */ | |
516 params = g_strdup_printf("Action=open&Server=%s&IP=%s", | |
517 server_type, | |
518 servconn->host); | |
519 } | |
520 else | |
521 { | |
522 /* The rest of the times servconn->host is the gateway host. */ | |
523 host = httpconn->host; | |
524 | |
10568 | 525 if (host == NULL || httpconn->full_session_id == NULL) |
526 { | |
527 gaim_debug_warning("msn", "Attempted HTTP write before session is established\n"); | |
528 return -1; | |
529 } | |
530 | |
10463 | 531 params = g_strdup_printf("SessionID=%s", |
532 httpconn->full_session_id); | |
533 } | |
534 | |
10568 | 535 auth = msn_httpconn_proxy_auth(httpconn); |
536 | |
10481 | 537 header = g_strdup_printf( |
10463 | 538 "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n" |
539 "Accept: */*\r\n" | |
540 "Accept-Language: en-us\r\n" | |
541 "User-Agent: MSMSGS\r\n" | |
542 "Host: %s\r\n" | |
543 "Proxy-Connection: Keep-Alive\r\n" | |
10568 | 544 "%s" /* Proxy auth */ |
10463 | 545 "Connection: Keep-Alive\r\n" |
546 "Pragma: no-cache\r\n" | |
547 "Content-Type: application/x-msn-messenger\r\n" | |
10481 | 548 "Content-Length: %d\r\n", |
10463 | 549 host, |
550 params, | |
551 host, | |
10568 | 552 auth ? auth : "", |
10463 | 553 (int)size); |
554 | |
555 g_free(params); | |
556 | |
10568 | 557 if (auth != NULL) |
558 g_free(auth); | |
559 | |
10481 | 560 r = write_raw(httpconn, header, data, size); |
10463 | 561 |
10481 | 562 g_free(header); |
10463 | 563 |
564 if (r > 0) | |
565 { | |
566 httpconn->virgin = FALSE; | |
567 httpconn->waiting_response = TRUE; | |
568 httpconn->dirty = FALSE; | |
569 } | |
570 | |
571 return r; | |
572 } | |
573 | |
574 gboolean | |
575 msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf, | |
576 size_t size, char **ret_buf, size_t *ret_size, | |
577 gboolean *error) | |
578 { | |
579 GaimConnection *gc; | |
580 const char *s, *c; | |
10481 | 581 char *header, *body; |
10463 | 582 const char *body_start; |
583 char *tmp; | |
584 size_t body_len = 0; | |
585 gboolean wasted = FALSE; | |
586 | |
587 g_return_val_if_fail(httpconn != NULL, FALSE); | |
588 g_return_val_if_fail(buf != NULL, FALSE); | |
589 g_return_val_if_fail(size > 0, FALSE); | |
590 g_return_val_if_fail(ret_buf != NULL, FALSE); | |
591 g_return_val_if_fail(ret_size != NULL, FALSE); | |
592 g_return_val_if_fail(error != NULL, FALSE); | |
593 | |
594 #if 0 | |
595 gaim_debug_info("msn", "HTTP: parsing data {%s}\n", buf); | |
596 #endif | |
597 | |
598 httpconn->waiting_response = FALSE; | |
599 | |
600 gc = gaim_account_get_connection(httpconn->session->account); | |
601 | |
602 /* Healthy defaults. */ | |
603 body = NULL; | |
604 | |
605 *ret_buf = NULL; | |
606 *ret_size = 0; | |
607 *error = FALSE; | |
608 | |
609 /* First, some tests to see if we have a full block of stuff. */ | |
610 if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) && | |
611 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) && | |
612 ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) && | |
613 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0))) | |
614 { | |
615 *error = TRUE; | |
616 | |
617 return FALSE; | |
618 } | |
619 | |
620 if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0) | |
621 { | |
622 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
623 return FALSE; | |
624 | |
625 s += 4; | |
626 | |
627 if (*s == '\0') | |
628 { | |
629 *ret_buf = g_strdup(""); | |
630 *ret_size = 0; | |
631 | |
632 msn_httpconn_process_queue(httpconn); | |
633 | |
634 return TRUE; | |
635 } | |
636 | |
637 buf = s; | |
638 size -= (s - buf); | |
639 } | |
640 | |
641 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
642 return FALSE; | |
643 | |
10718 | 644 s += 4; /* Skip \r\n */ |
10481 | 645 header = g_strndup(buf, s - buf); |
10463 | 646 body_start = s; |
647 body_len = size - (body_start - buf); | |
648 | |
12213 | 649 if ((s = gaim_strcasestr(header, "Content-Length: ")) != NULL) |
10463 | 650 { |
651 int tmp_len; | |
652 | |
653 s += strlen("Content-Length: "); | |
654 | |
655 if ((c = strchr(s, '\r')) == NULL) | |
656 { | |
10481 | 657 g_free(header); |
10463 | 658 |
659 return FALSE; | |
660 } | |
661 | |
662 tmp = g_strndup(s, c - s); | |
663 tmp_len = atoi(tmp); | |
664 g_free(tmp); | |
665 | |
666 if (body_len != tmp_len) | |
667 { | |
10481 | 668 g_free(header); |
10463 | 669 |
670 #if 0 | |
671 gaim_debug_warning("msn", | |
672 "body length (%d) != content length (%d)\n", | |
673 body_len, tmp_len); | |
674 #endif | |
675 | |
676 return FALSE; | |
677 } | |
678 } | |
679 | |
10481 | 680 body = g_malloc0(body_len + 1); |
681 memcpy(body, body_start, body_len); | |
10463 | 682 |
683 #ifdef MSN_DEBUG_HTTP | |
10481 | 684 gaim_debug_misc("msn", "Incoming HTTP buffer (header): {%s\r\n}\n", |
685 header); | |
10463 | 686 #endif |
687 | |
688 /* Now we should be able to process the data. */ | |
12213 | 689 if ((s = gaim_strcasestr(header, "X-MSN-Messenger: ")) != NULL) |
10463 | 690 { |
691 char *full_session_id, *gw_ip, *session_action; | |
692 char *t, *session_id; | |
693 char **elems, **cur, **tokens; | |
694 | |
695 full_session_id = gw_ip = session_action = NULL; | |
696 | |
697 s += strlen("X-MSN-Messenger: "); | |
698 | |
699 if ((c = strchr(s, '\r')) == NULL) | |
700 { | |
10481 | 701 msn_session_set_error(httpconn->session, |
702 MSN_ERROR_HTTP_MALFORMED, NULL); | |
10463 | 703 gaim_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}", |
704 buf); | |
705 | |
10481 | 706 g_free(body); |
10463 | 707 return FALSE; |
708 } | |
709 | |
710 tmp = g_strndup(s, c - s); | |
711 | |
712 elems = g_strsplit(tmp, "; ", 0); | |
713 | |
714 for (cur = elems; *cur != NULL; cur++) | |
715 { | |
716 tokens = g_strsplit(*cur, "=", 2); | |
717 | |
718 if (strcmp(tokens[0], "SessionID") == 0) | |
719 full_session_id = tokens[1]; | |
720 else if (strcmp(tokens[0], "GW-IP") == 0) | |
721 gw_ip = tokens[1]; | |
722 else if (strcmp(tokens[0], "Session") == 0) | |
723 session_action = tokens[1]; | |
724 | |
725 g_free(tokens[0]); | |
726 /* Don't free each of the tokens, only the array. */ | |
727 g_free(tokens); | |
728 } | |
729 | |
730 g_strfreev(elems); | |
731 | |
732 g_free(tmp); | |
733 | |
734 if ((session_action != NULL) && (strcmp(session_action, "close") == 0)) | |
735 wasted = TRUE; | |
736 | |
737 g_free(session_action); | |
738 | |
739 t = strchr(full_session_id, '.'); | |
740 session_id = g_strndup(full_session_id, t - full_session_id); | |
741 | |
742 if (!wasted) | |
743 { | |
10504 | 744 if (httpconn->full_session_id != NULL) |
10463 | 745 g_free(httpconn->full_session_id); |
746 | |
747 httpconn->full_session_id = full_session_id; | |
748 | |
10504 | 749 if (httpconn->session_id != NULL) |
10463 | 750 g_free(httpconn->session_id); |
751 | |
752 httpconn->session_id = session_id; | |
753 | |
10504 | 754 if (httpconn->host != NULL) |
10463 | 755 g_free(httpconn->host); |
756 | |
757 httpconn->host = gw_ip; | |
758 } | |
759 else | |
760 { | |
761 MsnServConn *servconn; | |
762 | |
763 /* It's going to die. */ | |
10504 | 764 /* poor thing */ |
10463 | 765 |
766 servconn = httpconn->servconn; | |
767 | |
10533 | 768 /* I'll be honest, I don't fully understand all this, but this |
769 * causes crashes, Stu. */ | |
770 /* if (servconn != NULL) | |
771 servconn->wasted = TRUE; */ | |
10463 | 772 |
773 g_free(full_session_id); | |
10504 | 774 g_free(session_id); |
10463 | 775 g_free(gw_ip); |
776 } | |
777 } | |
778 | |
10481 | 779 g_free(header); |
10463 | 780 |
781 *ret_buf = body; | |
782 *ret_size = body_len; | |
783 | |
784 msn_httpconn_process_queue(httpconn); | |
785 | |
786 return TRUE; | |
787 } |