Mon, 02 Jul 2012 00:58:03 +0200
Gadu-Gadu: refactoring of account registration done
--- a/libpurple/protocols/gg/account.c Sat Jun 30 19:56:46 2012 +0200 +++ b/libpurple/protocols/gg/account.c Mon Jul 02 00:58:03 2012 +0200 @@ -18,27 +18,30 @@ ggp_account_token_cb callback; PurpleConnection *gc; void *user_data; - - ggp_libgaduw_http_req *req; } ggp_account_token_reqdata; -static void ggp_account_token_response(struct gg_http *h, gboolean success, gboolean cancelled, gpointer _reqdata); +static void ggp_account_token_response(struct gg_http *h, gboolean success, + gboolean cancelled, gpointer _reqdata); /******************************************************************************/ void ggp_account_token_free(ggp_account_token *token) { + if (!token) + return; g_free(token->id); g_free(token->data); g_free(token); } -void ggp_account_token_request(PurpleConnection *gc, ggp_account_token_cb callback, void *user_data) +void ggp_account_token_request(PurpleConnection *gc, + ggp_account_token_cb callback, void *user_data) { struct gg_http *h; ggp_account_token_reqdata *reqdata; - purple_debug_info("gg", "ggp_account_token_request: requesting token...\n"); + purple_debug_info("gg", "ggp_account_token_request: " + "requesting token...\n"); if (!ggp_deprecated_setup_proxy(gc)) { @@ -58,7 +61,8 @@ reqdata->callback = callback; reqdata->gc = gc; reqdata->user_data = user_data; - reqdata->req = ggp_libgaduw_http_watch(gc, h, ggp_account_token_response, reqdata, TRUE); + ggp_libgaduw_http_watch(gc, h, ggp_account_token_response, reqdata, + TRUE); } static void ggp_account_token_response(struct gg_http *h, gboolean success, @@ -71,10 +75,12 @@ g_assert(!(success && cancelled)); if (cancelled) - purple_debug_info("gg", "ggp_account_token_handler: cancelled\n"); + purple_debug_info("gg", "ggp_account_token_handler: " + "cancelled\n"); else if (success) { - purple_debug_info("gg", "ggp_account_token_handler: got token\n"); + purple_debug_info("gg", "ggp_account_token_handler: " + "got token\n"); token = g_new(ggp_account_token, 1); @@ -82,6 +88,7 @@ token->id = g_strdup(token_info->tokenid); token->size = h->body_size; token->data = g_memdup(h->body, token->size); + token->length = token_info->length; } else { @@ -89,10 +96,9 @@ purple_notify_error( purple_connection_get_account(reqdata->gc), _("Token Error"), - _("Unable to fetch the token.\n"), NULL); + _("Unable to fetch the token."), NULL); } - gg_token_free(h); reqdata->callback(reqdata->gc, token, reqdata->user_data); g_free(reqdata); } @@ -105,93 +111,118 @@ { ggp_account_token *token; PurpleConnection *gc; + + gchar *email; + gchar *password; + gchar *token_value; + gboolean password_remember; } ggp_account_register_data; -static void ggp_account_register_dialog(PurpleConnection *gc, ggp_account_token *token, gpointer user_data); -static void ggp_account_register_dialog_ok(ggp_account_register_data *register_data, PurpleRequestFields *fields); -static void ggp_account_register_dialog_cancel(ggp_account_register_data *register_data, PurpleRequestFields *fields); -static void ggp_account_register_completed(ggp_account_register_data *register_data, gboolean success); +static void ggp_account_register_dialog(PurpleConnection *gc, + ggp_account_token *token, gpointer user_data); +static void ggp_account_register_dialog_ok( + ggp_account_register_data *register_data, PurpleRequestFields *fields); +static void ggp_account_register_dialog_invalid( + ggp_account_register_data *register_data, const gchar *message); +static void ggp_account_register_dialog_cancel( + ggp_account_register_data *register_data, PurpleRequestFields *fields); +static void ggp_account_register_response(struct gg_http *h, gboolean success, + gboolean cancelled, gpointer _reqdata); +static void ggp_account_register_completed( + ggp_account_register_data *register_data, gboolean success); + +#define GGP_ACCOUNT_REGISTER_TITLE _("Register New Gadu-Gadu Account") /******************************************************************************/ -static void ggp_account_register_completed(ggp_account_register_data *register_data, gboolean success) -{ - PurpleAccount *account = purple_connection_get_account(register_data->gc); - - ggp_account_token_free(register_data->token); - g_free(register_data); - - purple_account_disconnect(account); - purple_account_register_completed(account, TRUE); -} - void ggp_account_register(PurpleAccount *account) { PurpleConnection *gc = purple_account_get_connection(account); + ggp_account_register_data *register_data; purple_debug_info("gg", "ggp_account_register\n"); - ggp_account_token_request(gc, ggp_account_register_dialog, NULL); + register_data = g_new0(ggp_account_register_data, 1); + register_data->gc = gc; + register_data->password_remember = TRUE; + + ggp_account_token_request(gc, ggp_account_register_dialog, + register_data); } -static void ggp_account_register_dialog(PurpleConnection *gc, ggp_account_token *token, gpointer user_data) +static void ggp_account_register_dialog(PurpleConnection *gc, + ggp_account_token *token, gpointer _register_data) { PurpleAccount *account = purple_connection_get_account(gc); PurpleRequestFields *fields; - PurpleRequestFieldGroup *group; + PurpleRequestFieldGroup *main_group, *password_group, *token_group; PurpleRequestField *field; - ggp_account_register_data *register_data; + ggp_account_register_data *register_data = _register_data; purple_debug_info("gg", "ggp_account_register_dialog(%x, %x, %x)\n", - (unsigned int)gc, (unsigned int)token, (unsigned int)user_data); + (unsigned int)gc, (unsigned int)token, + (unsigned int)_register_data); if (!token) { - purple_account_disconnect(account); - purple_account_register_completed(account, FALSE); + ggp_account_register_completed(register_data, FALSE); return; } - // TODO: required fields fields = purple_request_fields_new(); - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); + main_group = purple_request_field_group_new(NULL); + purple_request_fields_add_group(fields, main_group); - field = purple_request_field_string_new("email", _("Email"), "", FALSE); - purple_request_field_group_add_field(group, field); - - field = purple_request_field_string_new("password1", _("Password"), "", - FALSE); + field = purple_request_field_string_new("email", _("Email"), + register_data->email, FALSE); + purple_request_field_set_required(field, TRUE); + purple_request_field_group_add_field(main_group, field); + + password_group = purple_request_field_group_new(_("Password")); + purple_request_fields_add_group(fields, password_group); + + field = purple_request_field_string_new("password1", _("Password"), + register_data->password, FALSE); + purple_request_field_set_required(field, TRUE); purple_request_field_string_set_masked(field, TRUE); - purple_request_field_group_add_field(group, field); + purple_request_field_group_add_field(password_group, field); - field = purple_request_field_string_new("password2", _("Password (again)"), "", - FALSE); + field = purple_request_field_string_new("password2", + _("Password (again)"), register_data->password, FALSE); + purple_request_field_set_required(field, TRUE); purple_request_field_string_set_masked(field, TRUE); - purple_request_field_group_add_field(group, field); + purple_request_field_group_add_field(password_group, field); + + field = purple_request_field_bool_new("password_remember", + _("Remember password"), register_data->password_remember); + purple_request_field_group_add_field(password_group, field); - //TODO: move it into a new group? + token_group = purple_request_field_group_new(_("Captcha")); + purple_request_fields_add_group(fields, token_group); + field = purple_request_field_string_new("token_value", - _("Enter captcha text"), "", FALSE); - purple_request_field_group_add_field(group, field); + _("Enter text from image below"), register_data->token_value, + FALSE); + purple_request_field_set_required(field, TRUE); + purple_request_field_group_add_field(token_group, field); field = purple_request_field_image_new("token_image", _("Captcha"), token->data, token->size); - purple_request_field_group_add_field(group, field); + purple_request_field_group_add_field(token_group, field); - register_data = g_new(ggp_account_register_data, 1); - register_data->gc = gc; register_data->token = token; + register_data->password = NULL; purple_request_fields(gc, - _("Register New Gadu-Gadu Account"), - _("Register New Gadu-Gadu Account"), + GGP_ACCOUNT_REGISTER_TITLE, + GGP_ACCOUNT_REGISTER_TITLE, _("Please, fill in the following fields"), fields, _("OK"), G_CALLBACK(ggp_account_register_dialog_ok), _("Cancel"), G_CALLBACK(ggp_account_register_dialog_cancel), account, NULL, NULL, register_data); } -static void ggp_account_register_dialog_cancel(ggp_account_register_data *register_data, PurpleRequestFields *fields) +static void ggp_account_register_dialog_cancel( + ggp_account_register_data *register_data, PurpleRequestFields *fields) { purple_debug_info("gg", "ggp_account_register_dialog_cancel(%x, %x)\n", (unsigned int)register_data, (unsigned int)fields); @@ -199,60 +230,150 @@ ggp_account_register_completed(register_data, FALSE); } -static void ggp_account_register_dialog_ok(ggp_account_register_data *register_data, PurpleRequestFields *fields) +static void ggp_account_register_dialog_ok( + ggp_account_register_data *register_data, PurpleRequestFields *fields) { - PurpleAccount *account = purple_connection_get_account(register_data->gc); - const gchar *email, *password1, *password2, *token_value; + const gchar *password2; struct gg_http *h; - struct gg_pubdir *register_result; - uin_t uin; - purple_debug_info("gg", "ggp_account_register_dialog_ok(%x, %x)\n", + purple_debug_misc("gg", "ggp_account_register_dialog_ok(%x, %x)\n", (unsigned int)register_data, (unsigned int)fields); - email = purple_request_fields_get_string(fields, "email"); - password1 = purple_request_fields_get_string(fields, "password1"); + g_free(register_data->email); + g_free(register_data->password); + g_free(register_data->token_value); + + register_data->email = g_strdup( + purple_request_fields_get_string(fields, "email")); + register_data->password = g_strdup( + purple_request_fields_get_string(fields, "password1")); password2 = purple_request_fields_get_string(fields, "password2"); - token_value = purple_request_fields_get_string(fields, "token_value"); + register_data->password_remember = + purple_request_fields_get_bool(fields, "password_remember"); + register_data->token_value = g_strdup( + purple_request_fields_get_string(fields, "token_value")); - g_assert(email != NULL); - g_assert(password1 != NULL); + g_assert(register_data->email != NULL); + g_assert(register_data->password != NULL); g_assert(password2 != NULL); - g_assert(token_value != NULL); + g_assert(register_data->token_value != NULL); - if (g_utf8_collate(password1, password2) != 0) + if (g_utf8_collate(register_data->password, password2) != 0) + { + g_free(register_data->password); + register_data->password = NULL; + ggp_account_register_dialog_invalid(register_data, + _("Passwords do not match")); + return; + } + if (!ggp_password_validate(register_data->password)) + { + g_free(register_data->password); + register_data->password = NULL; + ggp_account_register_dialog_invalid(register_data, + _("Password can contain 6-15 alphanumeric characters")); + return; + } + if (!purple_email_is_valid(register_data->email)) + { + ggp_account_register_dialog_invalid(register_data, + _("Invalid email address")); + return; + } + if (strlen(register_data->token_value) != register_data->token->length + || !g_regex_match_simple("^[a-zA-Z0-9]+$", + register_data->token_value, 0, 0)) { - purple_debug_warning("gg", "ggp_account_register_dialog_ok: validation failed - passwords does not match\n"); - purple_notify_error(purple_connection_get_account(register_data->gc), - _("TODO: title"), - _("Passwords do not match"), NULL); + ggp_account_register_dialog_invalid(register_data, + _("Captcha validation failed")); + return; + } + + purple_debug_info("gg", "ggp_account_register_dialog_ok: validation ok " + "[token id=%s, value=%s]\n", + register_data->token->id, register_data->token_value); + h = gg_register3(register_data->email, register_data->password, + register_data->token->id, register_data->token_value, TRUE); + + ggp_libgaduw_http_watch(register_data->gc, h, + ggp_account_register_response, register_data, TRUE); +} + +static void ggp_account_register_dialog_invalid( + ggp_account_register_data *register_data, const gchar *message) +{ + purple_debug_warning("gg", "ggp_account_register_dialog_invalid: %s\n", + message); + ggp_account_register_dialog(register_data->gc, register_data->token, + register_data); + purple_notify_error(purple_connection_get_account(register_data->gc), + GGP_ACCOUNT_REGISTER_TITLE, message, NULL); +} + +static void ggp_account_register_response(struct gg_http *h, gboolean success, + gboolean cancelled, gpointer _register_data) +{ + ggp_account_register_data *register_data = _register_data; + PurpleAccount *account = + purple_connection_get_account(register_data->gc); + struct gg_pubdir *register_result = h->data; + uin_t uin; + gchar *tmp; + + g_assert(!(success && cancelled)); + + if (cancelled) + { + purple_debug_info("gg", "ggp_account_register_response: " + "cancelled\n"); + ggp_account_register_completed(register_data, FALSE); + return; + } + if (!success || !register_result->success) + { + //TODO (libgadu 1.12.x): check register_result->error + purple_debug_error("gg", "ggp_account_register_response: " + "error\n"); + purple_notify_error(NULL, + GGP_ACCOUNT_REGISTER_TITLE, + _("Unable to register new account. " + "An unknown error occurred."), NULL); ggp_account_register_completed(register_data, FALSE); return; } - purple_debug_info("gg", "ggp_account_register_dialog_ok: validation ok [token id=%s, value=%s]\n", - register_data->token->id, token_value); - h = gg_register3(email, password1, register_data->token->id, token_value, 0); // TODO: async (use code from ggp_account_token_handler) - if (h == NULL || !(register_result = h->data) || !register_result->success) - { - purple_debug_warning("gg", "ggp_account_register_dialog_ok: registration failed\n"); - purple_notify_error(purple_connection_get_account(register_data->gc), - _("TODO: title"), - _("Unable to register new account. An unknown error occurred."), NULL); - ggp_account_register_completed(register_data, FALSE); - return; - } uin = register_result->uin; - - purple_debug_info("gg", "ggp_account_register_dialog_ok: registered uin %u\n", uin); - gg_register_free(h); + purple_debug_info("gg", "ggp_account_register_dialog_ok: " + "registered uin %u\n", uin); purple_account_set_username(account, ggp_uin_to_str(uin)); - purple_account_set_remember_password(account, TRUE); //TODO: option - purple_account_set_password(account, password1); + purple_account_set_remember_password(account, + register_data->password_remember); + purple_account_set_password(account, register_data->password); - purple_notify_info(NULL, _("New Gadu-Gadu Account Registered"), - _("Registration completed successfully!"), NULL); //TODO: show new UIN + tmp = g_strdup_printf(_("Your new GG number: %u."), uin); + purple_notify_info(NULL, GGP_ACCOUNT_REGISTER_TITLE, + _("Registration completed successfully!"), tmp); + g_free(tmp); ggp_account_register_completed(register_data, TRUE); } + +static void ggp_account_register_completed( + ggp_account_register_data *register_data, gboolean success) +{ + PurpleAccount *account = + purple_connection_get_account(register_data->gc); + + purple_debug_misc("gg", "ggp_account_register_completed: %d\n", + success); + + g_free(register_data->email); + g_free(register_data->password); + g_free(register_data->token_value); + ggp_account_token_free(register_data->token); + g_free(register_data); + + purple_account_disconnect(account); + purple_account_register_completed(account, success); +}
--- a/libpurple/protocols/gg/account.h Sat Jun 30 19:56:46 2012 +0200 +++ b/libpurple/protocols/gg/account.h Mon Jul 02 00:58:03 2012 +0200 @@ -8,14 +8,17 @@ gchar *id; gpointer data; size_t size; + int length; } ggp_account_token; /** * token must be free'd with ggp_account_token_free */ -typedef void (*ggp_account_token_cb)(PurpleConnection *gc, ggp_account_token *token, gpointer user_data); +typedef void (*ggp_account_token_cb)(PurpleConnection *gc, + ggp_account_token *token, gpointer user_data); -void ggp_account_token_request(PurpleConnection *gc, ggp_account_token_cb callback, void *user_data); +void ggp_account_token_request(PurpleConnection *gc, + ggp_account_token_cb callback, void *user_data); void ggp_account_token_free(ggp_account_token *token);
--- a/libpurple/protocols/gg/libgaduw.c Sat Jun 30 19:56:46 2012 +0200 +++ b/libpurple/protocols/gg/libgaduw.c Mon Jul 02 00:58:03 2012 +0200 @@ -24,8 +24,8 @@ gpointer user_data, gboolean show_processing) { ggp_libgaduw_http_req *req; - purple_debug_misc("gg", "ggp_libgaduw_http_watch(h=%x, show_processing=%d)\n", - (unsigned int)h, show_processing); + purple_debug_misc("gg", "ggp_libgaduw_http_watch(h=%x, " + "show_processing=%d)\n", (unsigned int)h, show_processing); req = g_new(ggp_libgaduw_http_req, 1); req->user_data = user_data; @@ -55,7 +55,7 @@ { ggp_libgaduw_http_req *req = _req; - if (gg_token_watch_fd(req->h) == -1 || req->h->state == GG_STATE_ERROR) + if (req->h->callback(req->h) == -1 || req->h->state == GG_STATE_ERROR) { purple_debug_error("gg", "ggp_libgaduw_http_handler: failed to " "make http request: %d\n", req->h->error); @@ -107,5 +107,6 @@ } purple_input_remove(req->inpa); req->cb(req->h, success, req->cancelled, req->user_data); + req->h->destroy(req->h); g_free(req); }
--- a/libpurple/protocols/gg/libgaduw.h Sat Jun 30 19:56:46 2012 +0200 +++ b/libpurple/protocols/gg/libgaduw.h Mon Jul 02 00:58:03 2012 +0200 @@ -21,7 +21,8 @@ } ggp_libgaduw_http_req; ggp_libgaduw_http_req * ggp_libgaduw_http_watch(PurpleConnection *gc, - struct gg_http *h, ggp_libgaduw_http_cb cb, gpointer user_data, gboolean show_processing); + struct gg_http *h, ggp_libgaduw_http_cb cb, gpointer user_data, + gboolean show_processing); void ggp_libgaduw_http_cancel(ggp_libgaduw_http_req *req);
--- a/libpurple/protocols/gg/purplew.c Sat Jun 30 19:56:46 2012 +0200 +++ b/libpurple/protocols/gg/purplew.c Mon Jul 02 00:58:03 2012 +0200 @@ -1,6 +1,7 @@ #include "purplew.h" #include <request.h> +#include <debug.h> guint ggp_purplew_http_input_add(struct gg_http *http_req, PurpleInputFunction func, gpointer user_data) @@ -13,6 +14,10 @@ if (check & GG_CHECK_WRITE) cond |= PURPLE_INPUT_WRITE; + //TODO: verbose mode + //purple_debug_misc("gg", "ggp_purplew_http_input_add: " + // "[req=%x, fd=%d, cond=%d]\n", + // (unsigned int)http_req, http_req->fd, cond); return purple_input_add(http_req->fd, cond, func, user_data); }
--- a/libpurple/protocols/gg/utils.c Sat Jun 30 19:56:46 2012 +0200 +++ b/libpurple/protocols/gg/utils.c Mon Jul 02 00:58:03 2012 +0200 @@ -85,3 +85,12 @@ { return ggp_convert(src, "CP1250", "UTF-8"); } + +gboolean ggp_password_validate(const gchar *password) +{ + const int len = strlen(password); + if (len < 6 || len > 15) + return FALSE; + return g_regex_match_simple("^[ a-zA-Z0-9~`!@#$%^&*()_+=[\\]{};':\",./?" + "<>\\\\|-]+$", password, 0, 0); +}