Re-arrange GG edisc file to avoid prototypes.

Fri, 11 Oct 2019 05:45:14 -0400

author
Elliott Sales de Andrade <qulogic@pidgin.im>
date
Fri, 11 Oct 2019 05:45:14 -0400
changeset 40009
0f7a002a052a
parent 40008
73ed25ee0008
child 40010
a72915f6fb1d

Re-arrange GG edisc file to avoid prototypes.

libpurple/protocols/gg/edisc.c file | annotate | diff | comparison | revisions
--- a/libpurple/protocols/gg/edisc.c	Wed Oct 09 21:05:42 2019 -0400
+++ b/libpurple/protocols/gg/edisc.c	Fri Oct 11 05:45:14 2019 -0400
@@ -46,8 +46,6 @@
 	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
 	" [](){}-+=_;'<>,.&$!"
 
-typedef struct _ggp_edisc_auth_data ggp_edisc_auth_data;
-
 typedef struct _ggp_edisc_xfer ggp_edisc_xfer;
 
 struct _ggp_edisc_session_data
@@ -88,37 +86,6 @@
 typedef void (*ggp_ggdrive_auth_cb)(PurpleConnection *gc, gboolean success,
 	gpointer user_data);
 
-/* Setting up. */
-static inline ggp_edisc_session_data *
-ggp_edisc_get_sdata(PurpleConnection *gc);
-
-/* Misc. */
-static void ggp_edisc_set_defaults(PurpleHttpRequest *req);
-static int ggp_edisc_parse_error(const gchar *data);
-
-/* General xfer functions. */
-static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg);
-static const gchar * ggp_edisc_xfer_ticket_url(const gchar *ticket_id);
-static void ggp_edisc_xfer_progress_watcher(PurpleHttpConnection *hc,
-	gboolean reading_state, int processed, int total, gpointer _xfer);
-static ggp_edisc_xfer_ack_status
-ggp_edisc_xfer_parse_ack_status(const gchar *str);
-
-
-/* Sending a file. */
-static void ggp_edisc_xfer_send_ticket_changed(PurpleConnection *gc,
-	PurpleXfer *xfer, gboolean is_allowed);
-
-/* Receiving a file. */
-static void ggp_edisc_xfer_recv_reject(PurpleXfer *xfer);
-static void ggp_edisc_xfer_recv_ticket_got(PurpleConnection *gc,
-	const gchar *ticket_id);
-static void ggp_edisc_xfer_recv_ticket_completed(PurpleXfer *xfer);
-
-/* Authentication. */
-static void ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb,
-	gpointer user_data);
-
 /*******************************************************************************
  * Setting up.
  ******************************************************************************/
@@ -210,10 +177,41 @@
 	return error_id;
 }
 
+static ggp_edisc_xfer_ack_status
+ggp_edisc_xfer_parse_ack_status(const gchar *str)
+{
+	g_return_val_if_fail(str != NULL, GGP_EDISC_XFER_ACK_STATUS_UNKNOWN);
+
+	if (g_strcmp0("unknown", str) == 0) {
+		return GGP_EDISC_XFER_ACK_STATUS_UNKNOWN;
+	}
+	if (g_strcmp0("allowed", str) == 0) {
+		return GGP_EDISC_XFER_ACK_STATUS_ALLOWED;
+	}
+	if (g_strcmp0("rejected", str) == 0) {
+		return GGP_EDISC_XFER_ACK_STATUS_REJECTED;
+	}
+
+	purple_debug_warning(
+	        "gg", "ggp_edisc_xfer_parse_ack_status: unknown status (%s)", str);
+	return GGP_EDISC_XFER_ACK_STATUS_UNKNOWN;
+}
+
 /*******************************************************************************
  * General xfer functions.
  ******************************************************************************/
 
+static const gchar *
+ggp_edisc_xfer_ticket_url(const gchar *ticket_id)
+{
+	static gchar ticket_url[150];
+
+	g_snprintf(ticket_url, sizeof(ticket_url),
+	           "https://drive.mpa.gg.pl/send_ticket/%s", ticket_id);
+
+	return ticket_url;
+}
+
 static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg)
 {
 	if (purple_xfer_is_cancelled(xfer))
@@ -228,74 +226,6 @@
 	purple_xfer_end(xfer);
 }
 
-void ggp_edisc_xfer_ticket_changed(PurpleConnection *gc, const char *data)
-{
-	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
-	PurpleXfer *xfer;
-	JsonParser *parser;
-	JsonObject *ticket;
-	const gchar *ticket_id, *send_status;
-	ggp_edisc_xfer_ack_status ack_status;
-	gboolean is_completed;
-
-	g_return_if_fail(sdata != NULL);
-
-	parser = ggp_json_parse(data);
-	ticket = json_node_get_object(json_parser_get_root(parser));
-	ticket_id = json_object_get_string_member(ticket, "id");
-	ack_status = ggp_edisc_xfer_parse_ack_status(
-		json_object_get_string_member(ticket, "ack_status"));
-	send_status = json_object_get_string_member(ticket, "send_status");
-
-	if (ticket_id == NULL)
-		ticket_id = "";
-	xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
-	if (xfer == NULL) {
-		purple_debug_misc("gg", "ggp_edisc_event_ticket_changed: "
-			"ticket %s not found, updating it...\n",
-			purple_debug_is_unsafe() ? ticket_id : "");
-		ggp_edisc_xfer_recv_ticket_got(gc, ticket_id);
-		g_object_unref(parser);
-		return;
-	}
-
-	is_completed = FALSE;
-	if (g_strcmp0("in_progress", send_status) == 0) {
-		/* do nothing */
-	} else if (g_strcmp0("completed", send_status) == 0) {
-		is_completed = TRUE;
-	} else if (g_strcmp0("expired", send_status) == 0)
-		ggp_edisc_xfer_error(xfer, _("File transfer expired."));
-	else {
-		purple_debug_warning("gg", "ggp_edisc_event_ticket_changed: "
-			"unknown send_status=%s\n", send_status);
-		g_object_unref(parser);
-		return;
-	}
-
-	g_object_unref(parser);
-
-	if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) {
-		if (is_completed)
-			ggp_edisc_xfer_recv_ticket_completed(xfer);
-	} else {
-		if (ack_status != GGP_EDISC_XFER_ACK_STATUS_UNKNOWN)
-			ggp_edisc_xfer_send_ticket_changed(gc, xfer, ack_status
-				== GGP_EDISC_XFER_ACK_STATUS_ALLOWED);
-	}
-
-}
-
-static const gchar * ggp_edisc_xfer_ticket_url(const gchar *ticket_id)
-{
-	static gchar ticket_url[150];
-
-	g_snprintf(ticket_url, sizeof(ticket_url),
-		"https://drive.mpa.gg.pl/send_ticket/%s", ticket_id);
-
-	return ticket_url;
-}
-
 static void ggp_edisc_xfer_progress_watcher(PurpleHttpConnection *hc,
 	gboolean reading_state, int processed, int total, gpointer _xfer)
 {
@@ -320,41 +250,200 @@
 	purple_xfer_update_progress(xfer);
 }
 
