/cpw/tomkiewicz/gg11: 4b1a106bbf1d: Preparing a file transfer
Tomasz Wasilczyk
tomkiewicz at cpw.pidgin.im
Mon Oct 22 15:21:27 EDT 2012
Changeset: 4b1a106bbf1d45470860ea0c946bed09d4b61336
Author: Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date: 2012-10-22 21:21 +0200
Branch: default
URL: http://hg.pidgin.im/cpw/tomkiewicz/gg11/rev/4b1a106bbf1d
Description:
Preparing a file transfer
diffstat:
libpurple/protocols/gg/Makefile.am | 3 +
libpurple/protocols/gg/edisc.c | 250 +++++++++++++++++++++++++++++++-
libpurple/protocols/gg/edisc.h | 3 +
libpurple/protocols/gg/gg.c | 6 +-
libpurple/protocols/gg/libgadu-events.c | 17 ++
libpurple/protocols/gg/libgadu-events.h | 2 +
6 files changed, 274 insertions(+), 7 deletions(-)
diffs (truncated from 449 to 300 lines):
diff --git a/libpurple/protocols/gg/Makefile.am b/libpurple/protocols/gg/Makefile.am
--- a/libpurple/protocols/gg/Makefile.am
+++ b/libpurple/protocols/gg/Makefile.am
@@ -50,6 +50,8 @@ GADU_LIBS += $(GNUTLS_LIBS)
GADU_CFLAGS += $(GNUTLS_CFLAGS)
endif
+GADU_LIBS += $(JSON_LIBS)
+
GGSOURCES = \
$(INTGGSOURCES) \
account.c \
@@ -129,5 +131,6 @@ AM_CPPFLAGS = \
-I$(top_builddir)/libpurple \
$(INTGG_CFLAGS) \
$(GLIB_CFLAGS) \
+ $(JSON_CFLAGS) \
$(DEBUG_CFLAGS) \
$(GADU_EXTRA)
diff --git a/libpurple/protocols/gg/edisc.c b/libpurple/protocols/gg/edisc.c
--- a/libpurple/protocols/gg/edisc.c
+++ b/libpurple/protocols/gg/edisc.c
@@ -6,6 +6,8 @@
#include "libgaduw.h"
#include <http.h>
+#include <json-glib/json-glib.h>
+
#define GGP_EDISC_HOSTNAME "MyComputer"
#define GGP_EDISC_OS "WINNT x86-msvc"
#define GGP_EDISC_TYPE "desktop"
@@ -18,6 +20,8 @@ typedef struct _ggp_edisc_xfer ggp_edisc
struct _ggp_edisc_session_data
{
+ GHashTable *xfers_initialized;
+
PurpleHttpCookieJar *cookies;
gchar *security_token;
@@ -28,7 +32,13 @@ struct _ggp_edisc_session_data
struct _ggp_edisc_xfer
{
+ gchar *filename;
+ gchar *ticket_id;
+
+ gboolean allowed;
+
PurpleConnection *gc;
+ PurpleHttpConnection *hc;
};
typedef void (*ggp_ggdrive_auth_cb)(PurpleConnection *gc, gboolean success,
@@ -58,6 +68,7 @@ void ggp_edisc_setup(PurpleConnection *g
accdata->edisc_data = sdata;
sdata->cookies = purple_http_cookie_jar_new();
+ sdata->xfers_initialized = g_hash_table_new(g_str_hash, g_str_equal);
}
void ggp_edisc_cleanup(PurpleConnection *gc)
@@ -69,6 +80,7 @@ void ggp_edisc_cleanup(PurpleConnection
g_free(sdata->security_token);
purple_http_cookie_jar_unref(sdata->cookies);
+ g_hash_table_destroy(sdata->xfers_initialized);
g_free(sdata);
}
@@ -80,22 +92,34 @@ void ggp_edisc_cleanup(PurpleConnection
static void ggp_edisc_xfer_init(PurpleXfer *xfer);
static void ggp_edisc_xfer_init_authenticated(PurpleConnection *gc,
gboolean success, gpointer _xfer);
+static void ggp_edisc_xfer_init_ticket_sent(PurpleHttpConnection *hc,
+ PurpleHttpResponse *response, gpointer _xfer);
static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg);
static void ggp_edisc_xfer_free(PurpleXfer *xfer)
{
+ ggp_edisc_session_data *sdata;
ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer);
if (edisc_xfer == NULL)
return;
+ g_free(edisc_xfer->filename);
+
+ sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
+ g_hash_table_remove(sdata->xfers_initialized,
+ edisc_xfer->ticket_id);
+
g_free(edisc_xfer);
purple_xfer_set_protocol_data(xfer, NULL);
+
}
static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg)
{
+ purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
+ purple_xfer_conversation_write(xfer, msg, TRUE);
purple_xfer_error(
purple_xfer_get_type(xfer),
purple_xfer_get_account(xfer),
@@ -104,6 +128,35 @@ static void ggp_edisc_xfer_error(PurpleX
ggp_edisc_xfer_free(xfer);
}
+static int ggp_edisc_parse_error(const gchar *data)
+{
+ JsonParser *parser;
+ JsonObject *result;
+ int error_id;
+
+ parser = json_parser_new();
+ if (!json_parser_load_from_data(parser, data, -1, NULL)) {
+ if (purple_debug_is_unsafe())
+ purple_debug_error("gg", "ggp_edisc_parse_error: "
+ "couldn't parse error: %s\n", data);
+ else
+ purple_debug_error("gg", "ggp_edisc_parse_error: "
+ "couldn't parse error\n");
+ g_object_unref(parser);
+ return 0;
+ }
+
+ result = json_node_get_object(json_parser_get_root(parser));
+ result = json_object_get_object_member(result, "result");
+ error_id = json_object_get_int_member(result, "appStatus");
+ purple_debug_info("gg", "edisc error: %s (%d)\n",
+ json_object_get_string_member(result, "errorMsg"),
+ error_id);
+ g_object_unref(parser);
+
+ return error_id;
+}
+
gboolean ggp_edisc_xfer_can_receive_file(PurpleConnection *gc, const char *who)
{
return TRUE; /* TODO: only online, buddies (?) */
@@ -119,20 +172,183 @@ static void ggp_edisc_xfer_init(PurpleXf
return;
}
+ purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_NOT_STARTED);
+
+ edisc_xfer->filename = g_strdup(purple_xfer_get_filename(xfer)); /* TODO: filter */
+
ggp_ggdrive_auth(edisc_xfer->gc, ggp_edisc_xfer_init_authenticated, xfer);
}
static void ggp_edisc_xfer_init_authenticated(PurpleConnection *gc,
gboolean success, gpointer _xfer)
{
+ ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+ PurpleHttpRequest *req;
PurpleXfer *xfer = _xfer;
+ ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer);
+ gchar *data;
if (!success) {
ggp_edisc_xfer_error(xfer, _("Authentication failed"));
return;
}
- /* TODO: requesting a ticket */
+ req = purple_http_request_new("https://drive.mpa.gg.pl/send_ticket");
+ purple_http_request_set_method(req, "PUT");
+
+ /* TODO: defaults (browser name, etc) */
+ purple_http_request_set_max_len(req, GGP_EDISC_RESPONSE_MAX);
+ purple_http_request_set_cookie_jar(req, sdata->cookies);
+
+ purple_http_request_header_set(req, "X-gged-api-version", "6");
+ 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_init_ticket_sent, xfer);
+ purple_http_request_unref(req);
+}
+
+static void ggp_edisc_xfer_init_ticket_sent(PurpleHttpConnection *hc,
+ PurpleHttpResponse *response, gpointer _xfer)
+{
+ ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(
+ purple_http_conn_get_purple_connection(hc));
+ PurpleXfer *xfer = _xfer;
+ ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer);
+ const gchar *data = purple_http_response_get_data(response);
+ JsonParser *parser;
+ JsonObject *ticket;
+
+ if (!purple_http_response_is_successfull(response)) {
+ int error_id = ggp_edisc_parse_error(data);
+ if (error_id == 206) /* recipient not logged in */
+ ggp_edisc_xfer_error(xfer, _("Recipient not logged in"));
+ else
+ ggp_edisc_xfer_error(xfer, _("Cannot offer sending a file"));
+ return;
+ }
+
+ parser = json_parser_new();
+ if (!json_parser_load_from_data(parser, data, -1, NULL)) {
+ if (purple_debug_is_unsafe())
+ purple_debug_error("gg",
+ "ggp_edisc_xfer_init_ticket_sent: "
+ "invalid JSON: %s\n", data);
+ else
+ purple_debug_error("gg",
+ "ggp_edisc_xfer_init_ticket_sent: "
+ "invalid JSON\n");
+ g_object_unref(parser);
+ return;
+ }
+
+ ticket = json_node_get_object(json_parser_get_root(parser));
+ ticket = json_object_get_object_member(ticket, "result");
+ ticket = json_object_get_object_member(ticket, "send_ticket");
+ edisc_xfer->ticket_id = g_strdup(json_object_get_string_member(
+ ticket, "id"));
+
+ g_object_unref(parser);
+
+ if (edisc_xfer->ticket_id == NULL) {
+ purple_debug_error("gg",
+ "ggp_edisc_xfer_init_ticket_sent: "
+ "couldn't get ticket id\n");
+ return;
+ }
+
+ purple_debug_info("gg", "ggp_edisc_xfer_init_ticket_sent: "
+ "ticket \"%s\" created\n", edisc_xfer->ticket_id);
+
+ g_hash_table_insert(sdata->xfers_initialized,
+ edisc_xfer->ticket_id, xfer);
+}
+
+void ggp_edisc_event_send_ticket_changed(PurpleConnection *gc, const char *data)
+{
+ ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
+ PurpleXfer *xfer;
+ ggp_edisc_xfer *edisc_xfer;
+ JsonParser *parser;
+ JsonObject *ticket;
+ const gchar *ticket_id, *ack_status;
+ gboolean is_allowed;
+
+ parser = json_parser_new();
+ if (!json_parser_load_from_data(parser, data, -1, NULL)) {
+ if (purple_debug_is_unsafe())
+ purple_debug_error("gg",
+ "ggp_edisc_event_send_ticket_changed: "
+ "invalid JSON: %s\n", data);
+ else
+ purple_debug_error("gg",
+ "ggp_edisc_event_send_ticket_changed: "
+ "invalid JSON\n");
+ g_object_unref(parser);
+ return;
+ }
+
+ ticket = json_node_get_object(json_parser_get_root(parser));
+ ticket_id = json_object_get_string_member(ticket, "id");
+ ack_status = json_object_get_string_member(ticket, "ack_status");
+
+ if (g_strcmp0("unknown", ack_status) == 0) {
+ g_object_unref(parser);
+ return;
+ } else if (g_strcmp0("rejected", ack_status) == 0)
+ is_allowed = FALSE;
+ else if (g_strcmp0("allowed", ack_status) == 0)
+ is_allowed = TRUE;
+ else {
+ purple_debug_warning("gg", "ggp_edisc_event_send_ticket_changed: "
+ "unknown ack_status=%s\n", ack_status);
+ g_object_unref(parser);
+ return;
+ }
+
+ xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
+ if (xfer == NULL) {
+ purple_debug_warning("gg", "ggp_edisc_event_send_ticket_changed: "
+ "ticket %s not found\n", ticket_id);
+ g_object_unref(parser);
+ return;
+ }
+
More information about the Commits
mailing list