Mercurial > pidgin
view src/protocols/msn/httpmethod.c @ 10108:f0100b414d98
[gaim-migrate @ 11141]
Two things:
a. Added Enter as a gtk_binding to GtkIMHtml. This fixes everything.
Input methods now work. The "Enter sends" and "Ctrl-Enter sends" preferences
were removed and defaulted to yes and no respectively, BUT, in a very super-cool
turn of events, you can now add your own bindings to .gtkrc to make WHATEVER
YOU WANT send. Awesome. Someone should use g_signal_accumulator_true_handled
or something to make profiles and away messages able to insert newlines.
b. Removed "Use multi-colored screennames in chats," defaulted to yes, and
wrote a nifty algorithm to automatically adjust the colors to accomodate the
background (see http://gaim.sf.net/sean/porn-chat.png). People should play
around and tweak it a bit. The algorithm takes into consideration the
luminosity of the current background and the base hue to use for the screenname
in generating the new colors. Note that it does this while maintaining the hues.
Someone should optimize this so it skips over the floating point arithmatic when
the background color is white.
committer: Tailor Script <tailor@pidgin.im>
| author | Sean Egan <seanegan@gmail.com> |
|---|---|
| date | Sun, 17 Oct 2004 23:55:49 +0000 |
| parents | ab6636c5a136 |
| children |
line wrap: on
line source
/** * @file httpmethod.c HTTP connection method * * gaim * * Gaim is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * 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) { MsnSession *session; GList *l; session = data; for (l = session->switches; l != NULL; l = l->next) { MsnSwitchBoard *swboard; swboard = l->data; g_return_val_if_fail(swboard->servconn->http_data != NULL, FALSE); if (swboard->servconn->http_data->dirty) { #if 0 gaim_debug_info("msn", "Polling server %s.\n", servconn->http_data->gateway_host); #endif msn_http_servconn_poll(swboard->servconn); } } if (session->notification->servconn->http_data->dirty) msn_http_servconn_poll(session->notification->servconn); return TRUE; } static void stop_timer(MsnSession *session) { if (session->http_poll_timer) { gaim_timeout_remove(session->http_poll_timer); session->http_poll_timer = 0; } } static void start_timer(MsnSession *session) { stop_timer(session); session->http_poll_timer = gaim_timeout_add(2000, http_poll, session); } void msn_http_session_init(MsnSession *session) { g_return_if_fail(session != NULL); start_timer(session); } void msn_http_session_uninit(MsnSession *session) { g_return_if_fail(session != NULL); stop_timer(session); } 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) { 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_host); } else { params = g_strdup_printf("Action=open&IP=%s", servconn->http_data->gateway_host); } } 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_host), params, servconn->http_data->gateway_host, (int)size, buf); g_free(params); #if 0 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; servconn->http_data->dirty = FALSE; 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_host, servconn->http_data->session_id, servconn->http_data->gateway_host); #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; servconn->http_data->dirty = FALSE; 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_host != NULL) g_free(servconn->http_data->old_gateway_host); servconn->http_data->old_gateway_host = servconn->http_data->gateway_host; servconn->http_data->session_id = session_id; servconn->http_data->gateway_host = 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 servconn->http_data->dirty = TRUE; return TRUE; }