-static ggp_edisc_xfer_ack_status
-ggp_edisc_xfer_parse_ack_status(const gchar *str)
+/*******************************************************************************
+ * Authentication.
+ ******************************************************************************/
+
+typedef struct _ggp_edisc_auth_data {
+	ggp_ggdrive_auth_cb cb;
+	gpointer user_data;
+} ggp_edisc_auth_data;
+
+static void
+ggp_ggdrive_auth_results(PurpleConnection *gc, gboolean success)
+{
+	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+	GList *it;
+
+	purple_debug_info("gg", "ggp_ggdrive_auth_results(gc=%p): %d", gc, success);
+
+	g_return_if_fail(sdata != NULL);
+
+	it = g_list_first(sdata->auth_pending);
+	while (it) {
+		ggp_edisc_auth_data *auth = it->data;
+		it = g_list_next(it);
+
+		auth->cb(gc, success, auth->user_data);
+		g_free(auth);
+	}
+	g_list_free(sdata->auth_pending);
+	sdata->auth_pending = NULL;
+	sdata->auth_done = TRUE;
+}
+
+static void
+ggp_ggdrive_auth_done(PurpleHttpConnection *hc, PurpleHttpResponse *response,
+                      gpointer user_data)
 {
-	g_return_val_if_fail(str != NULL, GGP_EDISC_XFER_ACK_STATUS_UNKNOWN);
+	PurpleConnection *gc = purple_http_conn_get_purple_connection(hc);
+	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+	JsonParser *parser;
+	JsonObject *result;
+	int status = -1;
+
+	g_return_if_fail(sdata != NULL);
+
+	sdata->auth_request = NULL;
+
+	if (!purple_http_response_is_successful(response)) {
+		purple_debug_misc("gg",
+		                  "ggp_ggdrive_auth_done: authentication failed due to "
+		                  "unsuccessful request (code = %d)",
+		                  purple_http_response_get_code(response));
+		ggp_ggdrive_auth_results(gc, FALSE);
+		return;
+	}
+
+	parser = ggp_json_parse(purple_http_response_get_data(response, NULL));
+	result = json_node_get_object(json_parser_get_root(parser));
+	result = json_object_get_object_member(result, "result");
+	if (json_object_has_member(result, "status"))
+		status = json_object_get_int_member(result, "status");
+	g_object_unref(parser);
+
+	if (status != 0) {
+		purple_debug_misc("gg",
+		                  "ggp_ggdrive_auth_done: authentication failed due to "
+		                  "bad result (status=%d)",
+		                  status);
+		if (purple_debug_is_verbose()) {
+			purple_debug_misc("gg", "ggp_ggdrive_auth_done: result = %s",
+			                  purple_http_response_get_data(response, NULL));
+		}
+		ggp_ggdrive_auth_results(gc, FALSE);
+		return;
+	}
+
+	sdata->security_token = g_strdup(
+	        purple_http_response_get_header(response, "X-gged-security-token"));
+	if (!sdata->security_token) {
+		purple_debug_misc("gg", "ggp_ggdrive_auth_done: authentication failed "
+		                        "due to missing security token header");
+		ggp_ggdrive_auth_results(gc, FALSE);
+		return;
+	}
+
+	if (purple_debug_is_unsafe()) {
+		purple_debug_misc("gg", "ggp_ggdrive_auth_done: security_token=%s",
+		                  sdata->security_token);
+	}
+	ggp_ggdrive_auth_results(gc, TRUE);
+}
 
-	if (g_strcmp0("unknown", str) == 0)
-		return GGP_EDISC_XFER_ACK_STATUS_UNKNOWN;
-	if (g_strcmp0("allowed", str) == 0)
-		return GGP_EDISC_XFER_ACK_STATUS_ALLOWED;
-	if (g_strcmp0("rejected", str) == 0)
-		return GGP_EDISC_XFER_ACK_STATUS_REJECTED;
+static void
+ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb,
+                 gpointer user_data)
+{
+	GGPInfo *accdata = purple_connection_get_protocol_data(gc);
+	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+	ggp_edisc_auth_data *auth;
+	const gchar *imtoken;
+	gchar *metadata;
+	PurpleHttpRequest *req;
+
+	g_return_if_fail(sdata != NULL);
+
+	imtoken = ggp_get_imtoken(gc);
+	if (!imtoken) {
+		cb(gc, FALSE, user_data);
+		return;
+	}
+
+	if (sdata->auth_done) {
+		cb(gc, sdata->security_token != NULL, user_data);
+		return;
+	}
+
+	auth = g_new0(ggp_edisc_auth_data, 1);
+	auth->cb = cb;
+	auth->user_data = user_data;
+	sdata->auth_pending = g_list_prepend(sdata->auth_pending, auth);
+
+	if (sdata->auth_request) {
+		return;
+	}
+
+	purple_debug_info("gg", "ggp_ggdrive_auth(gc=%p)", gc);
+
+	req = purple_http_request_new("https://drive.mpa.gg.pl/signin");
+	purple_http_request_set_method(req, "PUT");
+
+	ggp_edisc_set_defaults(req);
+	purple_http_request_set_cookie_jar(req, sdata->cookies);
 
-	purple_debug_warning("gg", "ggp_edisc_xfer_parse_ack_status: "
-		"unknown status (%s)\n", str);
-	return GGP_EDISC_XFER_ACK_STATUS_UNKNOWN;
+	metadata =
+	        g_strdup_printf("{"
+	                        "\"id\": \"%032x\", "
+	                        "\"name\": \"%s\", "
+	                        "\"os_version\": \"" GGP_EDISC_OS "\", "
+	                        "\"client_version\": \"%s\", "
+	                        "\"type\": \"" GGP_EDISC_TYPE "\"}",
+	                        g_random_int_range(1, 1 << 16),
+	                        purple_get_host_name(), ggp_libgaduw_version(gc));
+
+	purple_http_request_header_set_printf(req, "Authorization", "IMToken %s",
+	                                      imtoken);
+	purple_http_request_header_set_printf(req, "X-gged-user", "gg/pl:%u",
+	                                      accdata->session->uin);
+	purple_http_request_header_set(req, "X-gged-client-metadata", metadata);
+	g_free(metadata);
+
+	sdata->auth_request =
+	        purple_http_request(gc, req, ggp_ggdrive_auth_done, NULL);
+	purple_http_request_unref(req);
+}
+
+static void
+ggp_edisc_xfer_send_ticket_changed(PurpleConnection *gc, PurpleXfer *xfer,
+                                   gboolean is_allowed)
+{
+	GGPXfer *edisc_xfer = GGP_XFER(xfer);
+	if (!edisc_xfer) {
+		purple_debug_fatal(
+		        "gg",
+		        "ggp_edisc_event_ticket_changed: transfer %p already free'd",
+		        xfer);
+		return;
+	}
+
+	if (!is_allowed) {
+		purple_debug_info(
+		        "gg", "ggp_edisc_event_ticket_changed: transfer %p rejected",
+		        xfer);
+		purple_xfer_cancel_remote(xfer);
+		return;
+	}
+
+	if (edisc_xfer->allowed) {
+		purple_debug_misc(
+		        "gg",
+		        "ggp_edisc_event_ticket_changed: transfer %p already allowed",
+		        xfer);
+		return;
+	}
+	edisc_xfer->allowed = TRUE;
+
+	purple_xfer_start(xfer, -1, NULL, 0);
 }
 
 /*******************************************************************************
  * Sending a file.
  ******************************************************************************/
 
