static void nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { MsnNexus *nexus = data; MsnSession *session = nexus->session; const char *ticket; char *response; if (resp == NULL) { msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect")); return; } if (!nexus_parse_collection(nexus, -1, xmlnode_get_child(resp->xml, "Body/RequestSecurityTokenResponseCollection"))) { msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Invalid response")); return; } ticket = msn_nexus_get_token_str(nexus, MSN_AUTH_MESSENGER); response = msn_rps_encrypt(nexus); msn_got_login_params(session, ticket, response); g_free(response); }
static void out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { if (!g_ascii_strcasecmp(cmd->params[0], "OTH")) msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER, NULL); else if (!g_ascii_strcasecmp(cmd->params[0], "SSD")) msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL); }
static void close_cb (PecanNode *conn, MsnNotification *notification) { char *tmp; { const char *reason = NULL; if (conn->error) { reason = conn->error->message; pecan_error ("connection error: (NS):reason=[%s]", reason); tmp = pecan_strdup_printf (_("Error on notification server:\n%s"), reason); g_clear_error (&conn->error); } else { pecan_error ("connection error: (NS)"); tmp = pecan_strdup_printf (_("Error on notification server:\nUnknown")); } } pecan_node_close (PECAN_NODE (notification->conn)); notification->closed = TRUE; msn_session_set_error (notification->session, MSN_ERROR_SERVCONN, tmp); g_free (tmp); }
static void ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; gboolean protocol_supported = FALSE; const gchar *proto_str; guint i; session = cmdproc->session; proto_str = "MSNP12"; for (i = 1; i < cmd->param_count; i++) { if (!strcmp(cmd->params[i], proto_str)) { protocol_supported = TRUE; break; } } if (!protocol_supported) { msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL, NULL); return; } msn_cmdproc_send(cmdproc, "CVR", "0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS %s", msn_session_get_username(session)); }
static void error_handler (MsnCmdProc *cmdproc, MsnTransaction *trans, gint error) { MsnNotification *notification; gchar *reason; notification = cmdproc->data; g_return_if_fail (notification); reason = pecan_error_to_string (error); pecan_error ("connection error: (NS):reason=[%s]", reason); switch (error) { case 913: case 208: /* non-fatal */ break; default: { char *tmp; tmp = pecan_strdup_printf (_("Error on notification server:\n%s"), reason); msn_session_set_error (notification->session, MSN_ERROR_SERVCONN, tmp); g_free (tmp); } } g_free (reason); }
static void login_open_cb(PnNode *conn, gpointer data) { MsnNexus *nexus = data; MsnSession *session; const char *username, *password; char *req, *head, *tail; guint32 ctint; GIOStatus status = G_IO_STATUS_NORMAL; g_return_if_fail(conn); g_signal_handler_disconnect(conn, nexus->open_handler); nexus->open_handler = 0; session = nexus->session; username = msn_session_get_username(session); password = msn_session_get_password(session); ctint = strtoul((char *) g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200; head = g_strdup_printf("GET %s HTTP/1.1\r\n" "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s", nexus->login_path, (char *) g_hash_table_lookup(nexus->challenge_data, "ru"), purple_url_encode(username)); tail = g_strdup_printf("lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%" G_GUINT32_FORMAT ",kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" "User-Agent: MSMSGS\r\n" "Host: %s\r\n" "Connection: Keep-Alive\r\n" "Cache-Control: no-cache\r\n", get_key(nexus->challenge_data, "lc"), get_key(nexus->challenge_data, "id"), get_key(nexus->challenge_data, "tw"), get_key(nexus->challenge_data, "fs"), get_key(nexus->challenge_data, "ru"), ctint, get_key(nexus->challenge_data, "kpp"), get_key(nexus->challenge_data, "kv"), get_key(nexus->challenge_data, "ver"), get_key(nexus->challenge_data, "tpf"), nexus->login_host); req = g_strdup_printf("%s,pwd=%s,%s\r\n", head, purple_url_encode(password), tail); g_free(head); g_free(tail); status = pn_node_write(conn, req, strlen(req), NULL, NULL); if (status != G_IO_STATUS_NORMAL) { msn_session_set_error(nexus->session, MSN_ERROR_AUTH, _("nexus stream error")); } g_free(req); }
static void ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; GaimAccount *account; gboolean protocol_supported = FALSE; char proto_str[8]; size_t i; session = cmdproc->session; account = session->account; g_snprintf(proto_str, sizeof(proto_str), "MSNP%d", session->protocol_ver); for (i = 1; i < cmd->param_count; i++) { if (!strcmp(cmd->params[i], proto_str)) { protocol_supported = TRUE; break; } } if (!protocol_supported) { msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL, NULL); return; } msn_cmdproc_send(cmdproc, "CVR", "0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS %s", gaim_account_get_username(account)); }
static gboolean msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response) { xmlnode *body = xmlnode_get_child(response->xml, "Body"); xmlnode *fault = xmlnode_get_child(response->xml, "Fault"); if (fault) { xmlnode *faultcode = xmlnode_get_child(fault, "faultcode"); if (faultcode != NULL) { char *faultdata = xmlnode_get_data(faultcode); if (faultdata && g_str_equal(faultdata, "psf:Redirect")) { xmlnode *url = xmlnode_get_child(fault, "redirectUrl"); if (url) { char *urldata = xmlnode_get_data(url); if (urldata) msn_soap_handle_redirect(conn, urldata); g_free(urldata); } g_free(faultdata); msn_soap_message_destroy(response); return TRUE; } else if (faultdata && g_str_equal(faultdata, "wsse:FailedAuthentication")) { xmlnode *reason = xmlnode_get_child(fault, "faultstring"); char *reasondata = NULL; if (reason) reasondata = xmlnode_get_data(reason); msn_soap_connection_sanitize(conn, TRUE); msn_session_set_error(conn->session, MSN_ERROR_AUTH, reasondata); g_free(reasondata); g_free(faultdata); msn_soap_message_destroy(response); return FALSE; } g_free(faultdata); } } if (fault || body) { if (conn->current_request) { MsnSoapRequest *request = conn->current_request; conn->current_request = NULL; request->cb(request->message, response, request->cb_data); msn_soap_request_destroy(request, FALSE); } msn_soap_message_destroy(response); } return TRUE; }
static void login_read_cb(PnNode *conn, gpointer data) { MsnNexus *nexus = data; GIOStatus status = G_IO_STATUS_NORMAL; gchar *str = NULL; if (!nexus->header) nexus->header = g_string_new(NULL); g_object_ref (conn); while (nexus->parser_state == 0) { gsize terminator_pos; status = pn_parser_read_line(nexus->parser, &str, NULL, &terminator_pos, NULL); if (status == G_IO_STATUS_AGAIN) goto leave; if (status != G_IO_STATUS_NORMAL) { msn_session_set_error(nexus->session, MSN_ERROR_AUTH, _("nexus stream error")); goto leave; } if (str) { str[terminator_pos] = '\0'; nexus->header = g_string_append(nexus->header, str); if (str[0] == '\0') { gchar *tmp; nexus->parser_state++; tmp = g_string_free(nexus->header, FALSE); nexus->header = NULL; got_header(nexus, tmp); g_free(tmp); g_free(str); break; } g_free(str); } } leave: g_object_unref(conn); }
void msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error, const char *reason) { MsnSession *session = servconn->session; MsnServConnType type = servconn->type; const char *names[] = { "Notification", "Switchboard" }; const char *name; name = names[type]; if (reason == NULL) { switch (error) { case MSN_SERVCONN_ERROR_CONNECT: reason = _("Unable to connect"); break; case MSN_SERVCONN_ERROR_WRITE: reason = _("Writing error"); break; case MSN_SERVCONN_ERROR_READ: reason = _("Reading error"); break; default: reason = _("Unknown error"); break; } } purple_debug_error("msn", "Connection error from %s server (%s): %s\n", name, servconn->host, reason); if (type == MSN_SERVCONN_SB) { MsnSwitchBoard *swboard; swboard = servconn->cmdproc->data; if (swboard != NULL) swboard->error = MSN_SB_ERROR_CONNECTION; } /* servconn->disconnect_cb may destroy servconn, so don't use it again */ msn_servconn_disconnect(servconn); if (type == MSN_SERVCONN_NS) { char *tmp = g_strdup_printf(_("Connection error from %s server:\n%s"), name, reason); msn_session_set_error(session, MSN_ERROR_SERVCONN, tmp); g_free(tmp); } }
static void login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) { MsnNexus *nexus; MsnSession *session; nexus = data; g_return_if_fail(nexus != NULL); nexus->gsc = NULL; session = nexus->session; g_return_if_fail(session != NULL); msn_session_set_error(session, MSN_ERROR_AUTH, _("Unable to connect")); /* the above line will result in nexus being destroyed, so we don't want * to destroy it here, or we'd crash */ }
static void close_cb(PnNode *conn, MsnNexus *nexus) { char *tmp; if (conn->error) { const char *reason; reason = conn->error->message; tmp = g_strdup_printf(_("error on nexus server: %s"), reason); g_clear_error(&conn->error); } else { tmp = g_strdup_printf(_("error on nexus server")); } msn_session_set_error(nexus->session, MSN_ERROR_AUTH, tmp); g_free(tmp); }
static void syn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; int total_users; session = cmdproc->session; if (cmd->param_count == 2) { /* * This can happen if we sent a SYN with an up-to-date * buddy list revision, but we send 0 to get a full list. * So, error out. */ msn_session_set_error(cmdproc->session, MSN_ERROR_BAD_BLIST, NULL); return; } total_users = atoi(cmd->params[2]); if (total_users == 0) { msn_session_finish_login(session); } else { /* syn_table */ MsnSync *sync; sync = msn_sync_new(session); sync->total_users = total_users; sync->old_cbs_table = cmdproc->cbs_table; session->sync = sync; cmdproc->cbs_table = sync->cbs_table; } }
static void nexus_open_cb(PnNode *conn, gpointer data) { MsnNexus *nexus = data; const gchar *req = "GET /rdr/pprdr.asp\r\n\r\n"; GIOStatus status = G_IO_STATUS_NORMAL; g_return_if_fail(conn); g_signal_handler_disconnect(conn, nexus->open_handler); nexus->open_handler = 0; g_signal_handler_disconnect(conn, nexus->error_handler); nexus->error_handler = 0; pn_node_write(conn, req, strlen(req), NULL, NULL); if (status != G_IO_STATUS_NORMAL) { msn_session_set_error(nexus->session, MSN_ERROR_AUTH, _("nexus stream error")); } }
static void usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) { MsnErrorType msnerr = 0; switch (error) { case 500: case 601: case 910: case 921: msnerr = MSN_ERROR_SERV_UNAVAILABLE; break; case 911: msnerr = MSN_ERROR_AUTH; break; default: return; break; } msn_session_set_error(cmdproc->session, msnerr, NULL); }
static void got_header(MsnNexus *nexus, const gchar *header) { MsnSession *session = nexus->session; if (strstr(header, "HTTP/1.1 200 OK")) { char *base, *c; char *login_params; base = strstr(header, "Authentication-Info: "); if (!base) goto parse_error; base = strstr(base, "from-PP='"); base += strlen("from-PP='"); c = strchr(base, '\''); login_params = g_strndup(base, c - base); msn_got_login_params(session, login_params); g_free(login_params); msn_nexus_destroy(nexus); session->nexus = NULL; return; } else if (strstr(header, "HTTP/1.1 302")) { /* Redirect. */ char *location, *c; location = strstr(header, "Location: "); if (!location) goto parse_error; location = strchr(location, ' ') + 1; if ((c = strchr(location, '\r'))) *c = '\0'; /* Skip the http:// */ if ((c = strchr(location, '/'))) location = c + 2; if ((c = strchr(location, '/'))) { g_free(nexus->login_path); nexus->login_path = g_strdup(c); *c = '\0'; } g_free(nexus->login_host); nexus->login_host = g_strdup(location); pn_info("reconnecting to '%s'", nexus->login_host); pn_parser_reset(nexus->parser); nexus->parser_state = 0; nexus->open_handler = g_signal_connect(nexus->conn, "open", G_CALLBACK(login_open_cb), nexus); pn_node_connect(nexus->conn, nexus->login_host, 443); return; } else if (strstr(header, "HTTP/1.1 401 Unauthorized")) { const char *tmp; gchar *error = NULL; if ((tmp = strstr(header, "WWW-Authenticate"))) { if ((tmp = strstr(tmp, "cbtxt="))) { const char *c; char *tmp2; tmp += strlen("cbtxt="); c = strchr(tmp, '\n'); if (!c) c = tmp + strlen(tmp); tmp2 = g_strndup(tmp, c - tmp); error = pn_url_decode(tmp2); g_free(tmp2); if ((tmp2 = strstr(error, " Do one of the following or try again:")) != NULL) *tmp2 = '\0'; } } msn_session_set_error(session, MSN_ERROR_AUTH, error); g_free(error); return; } else if (strstr(header, "HTTP/1.1 503 Service Unavailable")) { msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL); return; } parse_error: msn_session_set_error(session, MSN_ERROR_AUTH, _("nexus parse error")); }
static void nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond) { MsnNexus *nexus = data; MsnSession *session; int len; session = nexus->session; g_return_if_fail(session != NULL); if (nexus->input_handler == 0) /* TODO: Use purple_ssl_input_add()? */ nexus->input_handler = purple_input_add(nexus->gsc->fd, PURPLE_INPUT_READ, nexus_login_written_cb, nexus); len = msn_ssl_read(nexus); if (len < 0 && errno == EAGAIN) return; else if (len < 0) { purple_input_remove(nexus->input_handler); nexus->input_handler = 0; g_free(nexus->read_buf); nexus->read_buf = NULL; nexus->read_len = 0; /* TODO: error handling */ return; } if (g_strstr_len(nexus->read_buf, nexus->read_len, "\r\n\r\n") == NULL) return; purple_input_remove(nexus->input_handler); nexus->input_handler = 0; purple_ssl_close(nexus->gsc); nexus->gsc = NULL; pecan_log ("ssl buffer: [%s]", nexus->read_buf); if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL) { /* Redirect. */ char *location, *c; location = strstr(nexus->read_buf, "Location: "); if (location == NULL) { g_free(nexus->read_buf); nexus->read_buf = NULL; nexus->read_len = 0; return; } location = strchr(location, ' ') + 1; if ((c = strchr(location, '\r')) != NULL) *c = '\0'; /* Skip the http:// */ if ((c = strchr(location, '/')) != NULL) location = c + 2; if ((c = strchr(location, '/')) != NULL) { g_free(nexus->login_path); nexus->login_path = g_strdup(c); *c = '\0'; } g_free(nexus->login_host); nexus->login_host = g_strdup(location); nexus->gsc = purple_ssl_connect(session->account, nexus->login_host, PURPLE_SSL_DEFAULT_PORT, login_connect_cb, login_error_cb, nexus); } else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL) { const char *error; if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL) { if ((error = strstr(error, "cbtxt=")) != NULL) { const char *c; char *temp; error += strlen("cbtxt="); if ((c = strchr(error, '\n')) == NULL) c = error + strlen(error); temp = g_strndup(error, c - error); error = purple_url_decode(temp); g_free(temp); if ((temp = strstr(error, " Do one of the following or try again:")) != NULL) *temp = '\0'; } } msn_session_set_error(session, MSN_ERROR_AUTH, error); } else if (strstr(nexus->read_buf, "HTTP/1.1 503 Service Unavailable")) { msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL); } else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")) { char *base, *c; char *login_params; #if 0 /* All your base are belong to us. */ base = buffer; /* For great cookie! */ while ((base = strstr(base, "Set-Cookie: ")) != NULL) { base += strlen("Set-Cookie: "); c = strchr(base, ';'); session->login_cookies = g_list_append(session->login_cookies, g_strndup(base, c - base)); } #endif base = strstr(nexus->read_buf, "Authentication-Info: "); g_return_if_fail(base != NULL); base = strstr(base, "from-PP='"); base += strlen("from-PP='"); c = strchr(base, '\''); login_params = g_strndup(base, c - base); msn_got_login_params(session, login_params); g_free(login_params); msn_nexus_destroy(nexus); session->nexus = NULL; return; } g_free(nexus->read_buf); nexus->read_buf = NULL; nexus->read_len = 0; }
static void nexus_read_cb(PnNode *conn, gpointer data) { MsnNexus *nexus = data; GIOStatus status = G_IO_STATUS_NORMAL; gchar *str = NULL; while (nexus->parser_state == 0) { gsize terminator_pos; status = pn_parser_read_line(nexus->parser, &str, NULL, &terminator_pos, NULL); if (status == G_IO_STATUS_AGAIN) return; if (status != G_IO_STATUS_NORMAL) { msn_session_set_error(nexus->session, MSN_ERROR_AUTH, _("nexus stream error")); return; } if (str) { char *field; str[terminator_pos] = '\0'; if ((field = get_field(str, "PassportURLs: "))) { char *da_login; da_login = strstr(field, "DALogin="******"DALogin="******"msnia.login.live.com"); #endif } } g_free(str); if (nexus->login_host) { PnSslConn *ssl_conn; PnNode *conn; ssl_conn = pn_ssl_conn_new("login", PN_NODE_NULL); conn = PN_NODE(ssl_conn); conn->session = nexus->session; if (nexus->error_handler) g_signal_handler_disconnect(nexus->conn, nexus->error_handler); if (nexus->open_handler) g_signal_handler_disconnect(nexus->conn, nexus->open_handler); g_object_unref(nexus->conn); pn_parser_free(nexus->parser); nexus->parser_state = 0; nexus->parser = pn_parser_new(conn); pn_ssl_conn_set_read_cb(ssl_conn, login_read_cb, nexus); nexus->conn = conn; nexus->open_handler = g_signal_connect(conn, "open", G_CALLBACK(login_open_cb), nexus); nexus->error_handler = g_signal_connect(conn, "error", G_CALLBACK(close_cb), nexus); pn_node_connect(conn, nexus->login_host, 443); return; } } } }
static gboolean msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf, size_t size, char **ret_buf, size_t *ret_size, gboolean *error) { const char *s, *c; char *header, *body; const char *body_start; char *tmp; size_t body_len = 0; g_return_val_if_fail(httpconn != 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 purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf); #endif /* Healthy defaults. */ body = NULL; *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; msn_httpconn_process_queue(httpconn); return TRUE; } buf = s; size -= (s - buf); } if ((s = strstr(buf, "\r\n\r\n")) == NULL) /* Need to wait for the full HTTP header to arrive */ return FALSE; s += 4; /* Skip \r\n\r\n */ header = g_strndup(buf, s - buf); body_start = s; body_len = size - (body_start - buf); if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL) { int tmp_len; s += strlen("Content-Length: "); if ((c = strchr(s, '\r')) == NULL) { g_free(header); return FALSE; } tmp = g_strndup(s, c - s); tmp_len = atoi(tmp); g_free(tmp); if (body_len != tmp_len) { /* Need to wait for the full packet to arrive */ g_free(header); #if 0 purple_debug_warning("msn", "body length (%d) != content length (%d)\n", body_len, tmp_len); #endif return FALSE; } } body = g_malloc(body_len + 1); memcpy(body, body_start, body_len); body[body_len] = '\0'; #ifdef MSN_DEBUG_HTTP purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s}\n", header); #endif /* Now we should be able to process the data. */ if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL) { gchar *full_session_id = NULL, *gw_ip = NULL, *session_action = NULL; char *t, *session_id; char **elems, **cur, **tokens; full_session_id = gw_ip = session_action = NULL; s += strlen("X-MSN-Messenger: "); if ((c = strchr(s, '\r')) == NULL) { msn_session_set_error(httpconn->session, MSN_ERROR_HTTP_MALFORMED, NULL); purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n", buf); g_free(header); g_free(body); return FALSE; } tmp = g_strndup(s, c - s); elems = g_strsplit(tmp, "; ", 0); for (cur = elems; *cur != NULL; cur++) { tokens = g_strsplit(*cur, "=", 2); if (strcmp(tokens[0], "SessionID") == 0) { g_free(full_session_id); full_session_id = tokens[1]; } else if (strcmp(tokens[0], "GW-IP") == 0) { g_free(gw_ip); gw_ip = tokens[1]; } else if (strcmp(tokens[0], "Session") == 0) { g_free(session_action); session_action = tokens[1]; } else g_free(tokens[1]); g_free(tokens[0]); /* Don't free each of the tokens, only the array. */ g_free(tokens); } g_strfreev(elems); g_free(tmp); t = strchr(full_session_id, '.'); if (t != NULL) session_id = g_strndup(full_session_id, t - full_session_id); else { purple_debug_error("msn", "Malformed full_session_id[%s]\n", full_session_id ? full_session_id : NULL); session_id = g_strdup(full_session_id); } if (session_action == NULL || strcmp(session_action, "close") != 0) { g_free(httpconn->full_session_id); httpconn->full_session_id = full_session_id; g_free(httpconn->session_id); httpconn->session_id = session_id; g_free(httpconn->host); httpconn->host = gw_ip; } else { MsnServConn *servconn; /* It's going to die. */ /* poor thing */ servconn = httpconn->servconn; /* I'll be honest, I don't fully understand all this, but this * causes crashes, Stu. */ /* if (servconn != NULL) servconn->wasted = TRUE; */ g_free(full_session_id); g_free(session_id); g_free(gw_ip); } g_free(session_action); } g_free(header); *ret_buf = body; *ret_size = body_len; msn_httpconn_process_queue(httpconn); return TRUE; }
static void msn_soap_process(MsnSoapConnection *conn) { gboolean handled = FALSE; char *cursor; char *linebreak; cursor = conn->buf->str + conn->handled_len; if (!conn->headers_done) { while ((linebreak = strstr(cursor, "\r\n")) != NULL) { conn->handled_len = linebreak - conn->buf->str + 2; if (conn->response_code == 0) { if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) { /* something horribly wrong */ purple_ssl_close(conn->ssl); conn->ssl = NULL; handled = TRUE; break; } else if (conn->response_code == 503 && conn->session->login_step < MSN_LOGIN_STEP_END) { msn_soap_connection_sanitize(conn, TRUE); msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL); return; } } else if (cursor == linebreak) { /* blank line */ conn->headers_done = TRUE; cursor = conn->buf->str + conn->handled_len; break; } else { char *line = g_strndup(cursor, linebreak - cursor); char *sep = strstr(line, ": "); char *key = line; char *value; if (sep == NULL) { purple_debug_info("soap", "ignoring malformed line: %s\n", line); g_free(line); goto loop_end; } value = sep + 2; *sep = '\0'; msn_soap_message_add_header(conn->message, key, value); if ((conn->response_code == 301 || conn->response_code == 300) && strcmp(key, "Location") == 0) { msn_soap_handle_redirect(conn, value); handled = TRUE; g_free(line); break; } else if (conn->response_code == 401 && strcmp(key, "WWW-Authenticate") == 0) { char *error = strstr(value, "cbtxt="); if (error) { error += strlen("cbtxt="); } msn_soap_connection_sanitize(conn, TRUE); msn_session_set_error(conn->session, MSN_ERROR_AUTH, error ? purple_url_decode(error) : NULL); g_free(line); return; } else if (strcmp(key, "Content-Length") == 0) { if (sscanf(value, "%" G_GSIZE_FORMAT, &(conn->body_len)) != 1) purple_debug_error("soap", "Unable to parse Content-Length\n"); } else if (strcmp(key, "Connection") == 0) { if (strcmp(value, "close") == 0) { conn->close_when_done = TRUE; } } g_free(line); } loop_end: cursor = conn->buf->str + conn->handled_len; } } if (!handled && conn->headers_done) { if (conn->buf->len - conn->handled_len >= conn->body_len) { xmlnode *node = xmlnode_from_str(cursor, conn->body_len); if (node == NULL) { purple_debug_info("soap", "Malformed SOAP response: %s\n", cursor); } else { MsnSoapMessage *message = conn->message; conn->message = NULL; message->xml = node; if (!msn_soap_handle_body(conn, message)) { return; } } msn_soap_connection_handle_next(conn); } return; } if (handled) { msn_soap_connection_handle_next(conn); } }