Mon, 22 Oct 2012 01:26:22 +0200
Edisc authentication, file transfer implementation started
| libpurple/protocols/gg/Makefile.am | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/gg/edisc.c | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/gg/edisc.h | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/gg/gg.c | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/gg/gg.h | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/gg/ggdrive.c | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/gg/ggdrive.h | file | annotate | diff | comparison | revisions |
--- a/libpurple/protocols/gg/Makefile.am Sun Oct 21 22:51:13 2012 +0200 +++ b/libpurple/protocols/gg/Makefile.am Mon Oct 22 01:26:22 2012 +0200 @@ -62,10 +62,10 @@ chat.h \ deprecated.c \ deprecated.h \ + edisc.c \ + edisc.h \ gg.c \ gg.h \ - ggdrive.c \ - ggdrive.h \ html.c \ html.h \ image.c \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/gg/edisc.c Mon Oct 22 01:26:22 2012 +0200 @@ -0,0 +1,317 @@ +#include "edisc.h" + +#include <debug.h> + +#include "gg.h" +#include "libgaduw.h" +#include <http.h> + +#define GGP_EDISC_HOSTNAME "MyComputer" +#define GGP_EDISC_OS "WINNT x86-msvc" +#define GGP_EDISC_TYPE "desktop" + +#define GGP_EDISC_RESPONSE_MAX 10240 + +typedef struct _ggp_edisc_auth_data ggp_edisc_auth_data; + +typedef struct _ggp_edisc_xfer ggp_edisc_xfer; + +struct _ggp_edisc_session_data +{ + PurpleHttpCookieJar *cookies; + gchar *security_token; + + PurpleHttpConnection *auth_request; + gboolean auth_done; + GList *auth_pending; +}; + +struct _ggp_edisc_xfer +{ + PurpleConnection *gc; +}; + +typedef void (*ggp_ggdrive_auth_cb)(PurpleConnection *gc, gboolean success, + gpointer user_data); + +static void ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb, + gpointer user_data); + +static void ggp_edisc_xfer_free(PurpleXfer *xfer); + +/******************************************************************************* + * Setting up. + ******************************************************************************/ + +static inline ggp_edisc_session_data * +ggp_edisc_get_sdata(PurpleConnection *gc) +{ + GGPInfo *accdata = purple_connection_get_protocol_data(gc); + return accdata->edisc_data; +} + +void ggp_edisc_setup(PurpleConnection *gc) +{ + GGPInfo *accdata = purple_connection_get_protocol_data(gc); + ggp_edisc_session_data *sdata = g_new0(ggp_edisc_session_data, 1); + + accdata->edisc_data = sdata; + + sdata->cookies = purple_http_cookie_jar_new(); +} + +void ggp_edisc_cleanup(PurpleConnection *gc) +{ + ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc); + + purple_http_conn_cancel(sdata->auth_request); + g_list_free_full(sdata->auth_pending, g_free); + g_free(sdata->security_token); + + purple_http_cookie_jar_unref(sdata->cookies); + + g_free(sdata); +} + +/******************************************************************************* + * Sending a file. + ******************************************************************************/ + +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_error(PurpleXfer *xfer, const gchar *msg); + +static void ggp_edisc_xfer_free(PurpleXfer *xfer) +{ + ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer); + + if (edisc_xfer == NULL) + return; + + g_free(edisc_xfer); + purple_xfer_set_protocol_data(xfer, NULL); +} + +static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg) +{ + purple_xfer_error( + purple_xfer_get_type(xfer), + purple_xfer_get_account(xfer), + purple_xfer_get_remote_user(xfer), + msg); + ggp_edisc_xfer_free(xfer); +} + +gboolean ggp_edisc_xfer_can_receive_file(PurpleConnection *gc, const char *who) +{ + return TRUE; /* TODO: only online, buddies (?) */ +} + +static void ggp_edisc_xfer_init(PurpleXfer *xfer) +{ + ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer); + + if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) { + purple_debug_error("gg", "ggp_edisc_xfer_init: " + "Not yet implemented\n"); + return; + } + + 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) +{ + PurpleXfer *xfer = _xfer; + + if (!success) { + ggp_edisc_xfer_error(xfer, _("Authentication failed")); + return; + } + + /* TODO: requesting a ticket */ + + purple_xfer_start(xfer, -1, NULL, 0); +} + +static void ggp_edisc_xfer_start(PurpleXfer *xfer) +{ + g_return_if_fail(xfer != NULL); + + if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) { + purple_debug_error("gg", "ggp_edisc_xfer_start: " + "Not yet implemented\n"); + return; + } + + purple_debug_info("gg", "Starting a file transfer...\n"); +} + +PurpleXfer * ggp_edisc_xfer_new(PurpleConnection *gc, const char *who) +{ + PurpleXfer *xfer; + ggp_edisc_xfer *edisc_xfer; + + g_return_val_if_fail(gc != NULL, NULL); + g_return_val_if_fail(who != NULL, NULL); + + xfer = purple_xfer_new(purple_connection_get_account(gc), + PURPLE_XFER_SEND, who); + edisc_xfer = g_new0(ggp_edisc_xfer, 1); + purple_xfer_set_protocol_data(xfer, edisc_xfer); + + edisc_xfer->gc = gc; + + purple_xfer_set_init_fnc(xfer, ggp_edisc_xfer_init); + purple_xfer_set_start_fnc(xfer, ggp_edisc_xfer_start); + + //purple_xfer_set_cancel_send_fnc(xfer, bonjour_xfer_cancel_send); + //purple_xfer_set_end_fnc(xfer, bonjour_xfer_end); + + return xfer; +} + +void ggp_edisc_xfer_send_file(PurpleConnection *gc, const char *who, + const char *filename) +{ + PurpleXfer *xfer; + + g_return_if_fail(gc != NULL); + g_return_if_fail(who != NULL); + + /* Nothing interesting here, this code is common among prpls. + * See ggp_edisc_new_xfer. */ + + xfer = ggp_edisc_xfer_new(gc, who); + if (filename) + purple_xfer_request_accepted(xfer, filename); + else + purple_xfer_request(xfer); +} + +/******************************************************************************* + * Authentication + ******************************************************************************/ + +struct _ggp_edisc_auth_data +{ + 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; + PurpleHttpRequest *req; + + 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)\n", gc); + + req = purple_http_request_new("https://drive.mpa.gg.pl/signin"); + 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); + + metadata = g_strdup_printf("{" + "\"id\": \"%032x\", " + "\"name\": \"" GGP_EDISC_HOSTNAME "\", " + "\"os_version\": \"" GGP_EDISC_OS "\", " + "\"client_version\": \"%s\", " + "\"type\": \"" GGP_EDISC_TYPE "\"}", + g_random_int_range(1, 1 << 16), + 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); + purple_http_request_header_set(req, "X-gged-api-version", "6"); + 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); + + 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); + + sdata->auth_request = NULL; + + if (!purple_http_response_is_successfull(response) || + 0 != strcmp(purple_http_response_get_data(response), + "{\"result\":{\"status\":0}}")) { + 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) { + ggp_ggdrive_auth_results(gc, FALSE); + 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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/gg/edisc.h Mon Oct 22 01:26:22 2012 +0200 @@ -0,0 +1,18 @@ +#ifndef _GGP_EDISC_H +#define _GGP_EDISC_H + +#include <internal.h> + +typedef struct _ggp_edisc_session_data ggp_edisc_session_data; + +void ggp_edisc_setup(PurpleConnection *gc); +void ggp_edisc_cleanup(PurpleConnection *gc); + +gboolean ggp_edisc_xfer_can_receive_file(PurpleConnection *gc, const char *who); + +void ggp_edisc_xfer_send_file(PurpleConnection *gc, const char *who, + const char *filename); + +PurpleXfer * ggp_edisc_xfer_new(PurpleConnection *gc, const char *who); + +#endif /* _GGP_EDISC_H */
--- a/libpurple/protocols/gg/gg.c Sun Oct 21 22:51:13 2012 +0200 +++ b/libpurple/protocols/gg/gg.c Mon Oct 22 01:26:22 2012 +0200 @@ -54,7 +54,6 @@ #include "pubdir-prpl.h" #include "message-prpl.h" #include "html.h" -#include "ggdrive.h" /* ---------------------------------------------------------------------- */ @@ -378,7 +377,6 @@ purple_debug_info("gg", "gg11: got IMTOKEN\n"); g_free(info->imtoken); info->imtoken = g_strdup(ev->event.imtoken.imtoken); - ggp_ggdrive_test(gc); break; case GG_EVENT_PONG110: purple_debug_info("gg", "gg11: got PONG110 %lu\n", ev->event.pong110.time); @@ -658,6 +656,7 @@ ggp_status_setup(gc); ggp_chat_setup(gc); ggp_message_setup(gc); + ggp_edisc_setup(gc); glp->uin = ggp_str_to_uin(purple_account_get_username(account)); glp->password = ggp_convert_to_cp1250(purple_account_get_password(account)); @@ -763,6 +762,7 @@ ggp_status_cleanup(gc); ggp_chat_cleanup(gc); ggp_message_cleanup(gc); + ggp_edisc_cleanup(gc); if (info->inpa > 0) purple_input_remove(info->inpa); @@ -972,9 +972,9 @@ ggp_chat_roomlist_get_list, /* roomlist_get_list */ NULL, /* roomlist_cancel */ NULL, /* roomlist_expand_category */ - NULL, /* can_receive_file */ - NULL, /* send_file */ - NULL, /* new_xfer */ + ggp_edisc_xfer_can_receive_file,/* can_receive_file */ + ggp_edisc_xfer_send_file, /* send_file */ + ggp_edisc_xfer_new, /* new_xfer */ ggp_offline_message, /* offline_message */ NULL, /* whiteboard_prpl_ops */ NULL, /* send_raw */
--- a/libpurple/protocols/gg/gg.h Sun Oct 21 22:51:13 2012 +0200 +++ b/libpurple/protocols/gg/gg.h Mon Oct 22 01:26:22 2012 +0200 @@ -37,6 +37,7 @@ #include "status.h" #include "chat.h" #include "message-prpl.h" +#include "edisc.h" #define GGP_UIN_LEN_MAX 10 @@ -54,6 +55,7 @@ ggp_status_session_data *status_data; ggp_chat_session_data *chat_data; ggp_message_session_data *message_data; + ggp_edisc_session_data *edisc_data; } GGPInfo; typedef struct
--- a/libpurple/protocols/gg/ggdrive.c Sun Oct 21 22:51:13 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -#include "ggdrive.h" - -#include <debug.h> - -#include "gg.h" -#include "libgaduw.h" - -#define GGP_GGDRIVE_HOSTNAME "MyComputer" -#define GGP_GGDRIVE_OS "WINNT x86-msvc" -#define GGP_GGDRIVE_TYPE "desktop" - -#define GGP_GGDRIVE_RESPONSE_MAX 1024 - -/******************************************************************************* - * Authentication - ******************************************************************************/ - -typedef void (*ggp_ggdrive_authentication_cb)(const gchar *security_token, - gpointer user_data); - -static void ggp_ggdrive_authenticate(PurpleConnection *gc, - ggp_ggdrive_authentication_cb cb, gpointer user_data); - -#if 0 -static void ggp_ggdrive_authenticate_done(PurpleUtilFetchUrlData *url_data, - gpointer _user_data, const gchar *url_text, gsize len, - const gchar *error_message); -#endif - -typedef struct -{ - PurpleConnection *gc; - ggp_ggdrive_authentication_cb cb; - gpointer user_data; -} ggp_ggdrive_authenticate_data; - -/******************************************************************************/ - -static void ggp_ggdrive_authenticate(PurpleConnection *gc, - ggp_ggdrive_authentication_cb cb, gpointer user_data) -{ -#if 0 - PurpleAccount *account = purple_connection_get_account(gc); - const gchar *imtoken; - gchar *request, *metadata; - ggp_ggdrive_authenticate_data *req_data; - - imtoken = ggp_get_imtoken(gc); - if (!imtoken) - { - cb(NULL, user_data); - return; - } - - metadata = g_strdup_printf("{" - "\"id\": \"%032x\", " - "\"name\": \"" GGP_GGDRIVE_HOSTNAME "\", " - "\"os_version\": \"" GGP_GGDRIVE_OS "\", " - "\"client_version\": \"%s\", " - "\"type\": \"" GGP_GGDRIVE_TYPE "\"}", - g_random_int_range(1, 1 << 16), - ggp_libgaduw_version(gc)); - - request = g_strdup_printf( - "PUT /signin HTTP/1.1\r\n" - "Host: drive.mpa.gg.pl\r\n" - "Authorization: IMToken %s\r\n" - "X-gged-user: gg/pl:%u\r\n" - "X-gged-client-metadata: %s\r\n" - "X-gged-api-version: 6\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 0\r\n" - "\r\n", - imtoken, ggp_own_uin(gc), metadata); - - req_data = g_new0(ggp_ggdrive_authenticate_data, 1); - req_data->gc = gc; - req_data->cb = cb; - req_data->user_data = user_data; - - purple_util_fetch_url_request(account, "https://drive.mpa.gg.pl/signin", - FALSE, NULL, TRUE, request, TRUE, GGP_GGDRIVE_RESPONSE_MAX, - ggp_ggdrive_authenticate_done, req_data); - - g_free(metadata); - g_free(request); -#endif -} - -#if 0 -static void ggp_ggdrive_authenticate_done(PurpleUtilFetchUrlData *url_data, - gpointer _user_data, const gchar *url_text, gsize len, - const gchar *error_message) -{ - ggp_ggdrive_authenticate_data *req_data = _user_data; - PurpleConnection *gc = req_data->gc; - ggp_ggdrive_authentication_cb cb = req_data->cb; - gpointer user_data = req_data->user_data; - - g_free(req_data); - - if (!PURPLE_CONNECTION_IS_VALID(gc)) - { - cb(NULL, user_data); - return; - } - - if (len == 0) - { - purple_debug_error("gg", "ggp_ggdrive_authenticate_done: failed\n"); - cb(NULL, user_data); - return; - } - - purple_debug_info("gg", "ggp_ggdrive_authenticate_done: [%s]\n", url_text); -} -#endif - -/***/ - -static void ggp_ggdrive_test_cb(const gchar *security_token, - gpointer user_data) -{ - if (!security_token) - purple_debug_error("gg", "ggp_ggdrive_test_cb: didn't got security token\n"); - else - purple_debug_info("gg", "ggp_ggdrive_test_cb: got security token [%s]\n", security_token); -} - -void ggp_ggdrive_test(PurpleConnection *gc) -{ - ggp_ggdrive_authenticate(gc, ggp_ggdrive_test_cb, NULL); -}