-static void ggp_edisc_xfer_send_init(PurpleXfer *xfer);
-static void ggp_edisc_xfer_send_init_authenticated(PurpleConnection *gc,
-	gboolean success, gpointer _xfer);
-static void ggp_edisc_xfer_send_init_ticket_created(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer _xfer);
-static void ggp_edisc_xfer_send_reader(PurpleHttpConnection *hc,
-	gchar *buffer, size_t offset, size_t length, gpointer _xfer,
-	PurpleHttpContentReaderCb cb);
-static void ggp_edisc_xfer_send_start(PurpleXfer *xfer);
-static void ggp_edisc_xfer_send_done(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer _xfer);
-
-gboolean ggp_edisc_xfer_can_receive_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc,
-	const char *who)
+gboolean
+ggp_edisc_xfer_can_receive_file(PurpleProtocolXfer *prplxfer,
+                                PurpleConnection *gc, const char *who)
 {
 	PurpleBuddy *buddy;
 
@@ -362,71 +451,15 @@
 	g_return_val_if_fail(who != NULL, FALSE);
 
 	buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who);
-	if (buddy == NULL)
+	if (buddy == NULL) {
 		return FALSE;
+	}
 
 	/* TODO: check, if this buddy have us on his list */
 
 	return PURPLE_BUDDY_IS_ONLINE(buddy);
 }
 
-static void ggp_edisc_xfer_send_init(PurpleXfer *xfer)
-{
-	GGPXfer *edisc_xfer = GGP_XFER(xfer);
-
-	purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_NOT_STARTED);
-
-	edisc_xfer->filename = g_strdup(purple_xfer_get_filename(xfer));
-	g_strcanon(edisc_xfer->filename, GGP_EDISC_FNAME_ALLOWED, '_');
-
-	ggp_ggdrive_auth(edisc_xfer->gc, ggp_edisc_xfer_send_init_authenticated,
-		xfer);
-}
-
-static void ggp_edisc_xfer_send_init_authenticated(PurpleConnection *gc,
-	gboolean success, gpointer _xfer)
-{
-	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
-	PurpleHttpRequest *req;
-	PurpleXfer *xfer = _xfer;
-	GGPXfer *edisc_xfer = GGP_XFER(xfer);
-	gchar *data;
-
-	if (purple_xfer_is_cancelled(xfer))
-		return;
-
-	if (!success) {
-		ggp_edisc_xfer_error(xfer, _("Authentication failed"));
-		return;
-	}
-
-	g_return_if_fail(sdata != NULL);
-
-	req = purple_http_request_new("https://drive.mpa.gg.pl/send_ticket");
-	purple_http_request_set_method(req, "PUT");
-
-	ggp_edisc_set_defaults(req);
-	purple_http_request_set_cookie_jar(req, sdata->cookies);
-
-	purple_http_request_header_set(req, "X-gged-security-token",
-		sdata->security_token);
-
-	data = g_strdup_printf("{\"send_ticket\":{"
-		"\"recipient\":\"%s\","
-		"\"file_name\":\"%s\","
-		"\"file_size\":\"%u\""
-		"}}",
-		purple_xfer_get_remote_user(xfer),
-		edisc_xfer->filename,
-		(int)purple_xfer_get_size(xfer));
-	purple_http_request_set_contents(req, data, -1);
-	g_free(data);
-
-	edisc_xfer->hc = purple_http_request(gc, req,
-		ggp_edisc_xfer_send_init_ticket_created, xfer);
-	purple_http_request_unref(req);
-}
-
 static void ggp_edisc_xfer_send_init_ticket_created(PurpleHttpConnection *hc,
 	PurpleHttpResponse *response, gpointer _xfer)
 {
@@ -492,31 +525,64 @@
 			ack_status == GGP_EDISC_XFER_ACK_STATUS_ALLOWED);
 }
 
