--- 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,
-static inline ggp_edisc_session_data *
-ggp_edisc_get_sdata(PurpleConnection *gc);
-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);
-static void ggp_edisc_xfer_send_ticket_changed(PurpleConnection *gc,
- PurpleXfer *xfer, gboolean is_allowed);
-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);
-static void ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb,
/*******************************************************************************
******************************************************************************/
@@ -210,10 +177,41 @@
+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; + "gg", "ggp_edisc_xfer_parse_ack_status: unknown status (%s)", str); + return GGP_EDISC_XFER_ACK_STATUS_UNKNOWN; /*******************************************************************************
* General xfer functions.
******************************************************************************/
+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); static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg)
if (purple_xfer_is_cancelled(xfer))
@@ -228,74 +226,6 @@
-void ggp_edisc_xfer_ticket_changed(PurpleConnection *gc, const char *data)
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- const gchar *ticket_id, *send_status;
- ggp_edisc_xfer_ack_status ack_status;
- 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");
- xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
- 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);
- if (g_strcmp0("in_progress", send_status) == 0) {
- } else if (g_strcmp0("completed", send_status) == 0) {
- } else if (g_strcmp0("expired", send_status) == 0)
- ggp_edisc_xfer_error(xfer, _("File transfer expired."));
- purple_debug_warning("gg", "ggp_edisc_event_ticket_changed: "
- "unknown send_status=%s\n", send_status);
- g_object_unref(parser);
- g_object_unref(parser);
- if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) {
- ggp_edisc_xfer_recv_ticket_completed(xfer);
- 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);
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)
+/******************************************************************************* + ******************************************************************************/ +typedef struct _ggp_edisc_auth_data { + ggp_ggdrive_auth_cb cb; +ggp_ggdrive_auth_results(PurpleConnection *gc, gboolean success) + ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc); + 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); + ggp_edisc_auth_data *auth = it->data; + auth->cb(gc, success, auth->user_data); + g_list_free(sdata->auth_pending); + sdata->auth_pending = NULL; + sdata->auth_done = TRUE; +ggp_ggdrive_auth_done(PurpleHttpConnection *hc, PurpleHttpResponse *response, - 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); + 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); + 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); + purple_debug_misc("gg", + "ggp_ggdrive_auth_done: authentication failed due to " + "bad result (status=%d)", + 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); + 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); + 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;
+ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb, + GGPInfo *accdata = purple_connection_get_protocol_data(gc); + ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc); + ggp_edisc_auth_data *auth; + PurpleHttpRequest *req; + g_return_if_fail(sdata != NULL); + imtoken = ggp_get_imtoken(gc); + cb(gc, FALSE, user_data); + if (sdata->auth_done) { + cb(gc, sdata->security_token != NULL, user_data); + auth = g_new0(ggp_edisc_auth_data, 1); + auth->user_data = user_data; + sdata->auth_pending = g_list_prepend(sdata->auth_pending, auth); + if (sdata->auth_request) { + 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;
+ "\"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", + 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); + purple_http_request(gc, req, ggp_ggdrive_auth_done, NULL); + purple_http_request_unref(req); +ggp_edisc_xfer_send_ticket_changed(PurpleConnection *gc, PurpleXfer *xfer, + GGPXfer *edisc_xfer = GGP_XFER(xfer); + "ggp_edisc_event_ticket_changed: transfer %p already free'd", + "gg", "ggp_edisc_event_ticket_changed: transfer %p rejected", + purple_xfer_cancel_remote(xfer); + if (edisc_xfer->allowed) { + "ggp_edisc_event_ticket_changed: transfer %p already allowed", + edisc_xfer->allowed = TRUE; + purple_xfer_start(xfer, -1, NULL, 0); /*******************************************************************************
******************************************************************************/
-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,
+ggp_edisc_xfer_can_receive_file(PurpleProtocolXfer *prplxfer, + PurpleConnection *gc, const char *who) @@ -362,71 +451,15 @@
g_return_val_if_fail(who != NULL, FALSE);
buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who);
/* 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,
-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 (purple_xfer_is_cancelled(xfer))
- ggp_edisc_xfer_error(xfer, _("Authentication failed"));
- 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\","
- purple_xfer_get_remote_user(xfer),
- (int)purple_xfer_get_size(xfer));
- purple_http_request_set_contents(req, data, -1);
- 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,
+ggp_edisc_xfer_send_init_authenticated(PurpleConnection *gc, gboolean success, + ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc); + PurpleHttpRequest *req; + PurpleXfer *xfer = _xfer; GGPXfer *edisc_xfer = GGP_XFER(xfer);
- purple_debug_fatal("gg", "ggp_edisc_event_ticket_changed: "
- "transfer %p already free'd\n", xfer);
+ if (purple_xfer_is_cancelled(xfer)) { + ggp_edisc_xfer_error(xfer, _("Authentication failed"));
- purple_debug_info("gg", "ggp_edisc_event_ticket_changed: "
- "transfer %p rejected\n", xfer);
- purple_xfer_cancel_remote(xfer);
+ 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);
- edisc_xfer->allowed = TRUE;
+ data = g_strdup_printf("{\"send_ticket\":{" + "\"recipient\":\"%s\"," + "\"file_name\":\"%s\"," + purple_xfer_get_remote_user(xfer), + (int)purple_xfer_get_size(xfer)); + purple_http_request_set_contents(req, data, -1); - 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); +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, static void ggp_edisc_xfer_send_reader(PurpleHttpConnection *hc,
@@ -553,6 +619,46 @@
cb(hc, success, eof, stored);
+ggp_edisc_xfer_send_done(PurpleHttpConnection *hc, PurpleHttpResponse *response, + PurpleXfer *xfer = _xfer; + GGPXfer *edisc_xfer = GGP_XFER(xfer); + const gchar *data = purple_http_response_get_data(response, NULL); + int result_status = -1; + if (purple_xfer_is_cancelled(xfer)) { + g_return_if_fail(edisc_xfer != NULL); + if (!purple_http_response_is_successful(response)) { + ggp_edisc_xfer_error(xfer, _("Error while sending a file")); + 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); + 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);
- int result_status = -1;
- if (purple_xfer_is_cancelled(xfer))
- g_return_if_fail(edisc_xfer != NULL);
- if (!purple_http_response_is_successful(response)) {
- ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
- 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);
- ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
PurpleXfer * ggp_edisc_xfer_send_new(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who)
@@ -676,199 +744,44 @@
******************************************************************************/
-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,
-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))
- ggp_ggdrive_auth(gc, ggp_edisc_xfer_recv_ticket_update_authenticated,
-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);
- purple_debug_warning("gg",
- "ggp_edisc_xfer_recv_ticket_update_authenticated: "
- "update of ticket %s aborted due to authentication "
- req = purple_http_request_new(ggp_edisc_xfer_ticket_url(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,
- 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);
- ggp_edisc_session_data *sdata;
- const gchar *ticket_id, *file_name, *send_mode_str;
- uin_t sender, recipient;
- 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));
- 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");
- purple_debug_warning("gg",
- "ggp_edisc_xfer_recv_ticket_update_got: failed to get "
- "update (status=%d)\n", status);
- g_object_unref(parser);
- ticket_id = json_object_get_string_member(result, "id");
- sender = ggp_str_to_uin(json_object_get_string_member(result,
- recipient = ggp_str_to_uin(json_object_get_string_member(result,
- 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");
- * AQQ 2.4.2.10: direct_inbox
- send_mode_str = json_object_get_string_member(result, "send_mode");
- * 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, "
- xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
- 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);
- 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 : "",
- g_object_unref(parser);
- 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,
+ggp_edisc_xfer_recv_new(PurpleConnection *gc, const char *who) g_return_val_if_fail(gc != NULL, NULL);
g_return_val_if_fail(who != NULL, NULL);
- "account", purple_connection_get_account(gc),
- "type", PURPLE_XFER_TYPE_RECEIVE,
+ xfer = g_object_new(GGP_TYPE_XFER, "account", + purple_connection_get_account(gc), "type", + PURPLE_XFER_TYPE_RECEIVE, "remote-user", who, NULL); return PURPLE_XFER(xfer);
-static void ggp_edisc_xfer_recv_reject(PurpleXfer *xfer)
+ggp_edisc_xfer_recv_ack_done(PurpleHttpConnection *hc, + PurpleHttpResponse *response, gpointer _xfer) - ggp_edisc_xfer_recv_ack(xfer, FALSE);
+ PurpleXfer *xfer = _xfer; + if (purple_xfer_is_cancelled(xfer)) { -static void ggp_edisc_xfer_recv_accept(PurpleXfer *xfer)
- ggp_edisc_xfer_recv_ack(xfer, TRUE);
+ edisc_xfer = GGP_XFER(xfer); + if (!purple_http_response_is_successful(response)) { + ggp_edisc_xfer_error(xfer, _("Cannot confirm file transfer.")); + 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)
+ggp_edisc_xfer_recv_reject(PurpleXfer *xfer) - PurpleXfer *xfer = _xfer;
- if (purple_xfer_is_cancelled(xfer))
+ ggp_edisc_xfer_recv_ack(xfer, FALSE); - edisc_xfer = GGP_XFER(xfer);
- if (!purple_http_response_is_successful(response)) {
- ggp_edisc_xfer_error(xfer, _("Cannot confirm file transfer."));
- purple_debug_info("gg", "ggp_edisc_xfer_recv_ack_done: [%s]\n",
- purple_http_response_get_data(response, NULL));
+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;
- 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);
- 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,
- 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 @@
-/*******************************************************************************
- ******************************************************************************/
-struct _ggp_edisc_auth_data
+ggp_edisc_xfer_recv_start(PurpleXfer *xfer) - ggp_ggdrive_auth_cb cb;
-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,
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- ggp_edisc_auth_data *auth;
+ ggp_edisc_session_data *sdata; + 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);
- cb(gc, FALSE, user_data);
+ g_strdup_printf("https://drive.mpa.gg.pl/me/file/inbox/" + "%s,%s?api_version=%s&security_token=%s", + purple_url_encode(purple_xfer_get_filename(xfer)), + GGP_EDISC_API, sdata->security_token); + req = purple_http_request_new(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, + 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); +ggp_edisc_xfer_recv_ticket_update_got(PurpleHttpConnection *hc, + PurpleHttpResponse *response, + PurpleConnection *gc = purple_http_conn_get_purple_connection(hc); + ggp_edisc_session_data *sdata; + const gchar *ticket_id, *file_name, *send_mode_str; + uin_t sender, recipient; + 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)); - auth = g_new0(ggp_edisc_auth_data, 1);
- auth->user_data = user_data;
- sdata->auth_pending = g_list_prepend(sdata->auth_pending, auth);
- if (sdata->auth_request)
- 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("{"
- "\"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);
- 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);
- purple_debug_info("gg", "ggp_ggdrive_auth_results(gc=%p): %d\n",
+ sdata = ggp_edisc_get_sdata(gc); g_return_if_fail(sdata != NULL);
- it = g_list_first(sdata->auth_pending);
- ggp_edisc_auth_data *auth = it->data;
- auth->cb(gc, success, auth->user_data);
- 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);
- 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);
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"); + purple_debug_warning("gg", + "ggp_edisc_xfer_recv_ticket_update_got: failed to " + "get update (status=%d)", + g_object_unref(parser); + ticket_id = json_object_get_string_member(result, "id"); + sender = ggp_str_to_uin(json_object_get_string_member(result, "sender")); + 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"); + * AQQ 2.4.2.10: direct_inbox + send_mode_str = json_object_get_string_member(result, "send_mode"); + * 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,
- 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: "
- purple_http_response_get_data(response, NULL));
- ggp_ggdrive_auth_results(gc, FALSE);
+ xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id); + purple_debug_misc("gg", + "ggp_edisc_xfer_recv_ticket_update_got: ticket %s " + purple_debug_is_unsafe() ? ticket_id : ""); + g_object_unref(parser); + 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, + g_object_unref(parser); + 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), + g_object_unref(parser); +ggp_edisc_xfer_recv_ticket_update_authenticated(PurpleConnection *gc, + ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc); + PurpleHttpRequest *req; + gchar *ticket = _ticket; + g_return_if_fail(sdata != NULL); + "ggp_edisc_xfer_recv_ticket_update_authenticated: update of " + "ticket %s aborted due to authentication failure", - 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)); + 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); +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)) { - 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, +ggp_edisc_xfer_ticket_changed(PurpleConnection *gc, const char *data) + ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc); + const gchar *ticket_id, *send_status; + ggp_edisc_xfer_ack_status ack_status; + 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) { + xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id); + 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); + if (g_strcmp0("in_progress", send_status) == 0) { + } else if (g_strcmp0("completed", send_status) == 0) { + } else if (g_strcmp0("expired", send_status) == 0) + ggp_edisc_xfer_error(xfer, _("File transfer expired.")); + "gg", "ggp_edisc_event_ticket_changed: unknown send_status=%s", + g_object_unref(parser); + g_object_unref(parser); + if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) { + ggp_edisc_xfer_recv_ticket_completed(xfer); + 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);