Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
	}
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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);
	}
}