-void ggp_edisc_xfer_send_ticket_changed(PurpleConnection *gc, PurpleXfer *xfer,
-	gboolean is_allowed)
+static void
+ggp_edisc_xfer_send_init_authenticated(PurpleConnection *gc, gboolean success,
+                                       gpointer _xfer)
 {
+	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+	PurpleHttpRequest *req;
+	PurpleXfer *xfer = _xfer;
 	GGPXfer *edisc_xfer = GGP_XFER(xfer);
-	if (!edisc_xfer) {
-		purple_debug_fatal("gg", "ggp_edisc_event_ticket_changed: "
-			"transfer %p already free'd\n", xfer);
+	gchar *data;
+
+	if (purple_xfer_is_cancelled(xfer)) {
+		return;
+	}
+
+	if (!success) {
+		ggp_edisc_xfer_error(xfer, _("Authentication failed"));
 		return;
 	}
 
-	if (!is_allowed) {
-		purple_debug_info("gg", "ggp_edisc_event_ticket_changed: "
-			"transfer %p rejected\n", xfer);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
+	g_return_if_fail(sdata != NULL);
+
+	req = purple_http_request_new("https://drive.mpa.gg.pl/send_ticket");
+	purple_http_request_set_method(req, "PUT");
+
+	ggp_edisc_set_defaults(req);
+	purple_http_request_set_cookie_jar(req, sdata->cookies);
+
+	purple_http_request_header_set(req, "X-gged-security-token",
+	                               sdata->security_token);
 
-	if (edisc_xfer->allowed) {
-		purple_debug_misc("gg", "ggp_edisc_event_ticket_changed: "
-			"transfer %p already allowed\n", xfer);
-		return;
-	}
-	edisc_xfer->allowed = TRUE;
+	data = g_strdup_printf("{\"send_ticket\":{"
+	                       "\"recipient\":\"%s\","
+	                       "\"file_name\":\"%s\","
+	                       "\"file_size\":\"%u\""
+	                       "}}",
+	                       purple_xfer_get_remote_user(xfer),
+	                       edisc_xfer->filename,
+	                       (int)purple_xfer_get_size(xfer));
+	purple_http_request_set_contents(req, data, -1);
+	g_free(data);
 
-	purple_xfer_start(xfer, -1, NULL, 0);
+	edisc_xfer->hc = purple_http_request(
+	        gc, req, ggp_edisc_xfer_send_init_ticket_created, xfer);
+	purple_http_request_unref(req);
+}
+
+static void
+ggp_edisc_xfer_send_init(PurpleXfer *xfer)
+{
+	GGPXfer *edisc_xfer = GGP_XFER(xfer);
+
+	purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_NOT_STARTED);
+
+	edisc_xfer->filename = g_strdup(purple_xfer_get_filename(xfer));
+	g_strcanon(edisc_xfer->filename, GGP_EDISC_FNAME_ALLOWED, '_');
+
+	ggp_ggdrive_auth(edisc_xfer->gc, ggp_edisc_xfer_send_init_authenticated,
+	                 xfer);
 }
 
 static void ggp_edisc_xfer_send_reader(PurpleHttpConnection *hc,
@@ -553,6 +619,46 @@
 	cb(hc, success, eof, stored);
 }
 
+static void
+ggp_edisc_xfer_send_done(PurpleHttpConnection *hc, PurpleHttpResponse *response,
+                         gpointer _xfer)
+{
+	PurpleXfer *xfer = _xfer;
+	GGPXfer *edisc_xfer = GGP_XFER(xfer);
+	const gchar *data = purple_http_response_get_data(response, NULL);
+	JsonParser *parser;
+	JsonObject *result;
+	int result_status = -1;
+
+	if (purple_xfer_is_cancelled(xfer)) {
+		return;
+	}
+
+	g_return_if_fail(edisc_xfer != NULL);
+
+	edisc_xfer->hc = NULL;
+
+	if (!purple_http_response_is_successful(response)) {
+		ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
+		return;
+	}
+
+	parser = ggp_json_parse(data);
+	result = json_node_get_object(json_parser_get_root(parser));
+	result = json_object_get_object_member(result, "result");
+	if (json_object_has_member(result, "status")) {
+		result_status = json_object_get_int_member(result, "status");
+	}
+	g_object_unref(parser);
+
+	if (result_status == 0) {
+		purple_xfer_set_completed(xfer, TRUE);
+		purple_xfer_end(xfer);
+	} else {
+		ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
+	}
+}
+
 static void ggp_edisc_xfer_send_start(PurpleXfer *xfer)
 {
 	ggp_edisc_session_data *sdata;
@@ -596,44 +702,6 @@
 		ggp_edisc_xfer_progress_watcher, xfer, 250000);
 }
 
