Mercurial > pidgin
view src/protocols/msn/httpmethod.c @ 7864:dc80d4e5c3b0
[gaim-migrate @ 8518]
"Attached is a patch I wrote last night while trying to play with
docklet.c - it turns out that one of the signals doesn't have the right
parameter list (probably after Christian changed the signals some time).
It has been tested, rather simply with the fact that a debug statement
was not reached before, and is now, following the signal specs here:
http://gaim.sourceforge.net/api/conversation-signals.html#received-im-msg
I don't know if this needs to go through Robot101 (haven't seen him
terribly active of late), and if it does, I'll gladly relay it to him.
And yeah, I guess this was all inspired by my away msg at the time:
[:-P]
Well, I'm not that tired right now, and I think I'm going to work some
Merlot and coffee off with some coding and Oggs...
Oh yeah, and while I'm rambling about stuff irrelevant to the actual
code, I somehow dedicate this patch to the wonderful person for whom I
would like to be visually aware of their incoming messages..." --John B.
Silvestri
committer: Tailor Script <tailor@pidgin.im>
| author | Luke Schierer <lschiere@pidgin.im> |
|---|---|
| date | Sun, 14 Dec 2003 17:04:00 +0000 |
| parents | 99ffabc6ce73 |
| children | aa44049e8891 |
line wrap: on
line source
/** * @file httpmethod.c HTTP connection method * * gaim * * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "debug.h" #include "httpmethod.h" #define GET_NEXT(tmp) \ while (*(tmp) && *(tmp) != ' ' && *(tmp) != '\r') \ (tmp)++; \ if (*(tmp) != '\0') *(tmp)++ = '\0'; \ if (*(tmp) == '\n') (tmp)++; \ while (*(tmp) && *(tmp) == ' ') \ (tmp)++ #define GET_NEXT_LINE(tmp) \ while (*(tmp) && *(tmp) != '\r') \ (tmp)++; \ if (*(tmp) != '\0') *(tmp)++ = '\0'; \ if (*(tmp) == '\n') (tmp)++ typedef struct { MsnServConn *servconn; char *buffer; size_t size; const char *server_type; } MsnHttpQueueData; static gboolean http_poll(gpointer data) { MsnServConn *servconn = data; #if 0 gaim_debug_info("msn", "Polling server %s.\n", servconn->http_data->gateway_ip); #endif msn_http_servconn_poll(servconn); servconn->http_data->timer = 0; return FALSE; } static void stop_timer(MsnServConn *servconn) { if (servconn->http_data->timer) { g_source_remove(servconn->http_data->timer); servconn->http_data->timer = 0; } } static void start_timer(MsnServConn *servconn) { stop_timer(servconn); servconn->http_data->timer = g_timeout_add(5000, http_poll, servconn); } size_t msn_http_servconn_write(MsnServConn *servconn, const char *buf, size_t size, const char *server_type) { size_t s, needed; char *params; char *temp; gboolean first; int res; /* result of the write operation */ g_return_val_if_fail(servconn != NULL, 0); g_return_val_if_fail(buf != NULL, 0); g_return_val_if_fail(size > 0, 0); g_return_val_if_fail(servconn->http_data != NULL, 0); if (servconn->http_data->waiting_response || servconn->http_data->queue != NULL) { MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1); queue_data->servconn = servconn; queue_data->buffer = g_strdup(buf); queue_data->size = size; queue_data->server_type = server_type; servconn->http_data->queue = g_list_append(servconn->http_data->queue, queue_data); return size; } first = servconn->http_data->virgin; if (first) { if (server_type) { params = g_strdup_printf("Action=open&Server=%s&IP=%s", server_type, servconn->http_data->gateway_ip); } else { params = g_strdup_printf("Action=open&IP=%s", servconn->http_data->gateway_ip); } } else { params = g_strdup_printf("SessionID=%s", servconn->http_data->session_id); } temp = g_strdup_printf( "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n" "Accept: */*\r\n" "Accept-Language: en-us\r\n" "User-Agent: MSMSGS\r\n" "Host: %s\r\n" "Proxy-Connection: Keep-Alive\r\n" "Connection: Keep-Alive\r\n" "Pragma: no-cache\r\n" "Content-Type: application/x-msn-messenger\r\n" "Content-Length: %d\r\n" "\r\n" "%s", ((strcmp(server_type, "SB") == 0) && first ? "gateway.messenger.hotmail.com" : servconn->http_data->gateway_ip), params, servconn->http_data->gateway_ip, (int)size, buf); g_free(params); #if 1 gaim_debug_misc("msn", "Writing HTTP to fd %d: {%s}\n", servconn->fd, temp); #endif s = 0; needed = strlen(temp); do { res = write(servconn->fd, temp, needed); if (res >= 0) s += res; else if (errno != EAGAIN) { char *msg = g_strdup_printf("Unable to write to MSN server via HTTP (error %d)", errno); gaim_connection_error(servconn->session->account->gc, msg); g_free(msg); return -1; } } while (s < needed); g_free(temp); servconn->http_data->waiting_response = TRUE; servconn->http_data->virgin = FALSE; stop_timer(servconn); return s; } void msn_http_servconn_poll(MsnServConn *servconn) { size_t s; char *temp; g_return_if_fail(servconn != NULL); g_return_if_fail(servconn->http_data != NULL); if (servconn->http_data->waiting_response || servconn->http_data->queue != NULL) { return; } temp = g_strdup_printf( "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n" "Accept: */*\r\n" "Accept-Language: en-us\r\n" "User-Agent: MSMSGS\r\n" "Host: %s\r\n" "Proxy-Connection: Keep-Alive\r\n" "Connection: Keep-Alive\r\n" "Pragma: no-cache\r\n" "Content-Type: application/x-msn-messenger\r\n" "Content-Length: 0\r\n" "\r\n", servconn->http_data->gateway_ip, servconn->http_data->session_id, servconn->http_data->gateway_ip); #if 0 gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp); #endif s = write(servconn->fd, temp, strlen(temp)); g_free(temp); servconn->http_data->waiting_response = TRUE; stop_timer(servconn); if (s <= 0) gaim_connection_error(servconn->session->account->gc, _("Write error")); } gboolean msn_http_servconn_parse_data(MsnServConn *servconn, const char *buf, size_t size, char **ret_buf, size_t *ret_size, gboolean *error) { GaimConnection *gc; const char *s, *c; char *headers, *body; char *tmp; size_t len = 0; g_return_val_if_fail(servconn != NULL, FALSE); g_return_val_if_fail(buf != NULL, FALSE); g_return_val_if_fail(size > 0, FALSE); g_return_val_if_fail(ret_buf != NULL, FALSE); g_return_val_if_fail(ret_size != NULL, FALSE); g_return_val_if_fail(error != NULL, FALSE); #if 0 gaim_debug_info("msn", "parsing data {%s} from fd %d\n", buf, servconn->fd); #endif servconn->http_data->waiting_response = FALSE; gc = gaim_account_get_connection(servconn->session->account); /* Healthy defaults. */ *ret_buf = NULL; *ret_size = 0; *error = FALSE; /* First, some tests to see if we have a full block of stuff. */ if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) && (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) && ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) && (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0))) { *error = TRUE; return FALSE; } if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0) { if ((s = strstr(buf, "\r\n\r\n")) == NULL) return FALSE; s += 4; if (*s == '\0') { *ret_buf = g_strdup(""); *ret_size = 0; return TRUE; } buf = s; size -= (s - buf); } if ((s = strstr(buf, "\r\n\r\n")) == NULL) return FALSE; headers = g_strndup(buf, s - buf); s += 4; /* Skip \r\n */ body = g_strndup(s, size - (s - buf)); #if 0 gaim_debug_misc("msn", "Incoming HTTP buffer: {%s\r\n%s}", headers, body); #endif if ((s = strstr(headers, "Content-Length: ")) != NULL) { s += strlen("Content-Length: "); if ((c = strchr(s, '\r')) == NULL) { g_free(headers); g_free(body); return FALSE; } tmp = g_strndup(s, c - s); len = atoi(tmp); g_free(tmp); if (strlen(body) != len) { g_free(headers); g_free(body); gaim_debug_warning("msn", "body length (%d) != content length (%d)\n", strlen(body), len); return FALSE; } } /* Now we should be able to process the data. */ if ((s = strstr(headers, "X-MSN-Messenger: ")) != NULL) { char *session_id, *gw_ip; char *c2, *s2; s += strlen("X-MSN-Messenger: "); if ((c = strchr(s, '\r')) == NULL) { gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); return FALSE; } tmp = g_strndup(s, c - s); /* Find the value for the Session ID */ if ((s2 = strchr(tmp, '=')) == NULL) { gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); return FALSE; } s2++; /* Terminate the ; so we can g_strdup it. */ if ((c2 = strchr(s2, ';')) == NULL) { gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); return FALSE; } *c2 = '\0'; c2++; /* Now grab that session ID. */ session_id = g_strdup(s2); /* Continue to the gateway IP */ if ((s2 = strchr(c2, '=')) == NULL) { gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); return FALSE; } s2++; /* Grab the gateway IP */ gw_ip = g_strdup(s2); g_free(tmp); /* Set the new data. */ if (servconn->http_data->session_id != NULL) g_free(servconn->http_data->session_id); if (servconn->http_data->old_gateway_ip != NULL) g_free(servconn->http_data->old_gateway_ip); servconn->http_data->old_gateway_ip = servconn->http_data->gateway_ip; servconn->http_data->session_id = session_id; servconn->http_data->gateway_ip = gw_ip; } g_free(headers); *ret_buf = body; *ret_size = len; if (servconn->http_data->queue != NULL) { MsnHttpQueueData *queue_data; queue_data = (MsnHttpQueueData *)servconn->http_data->queue->data; servconn->http_data->queue = g_list_remove(servconn->http_data->queue, queue_data); msn_http_servconn_write(queue_data->servconn, queue_data->buffer, queue_data->size, queue_data->server_type); g_free(queue_data->buffer); g_free(queue_data); } else start_timer(servconn); return TRUE; }
