static void msn_soap_connection_handle_next(MsnSoapConnection *conn) { msn_soap_connection_sanitize(conn, FALSE); conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn); }
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 msn_soap_connection_handle_next(MsnSoapConnection *conn) { msn_soap_connection_sanitize(conn, FALSE); conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn); if (conn->current_request) { MsnSoapRequest *req = conn->current_request; conn->current_request = NULL; msn_soap_connection_destroy_foreach_cb(req, conn); } }
static void msn_soap_connection_destroy(MsnSoapConnection *conn) { if (conn->current_request) { MsnSoapRequest *req = conn->current_request; conn->current_request = NULL; msn_soap_connection_destroy_foreach_cb(req, conn); } msn_soap_connection_sanitize(conn, TRUE); g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn); g_queue_free(conn->queue); g_free(conn->host); g_free(conn); }
static gboolean msn_soap_connection_run(gpointer data) { MsnSoapConnection *conn = data; MsnSoapRequest *req = g_queue_peek_head(conn->queue); conn->run_timer = 0; if (req) { if (conn->ssl == NULL) { conn->ssl = purple_ssl_connect(conn->session->account, conn->host, 443, msn_soap_connected_cb, msn_soap_error_cb, conn); } else if (conn->connected) { int len = -1; char *body = xmlnode_to_str(req->message->xml, &len); GSList *iter; g_queue_pop_head(conn->queue); conn->buf = g_string_new(""); g_string_append_printf(conn->buf, "POST /%s HTTP/1.1\r\n" "SOAPAction: %s\r\n" "Content-Type:text/xml; charset=utf-8\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" "Accept: */*\r\n" "Host: %s\r\n" "Content-Length: %d\r\n" "Connection: Keep-Alive\r\n" "Cache-Control: no-cache\r\n", req->path, req->message->action ? req->message->action : "", conn->host, len); for (iter = req->message->headers; iter; iter = iter->next) { g_string_append(conn->buf, (char *)iter->data); g_string_append(conn->buf, "\r\n"); } g_string_append(conn->buf, "\r\n"); g_string_append(conn->buf, body); if (req->secure && !purple_debug_is_unsafe()) purple_debug_misc("soap", "Sending secure request.\n"); else purple_debug_misc("soap", "%s\n", conn->buf->str); conn->handled_len = 0; conn->current_request = req; if (conn->event_handle) purple_input_remove(conn->event_handle); conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_WRITE, msn_soap_write_cb, conn); if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) { /* Not connected => reconnect and retry */ purple_debug_info("soap", "not connected, reconnecting\n"); conn->connected = FALSE; conn->current_request = NULL; msn_soap_connection_sanitize(conn, FALSE); g_queue_push_head(conn->queue, req); conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn); } g_free(body); } } return FALSE; }
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); } }