-static void ggp_edisc_xfer_send_done(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer _xfer)
-{
-	PurpleXfer *xfer = _xfer;
-	GGPXfer *edisc_xfer = GGP_XFER(xfer);
-	const gchar *data = purple_http_response_get_data(response, NULL);
-	JsonParser *parser;
-	JsonObject *result;
-	int result_status = -1;
-
-	if (purple_xfer_is_cancelled(xfer))
-		return;
-
-	g_return_if_fail(edisc_xfer != NULL);
-
-	edisc_xfer->hc = NULL;
-
-	if (!purple_http_response_is_successful(response)) {
-		ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
-		return;
-	}
-
-	parser = ggp_json_parse(data);
-	result = json_node_get_object(json_parser_get_root(parser));
-	result = json_object_get_object_member(result, "result");
-	if (json_object_has_member(result, "status")) {
-		result_status = json_object_get_int_member(result, "status");
-	}
-	g_object_unref(parser);
-
-	if (result_status == 0) {
-		purple_xfer_set_completed(xfer, TRUE);
-		purple_xfer_end(xfer);
-	} else {
-		ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
-	}
-}
-
 PurpleXfer * ggp_edisc_xfer_send_new(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who)
 {
 	GGPXfer *xfer;
@@ -676,199 +744,44 @@
  * Receiving a file.
  ******************************************************************************/
 
-static void ggp_edisc_xfer_recv_ticket_update_authenticated(
-	PurpleConnection *gc, gboolean success, gpointer _ticket);
-static void ggp_edisc_xfer_recv_ticket_update_got(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer user_data);
-static PurpleXfer * ggp_edisc_xfer_recv_new(PurpleConnection *gc,
-	const char *who);
-static void ggp_edisc_xfer_recv_accept(PurpleXfer *xfer);
-static void ggp_edisc_xfer_recv_start(PurpleXfer *xfer);
-static void ggp_edisc_xfer_recv_ack(PurpleXfer *xfer, gboolean accept);
-static void ggp_edisc_xfer_recv_ack_done(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer _xfer);
-static gboolean ggp_edisc_xfer_recv_writer(PurpleHttpConnection *http_conn,
-	PurpleHttpResponse *response, const gchar *buffer, size_t offset,
-	size_t length, gpointer user_data);
-static void ggp_edisc_xfer_recv_done(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer _xfer);
-
-static void ggp_edisc_xfer_recv_ticket_got(PurpleConnection *gc,
-	const gchar *ticket_id)
-{
-	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
-
-	g_return_if_fail(sdata != NULL);
-
-	if (g_hash_table_lookup(sdata->xfers_history, ticket_id))
-		return;
-
-	ggp_ggdrive_auth(gc, ggp_edisc_xfer_recv_ticket_update_authenticated,
-		g_strdup(ticket_id));
-}
-
-static void ggp_edisc_xfer_recv_ticket_update_authenticated(
-	PurpleConnection *gc, gboolean success, gpointer _ticket)
-{
-	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
-	PurpleHttpRequest *req;
-	gchar *ticket = _ticket;
-
-	g_return_if_fail(sdata != NULL);
-
-	if (!success) {
-		purple_debug_warning("gg",
-			"ggp_edisc_xfer_recv_ticket_update_authenticated: "
-			"update of ticket %s aborted due to authentication "
-			"failure\n", ticket);
-		g_free(ticket);
-		return;
-	}
-
-	req = purple_http_request_new(ggp_edisc_xfer_ticket_url(ticket));
-	g_free(ticket);
-
-	ggp_edisc_set_defaults(req);
-	purple_http_request_set_cookie_jar(req, sdata->cookies);
-
-	purple_http_request_header_set(req, "X-gged-security-token",
-		sdata->security_token);
-
-	purple_http_request(gc, req, ggp_edisc_xfer_recv_ticket_update_got,
-		NULL);
-	purple_http_request_unref(req);
-}
-
-static void ggp_edisc_xfer_recv_ticket_update_got(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer user_data)
-{
-	PurpleConnection *gc = purple_http_conn_get_purple_connection(hc);
-	PurpleXfer *xfer;
-	GGPXfer *edisc_xfer;
-	JsonParser *parser;
-	JsonObject *result;
-	int status = -1;
-	ggp_edisc_session_data *sdata;
-
-	const gchar *ticket_id, *file_name, *send_mode_str;
-	uin_t sender, recipient;
-	int file_size;
-
-	if (!purple_http_response_is_successful(response)) {
-		purple_debug_error("gg",
-			"ggp_edisc_xfer_recv_ticket_update_got: "
-			"cannot fetch update for ticket (code=%d)\n",
-			purple_http_response_get_code(response));
-		return;
-	}
-
-	sdata = ggp_edisc_get_sdata(gc);
-	g_return_if_fail(sdata != NULL);
-
-	parser = ggp_json_parse(purple_http_response_get_data(response, NULL));
-	result = json_node_get_object(json_parser_get_root(parser));
-	result = json_object_get_object_member(result, "result");
-	if (json_object_has_member(result, "status"))
-		status = json_object_get_int_member(result, "status");
-	result = json_object_get_object_member(result, "send_ticket");
-
-	if (status != 0) {
-		purple_debug_warning("gg",
-			"ggp_edisc_xfer_recv_ticket_update_got: failed to get "
-			"update (status=%d)\n", status);
-		g_object_unref(parser);
-		return;
-	}
-
-	ticket_id = json_object_get_string_member(result, "id");
-	sender = ggp_str_to_uin(json_object_get_string_member(result,
-		"sender"));
-	recipient = ggp_str_to_uin(json_object_get_string_member(result,
-		"recipient"));
-	file_size = g_ascii_strtoll(json_object_get_string_member(result,
-		"file_size"), NULL, 10);
-	file_name = json_object_get_string_member(result, "file_name");
-
-	/* GG11: normal
-	 * AQQ 2.4.2.10: direct_inbox
-	 */
-	send_mode_str = json_object_get_string_member(result, "send_mode");
-
-	/* more fields:
-	 * send_progress (float), ack_status, send_status
-	 */
-
-	if (purple_debug_is_verbose() && purple_debug_is_unsafe())
-		purple_debug_info("gg", "Got ticket update: id=%s, sender=%u, "
-			"recipient=%u, file name=\"%s\", file size=%d, "
-			"send mode=%s)\n",
-			ticket_id,
-			sender, recipient,
-			file_name, file_size,
-			send_mode_str);
-
-	xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
-	if (xfer != NULL) {
-		purple_debug_misc("gg", "ggp_edisc_xfer_recv_ticket_update_got:"
-			" ticket %s already updated\n",
-			purple_debug_is_unsafe() ? ticket_id : "");
-		g_object_unref(parser);
-		return;
-	}
-
-	if (recipient != ggp_get_my_uin(gc)) {
-		purple_debug_misc("gg", "ggp_edisc_xfer_recv_ticket_update_got:"
-			" ticket %s is not for incoming transfer "
-			"(its from %u to %u)\n",
-			purple_debug_is_unsafe() ? ticket_id : "",
-			sender, recipient);
-		g_object_unref(parser);
-		return;
-	}
-
-	xfer = ggp_edisc_xfer_recv_new(gc, ggp_uin_to_str(sender));
-	purple_xfer_set_filename(xfer, file_name);
-	purple_xfer_set_size(xfer, file_size);
-	purple_xfer_request(xfer);
-	edisc_xfer = GGP_XFER(xfer);
-	edisc_xfer->ticket_id = g_strdup(ticket_id);
-	g_hash_table_insert(sdata->xfers_initialized,
-		edisc_xfer->ticket_id, xfer);
-	g_hash_table_insert(sdata->xfers_history,
-		g_strdup(ticket_id), GINT_TO_POINTER(1));
-
-	g_object_unref(parser);
-}
-
-static PurpleXfer * ggp_edisc_xfer_recv_new(PurpleConnection *gc,
-	const char *who)
+static PurpleXfer *
+ggp_edisc_xfer_recv_new(PurpleConnection *gc, const char *who)
 {
 	GGPXfer *xfer;
 
 	g_return_val_if_fail(gc != NULL, NULL);
 	g_return_val_if_fail(who != NULL, NULL);
 
-	xfer = g_object_new(
-		GGP_TYPE_XFER,
-		"account", purple_connection_get_account(gc),
-		"type", PURPLE_XFER_TYPE_RECEIVE,
-		"remote-user", who,
-		NULL
-	);
+	xfer = g_object_new(GGP_TYPE_XFER, "account",
+	                    purple_connection_get_account(gc), "type",
+	                    PURPLE_XFER_TYPE_RECEIVE, "remote-user", who, NULL);
 
 	xfer->gc = gc;
 
 	return PURPLE_XFER(xfer);
 }
 
-static void ggp_edisc_xfer_recv_reject(PurpleXfer *xfer)
+static void
+ggp_edisc_xfer_recv_ack_done(PurpleHttpConnection *hc,
+                             PurpleHttpResponse *response, gpointer _xfer)
 {
-	ggp_edisc_xfer_recv_ack(xfer, FALSE);
-}
+	PurpleXfer *xfer = _xfer;
+	GGPXfer *edisc_xfer;
+
+	if (purple_xfer_is_cancelled(xfer)) {
+		g_return_if_reached();
+	}
 
-static void ggp_edisc_xfer_recv_accept(PurpleXfer *xfer)
-{
-	ggp_edisc_xfer_recv_ack(xfer, TRUE);
+	edisc_xfer = GGP_XFER(xfer);
+	edisc_xfer->hc = NULL;
+
+	if (!purple_http_response_is_successful(response)) {
+		ggp_edisc_xfer_error(xfer, _("Cannot confirm file transfer."));
+		return;
+	}
+
+	purple_debug_info("gg", "ggp_edisc_xfer_recv_ack_done: [%s]\n",
+	                  purple_http_response_get_data(response, NULL));
 }
 
 static void ggp_edisc_xfer_recv_ack(PurpleXfer *xfer, gboolean accept)
@@ -902,25 +815,16 @@
 	}
 }
 
-static void ggp_edisc_xfer_recv_ack_done(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer _xfer)
+static void
+ggp_edisc_xfer_recv_reject(PurpleXfer *xfer)
 {
-	PurpleXfer *xfer = _xfer;
-	GGPXfer *edisc_xfer;
-
-	if (purple_xfer_is_cancelled(xfer))
-		g_return_if_reached();
+	ggp_edisc_xfer_recv_ack(xfer, FALSE);
+}
 
-	edisc_xfer = GGP_XFER(xfer);
-	edisc_xfer->hc = NULL;
-
-	if (!purple_http_response_is_successful(response)) {
-		ggp_edisc_xfer_error(xfer, _("Cannot confirm file transfer."));
-		return;
-	}
-
-	purple_debug_info("gg", "ggp_edisc_xfer_recv_ack_done: [%s]\n",
-		purple_http_response_get_data(response, NULL));
+static void
+ggp_edisc_xfer_recv_accept(PurpleXfer *xfer)
+{
+	ggp_edisc_xfer_recv_ack(xfer, TRUE);
 }
 
 static void ggp_edisc_xfer_recv_ticket_completed(PurpleXfer *xfer)
@@ -934,43 +838,6 @@
 	purple_xfer_start(xfer, -1, NULL, 0);
 }
 
-static void ggp_edisc_xfer_recv_start(PurpleXfer *xfer)
-{
-	ggp_edisc_session_data *sdata;
-	GGPXfer *edisc_xfer;
-	gchar *upload_url;
-	PurpleHttpRequest *req;
-
-	g_return_if_fail(xfer != NULL);
-	edisc_xfer = GGP_XFER(xfer);
-	g_return_if_fail(edisc_xfer != NULL);
-	sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
-	g_return_if_fail(sdata != NULL);
-
-	upload_url = g_strdup_printf("https://drive.mpa.gg.pl/me/file/inbox/"
-		"%s,%s?api_version=%s&security_token=%s",
-		edisc_xfer->ticket_id, purple_url_encode(purple_xfer_get_filename(xfer)),
-		GGP_EDISC_API, sdata->security_token);
-	req = purple_http_request_new(upload_url);
-	g_free(upload_url);
-
-	purple_http_request_set_timeout(req, -1);
-
-	ggp_edisc_set_defaults(req);
-	purple_http_request_set_max_len(req, purple_xfer_get_size(xfer) + 1);
-	purple_http_request_set_cookie_jar(req, sdata->cookies);
-
-	purple_http_request_set_response_writer(req, ggp_edisc_xfer_recv_writer,
-		xfer);
-
-	edisc_xfer->hc = purple_http_request(edisc_xfer->gc, req,
-		ggp_edisc_xfer_recv_done, xfer);
-	purple_http_request_unref(req);
-
-	purple_http_conn_set_progress_watcher(edisc_xfer->hc,
-		ggp_edisc_xfer_progress_watcher, xfer, 250000);
-}
-
 static gboolean ggp_edisc_xfer_recv_writer(PurpleHttpConnection *http_conn,
 	PurpleHttpResponse *response, const gchar *buffer, size_t offset,
 	size_t length, gpointer _xfer)
@@ -1031,157 +898,264 @@
 	}
 }
 
-/*******************************************************************************
- * Authentication.
- ******************************************************************************/
-
-struct _ggp_edisc_auth_data
+static void
+ggp_edisc_xfer_recv_start(PurpleXfer *xfer)
 {
-	ggp_ggdrive_auth_cb cb;
-	gpointer user_data;
-};
-
-static void ggp_ggdrive_auth_done(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer user_data);
-
-static void ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb,
-	gpointer user_data)
-{
-	GGPInfo *accdata = purple_connection_get_protocol_data(gc);
-	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
-	ggp_edisc_auth_data *auth;
-	const gchar *imtoken;
-	gchar *metadata;
+	ggp_edisc_session_data *sdata;
+	GGPXfer *edisc_xfer;
+	gchar *upload_url;
 	PurpleHttpRequest *req;
 
+	g_return_if_fail(xfer != NULL);
+	edisc_xfer = GGP_XFER(xfer);
+	g_return_if_fail(edisc_xfer != NULL);
+	sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
 	g_return_if_fail(sdata != NULL);
 
-	imtoken = ggp_get_imtoken(gc);
-	if (!imtoken) {
-		cb(gc, FALSE, user_data);
-		return;
-	}
+	upload_url =
+	        g_strdup_printf("https://drive.mpa.gg.pl/me/file/inbox/"
+	                        "%s,%s?api_version=%s&security_token=%s",
+	                        edisc_xfer->ticket_id,
+	                        purple_url_encode(purple_xfer_get_filename(xfer)),
+	                        GGP_EDISC_API, sdata->security_token);
+	req = purple_http_request_new(upload_url);
+	g_free(upload_url);
+
+	purple_http_request_set_timeout(req, -1);
+
+	ggp_edisc_set_defaults(req);
+	purple_http_request_set_max_len(req, purple_xfer_get_size(xfer) + 1);
+	purple_http_request_set_cookie_jar(req, sdata->cookies);
+
+	purple_http_request_set_response_writer(req, ggp_edisc_xfer_recv_writer,
+	                                        xfer);
+
+	edisc_xfer->hc = purple_http_request(edisc_xfer->gc, req,
+	                                     ggp_edisc_xfer_recv_done, xfer);
+	purple_http_request_unref(req);
 
-	if (sdata->auth_done) {
-		cb(gc, sdata->security_token != NULL, user_data);
+	purple_http_conn_set_progress_watcher(
+	        edisc_xfer->hc, ggp_edisc_xfer_progress_watcher, xfer, 250000);
+}
+
+static void
+ggp_edisc_xfer_recv_ticket_update_got(PurpleHttpConnection *hc,
+                                      PurpleHttpResponse *response,
+                                      gpointer user_data)
+{
+	PurpleConnection *gc = purple_http_conn_get_purple_connection(hc);
+	PurpleXfer *xfer;
+	GGPXfer *edisc_xfer;
+	JsonParser *parser;
+	JsonObject *result;
+	int status = -1;
+	ggp_edisc_session_data *sdata;
+
+	const gchar *ticket_id, *file_name, *send_mode_str;
+	uin_t sender, recipient;
+	int file_size;
+
+	if (!purple_http_response_is_successful(response)) {
+		purple_debug_error("gg",
+		                   "ggp_edisc_xfer_recv_ticket_update_got: cannot "
+		                   "fetch update for ticket (code=%d)",
+		                   purple_http_response_get_code(response));
 		return;
 	}
 
-	auth = g_new0(ggp_edisc_auth_data, 1);
-	auth->cb = cb;
-	auth->user_data = user_data;
-	sdata->auth_pending = g_list_prepend(sdata->auth_pending, auth);
-
-	if (sdata->auth_request)
-		return;
-
-	purple_debug_info("gg", "ggp_ggdrive_auth(gc=%p)\n", gc);
-
-	req = purple_http_request_new("https://drive.mpa.gg.pl/signin");
-	purple_http_request_set_method(req, "PUT");
-
-	ggp_edisc_set_defaults(req);
-	purple_http_request_set_cookie_jar(req, sdata->cookies);
-
-	metadata = g_strdup_printf("{"
-		"\"id\": \"%032x\", "
-		"\"name\": \"%s\", "
-		"\"os_version\": \"" GGP_EDISC_OS "\", "
-		"\"client_version\": \"%s\", "
-		"\"type\": \"" GGP_EDISC_TYPE "\"}",
-		g_random_int_range(1, 1 << 16),
-		purple_get_host_name(),
-		ggp_libgaduw_version(gc));
-
-	purple_http_request_header_set_printf(req, "Authorization",
-		"IMToken %s", imtoken);
-	purple_http_request_header_set_printf(req, "X-gged-user",
-		"gg/pl:%u", accdata->session->uin);
-	purple_http_request_header_set(req, "X-gged-client-metadata", metadata);
-	g_free(metadata);
-
-	sdata->auth_request = purple_http_request(gc, req,
-		ggp_ggdrive_auth_done, NULL);
-	purple_http_request_unref(req);
-}
-
-static void ggp_ggdrive_auth_results(PurpleConnection *gc, gboolean success)
-{
-	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
-	GList *it;
-
-	purple_debug_info("gg", "ggp_ggdrive_auth_results(gc=%p): %d\n",
-		gc, success);
-
+	sdata = ggp_edisc_get_sdata(gc);
 	g_return_if_fail(sdata != NULL);
 
-	it = g_list_first(sdata->auth_pending);
-	while (it) {
-		ggp_edisc_auth_data *auth = it->data;
-		it = g_list_next(it);
-
-		auth->cb(gc, success, auth->user_data);
-		g_free(auth);
-	}
-	g_list_free(sdata->auth_pending);
-	sdata->auth_pending = NULL;
-	sdata->auth_done = TRUE;
-}
-
-static void ggp_ggdrive_auth_done(PurpleHttpConnection *hc,
-	PurpleHttpResponse *response, gpointer user_data)
-{
-	PurpleConnection *gc = purple_http_conn_get_purple_connection(hc);
-	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
-	JsonParser *parser;
-	JsonObject *result;
-	int status = -1;
-
-	g_return_if_fail(sdata != NULL);
-
-	sdata->auth_request = NULL;
-
-	if (!purple_http_response_is_successful(response)) {
-		purple_debug_misc("gg", "ggp_ggdrive_auth_done: authentication "
-			"failed due to unsuccessful request (code = %d)\n",
-			purple_http_response_get_code(response));
-		ggp_ggdrive_auth_results(gc, FALSE);
-		return;
-	}
-
 	parser = ggp_json_parse(purple_http_response_get_data(response, NULL));
 	result = json_node_get_object(json_parser_get_root(parser));
 	result = json_object_get_object_member(result, "result");
 	if (json_object_has_member(result, "status"))
 		status = json_object_get_int_member(result, "status");
-	g_object_unref(parser);
+	result = json_object_get_object_member(result, "send_ticket");
+
+	if (status != 0) {
+		purple_debug_warning("gg",
+		                     "ggp_edisc_xfer_recv_ticket_update_got: failed to "
+		                     "get update (status=%d)",
+		                     status);
+		g_object_unref(parser);
+		return;
+	}
+
+	ticket_id = json_object_get_string_member(result, "id");
+	sender = ggp_str_to_uin(json_object_get_string_member(result, "sender"));
+	recipient =
+	        ggp_str_to_uin(json_object_get_string_member(result, "recipient"));
+	file_size = g_ascii_strtoll(
+	        json_object_get_string_member(result, "file_size"), NULL, 10);
+	file_name = json_object_get_string_member(result, "file_name");
+
+	/* GG11: normal
+	 * AQQ 2.4.2.10: direct_inbox
+	 */
+	send_mode_str = json_object_get_string_member(result, "send_mode");
+
+	/* more fields:
+	 * send_progress (float), ack_status, send_status
+	 */
+
+	if (purple_debug_is_verbose() && purple_debug_is_unsafe()) {
+		purple_debug_info("gg",
+		                  "Got ticket update: id=%s, sender=%u, recipient=%u, "
+		                  "file name=\"%s\", file size=%d, send mode=%s)",
+		                  ticket_id, sender, recipient, file_name, file_size,
+		                  send_mode_str);
+	}
 
-	if (status != 0 ) {
-		purple_debug_misc("gg", "ggp_ggdrive_auth_done: authentication "
-			"failed due to bad result (status=%d)\n", status);
-		if (purple_debug_is_verbose())
-			purple_debug_misc("gg", "ggp_ggdrive_auth_done: "
-				"result = %s\n",
-				purple_http_response_get_data(response, NULL));
-		ggp_ggdrive_auth_results(gc, FALSE);
+	xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
+	if (xfer != NULL) {
+		purple_debug_misc("gg",
+		                  "ggp_edisc_xfer_recv_ticket_update_got: ticket %s "
+		                  "already updated",
+		                  purple_debug_is_unsafe() ? ticket_id : "");
+		g_object_unref(parser);
+		return;
+	}
+
+	if (recipient != ggp_get_my_uin(gc)) {
+		purple_debug_misc("gg",
+		                  "ggp_edisc_xfer_recv_ticket_update_got: ticket %s is "
+		                  "not for incoming transfer (its from %u to %u)",
+		                  purple_debug_is_unsafe() ? ticket_id : "", sender,
+		                  recipient);
+		g_object_unref(parser);
+		return;
+	}
+
+	xfer = ggp_edisc_xfer_recv_new(gc, ggp_uin_to_str(sender));
+	purple_xfer_set_filename(xfer, file_name);
+	purple_xfer_set_size(xfer, file_size);
+	purple_xfer_request(xfer);
+	edisc_xfer = GGP_XFER(xfer);
+	edisc_xfer->ticket_id = g_strdup(ticket_id);
+	g_hash_table_insert(sdata->xfers_initialized, edisc_xfer->ticket_id, xfer);
+	g_hash_table_insert(sdata->xfers_history, g_strdup(ticket_id),
+	                    GINT_TO_POINTER(1));
+
+	g_object_unref(parser);
+}
+
+static void
+ggp_edisc_xfer_recv_ticket_update_authenticated(PurpleConnection *gc,
+                                                gboolean success,
+                                                gpointer _ticket)
+{
+	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+	PurpleHttpRequest *req;
+	gchar *ticket = _ticket;
+
+	g_return_if_fail(sdata != NULL);
+
+	if (!success) {
+		purple_debug_warning(
+		        "gg",
+		        "ggp_edisc_xfer_recv_ticket_update_authenticated: update of "
+		        "ticket %s aborted due to authentication failure",
+		        ticket);
+		g_free(ticket);
 		return;
 	}
 
-	sdata->security_token = g_strdup(purple_http_response_get_header(
-		response, "X-gged-security-token"));
-	if (!sdata->security_token) {
-		purple_debug_misc("gg", "ggp_ggdrive_auth_done: authentication "
-			"failed due to missing security token header\n");
-		ggp_ggdrive_auth_results(gc, FALSE);
+	req = purple_http_request_new(ggp_edisc_xfer_ticket_url(ticket));
+	g_free(ticket);
+
+	ggp_edisc_set_defaults(req);
+	purple_http_request_set_cookie_jar(req, sdata->cookies);
+
+	purple_http_request_header_set(req, "X-gged-security-token",
+	                               sdata->security_token);
+
+	purple_http_request(gc, req, ggp_edisc_xfer_recv_ticket_update_got, NULL);
+	purple_http_request_unref(req);
+}
+
+static void
+ggp_edisc_xfer_recv_ticket_got(PurpleConnection *gc, const gchar *ticket_id)
+{
+	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+
+	g_return_if_fail(sdata != NULL);
+
+	if (g_hash_table_lookup(sdata->xfers_history, ticket_id)) {
 		return;
 	}
 
-	if (purple_debug_is_unsafe())
-		purple_debug_misc("gg", "ggp_ggdrive_auth_done: "
-			"security_token=%s\n", sdata->security_token);
-	ggp_ggdrive_auth_results(gc, TRUE);
+	ggp_ggdrive_auth(gc, ggp_edisc_xfer_recv_ticket_update_authenticated,
+	                 g_strdup(ticket_id));
 }
 
+void
+ggp_edisc_xfer_ticket_changed(PurpleConnection *gc, const char *data)
+{
+	ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+	PurpleXfer *xfer;
+	JsonParser *parser;
+	JsonObject *ticket;
+	const gchar *ticket_id, *send_status;
+	ggp_edisc_xfer_ack_status ack_status;
+	gboolean is_completed;
+
+	g_return_if_fail(sdata != NULL);
+
+	parser = ggp_json_parse(data);
+	ticket = json_node_get_object(json_parser_get_root(parser));
+	ticket_id = json_object_get_string_member(ticket, "id");
+	ack_status = ggp_edisc_xfer_parse_ack_status(
+	        json_object_get_string_member(ticket, "ack_status"));
+	send_status = json_object_get_string_member(ticket, "send_status");
+
+	if (ticket_id == NULL) {
+		ticket_id = "";
+	}
+	xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
+	if (xfer == NULL) {
+		purple_debug_misc("gg",
+		                  "ggp_edisc_event_ticket_changed: ticket %s not "
+		                  "found, updating it...",
+		                  purple_debug_is_unsafe() ? ticket_id : "");
+		ggp_edisc_xfer_recv_ticket_got(gc, ticket_id);
+		g_object_unref(parser);
+		return;
+	}
+
+	is_completed = FALSE;
+	if (g_strcmp0("in_progress", send_status) == 0) {
+		/* do nothing */
+	} else if (g_strcmp0("completed", send_status) == 0) {
+		is_completed = TRUE;
+	} else if (g_strcmp0("expired", send_status) == 0)
+		ggp_edisc_xfer_error(xfer, _("File transfer expired."));
+	else {
+		purple_debug_warning(
+		        "gg", "ggp_edisc_event_ticket_changed: unknown send_status=%s",
+		        send_status);
+		g_object_unref(parser);
+		return;
+	}
+
+	g_object_unref(parser);
+
+	if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) {
+		if (is_completed) {
+			ggp_edisc_xfer_recv_ticket_completed(xfer);
+		}
+	} else {
+		if (ack_status != GGP_EDISC_XFER_ACK_STATUS_UNKNOWN) {
+			ggp_edisc_xfer_send_ticket_changed(
+			        gc, xfer, ack_status == GGP_EDISC_XFER_ACK_STATUS_ALLOWED);
+		}
+	}
+}
+
+/*******************************************************************************
+ * GObject implementation
+ ******************************************************************************/
+
 G_DEFINE_DYNAMIC_TYPE(GGPXfer, ggp_xfer, PURPLE_TYPE_XFER);
 
 static void

mercurial