mark PurpleImageClass as private
[pidgin-git.git] / libpurple / protocols / gg / account.c
blob0fdeada032a5e50934ca4b3dc3701f14b4234eaa
1 /* purple
3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * Rewritten from scratch during Google Summer of Code 2012
8 * by Tomek Wasilczyk (http://www.wasilczyk.pl).
10 * Previously implemented by:
11 * - Arkadiusz Miskiewicz <misiek@pld.org.pl> - first implementation (2001);
12 * - Bartosz Oler <bartosz@bzimage.us> - reimplemented during GSoC 2005;
13 * - Krzysztof Klinikowski <grommasher@gmail.com> - some parts (2009-2011).
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
30 #include "account.h"
32 #include <libgadu.h>
33 #include <debug.h>
35 #include "purplew.h"
36 #include "utils.h"
37 #include "libgaduw.h"
38 #include "validator.h"
40 /*******************************************************************************
41 * Token requesting.
42 ******************************************************************************/
44 typedef struct
46 ggp_account_token_cb callback;
47 PurpleConnection *gc;
48 void *user_data;
49 } ggp_account_token_reqdata;
51 static void ggp_account_token_response(struct gg_http *h, gboolean success,
52 gboolean cancelled, gpointer _reqdata);
54 /******************************************************************************/
56 void ggp_account_token_free(ggp_account_token *token)
58 if (!token)
59 return;
60 g_free(token->id);
61 g_free(token->data);
62 g_free(token);
65 void ggp_account_token_request(PurpleConnection *gc,
66 ggp_account_token_cb callback, void *user_data)
68 struct gg_http *h;
69 ggp_account_token_reqdata *reqdata;
71 purple_debug_info("gg", "ggp_account_token_request: "
72 "requesting token...\n");
74 h = gg_token(TRUE);
76 if (!h) {
77 callback(gc, NULL, user_data);
78 return;
81 reqdata = g_new(ggp_account_token_reqdata, 1);
82 reqdata->callback = callback;
83 reqdata->gc = gc;
84 reqdata->user_data = user_data;
85 ggp_libgaduw_http_watch(gc, h, ggp_account_token_response, reqdata,
86 TRUE);
89 static void ggp_account_token_response(struct gg_http *h, gboolean success,
90 gboolean cancelled, gpointer _reqdata)
92 ggp_account_token_reqdata *reqdata = _reqdata;
93 struct gg_token *token_info;
94 ggp_account_token *token = NULL;
96 g_assert(!(success && cancelled));
98 if (cancelled)
99 purple_debug_info("gg", "ggp_account_token_handler: "
100 "cancelled\n");
101 else if (success) {
102 purple_debug_info("gg", "ggp_account_token_handler: "
103 "got token\n");
105 token = g_new(ggp_account_token, 1);
107 token_info = h->data;
108 token->id = g_strdup(token_info->tokenid);
109 token->size = h->body_size;
110 token->data = g_memdup(h->body, token->size);
111 token->length = token_info->length;
112 } else {
113 purple_debug_error("gg", "ggp_account_token_handler: error\n");
114 purple_notify_error(
115 purple_connection_get_account(reqdata->gc),
116 _("Token Error"),
117 _("Unable to fetch the token."), NULL,
118 purple_request_cpar_from_connection(reqdata->gc));
121 reqdata->callback(reqdata->gc, token, reqdata->user_data);
122 g_free(reqdata);
125 gboolean ggp_account_token_validate(ggp_account_token *token,
126 const gchar *value)
128 if (strlen(value) != token->length)
129 return FALSE;
130 return g_regex_match_simple("^[a-zA-Z0-9]+$", value, 0, 0);
133 /*******************************************************************************
134 * New account registration.
135 ******************************************************************************/
137 typedef struct
139 ggp_account_token *token;
140 PurpleConnection *gc;
142 gchar *email;
143 gchar *password;
144 gchar *token_value;
145 gboolean password_remember;
146 } ggp_account_register_data;
148 static void ggp_account_register_dialog(PurpleConnection *gc,
149 ggp_account_token *token, gpointer _register_data);
150 static void ggp_account_register_dialog_ok(
151 ggp_account_register_data *register_data, PurpleRequestFields *fields);
152 static void ggp_account_register_dialog_cancel(
153 ggp_account_register_data *register_data, PurpleRequestFields *fields);
154 static void ggp_account_register_response(struct gg_http *h, gboolean success,
155 gboolean cancelled, gpointer _reqdata);
156 static void ggp_account_register_completed(
157 ggp_account_register_data *register_data, gboolean success);
159 #define GGP_ACCOUNT_REGISTER_TITLE _("Register New Gadu-Gadu Account")
161 /******************************************************************************/
163 void ggp_account_register(PurpleAccount *account)
165 PurpleConnection *gc = purple_account_get_connection(account);
166 ggp_account_register_data *register_data;
168 purple_debug_info("gg", "ggp_account_register\n");
170 register_data = g_new0(ggp_account_register_data, 1);
171 register_data->gc = gc;
172 register_data->password_remember = TRUE;
174 ggp_account_token_request(gc, ggp_account_register_dialog,
175 register_data);
178 static void ggp_account_register_dialog(PurpleConnection *gc,
179 ggp_account_token *token, gpointer _register_data)
181 PurpleRequestFields *fields;
182 PurpleRequestFieldGroup *main_group, *password_group, *token_group;
183 PurpleRequestField *field, *field_password;
184 ggp_account_register_data *register_data = _register_data;
186 purple_debug_info("gg", "ggp_account_register_dialog(%p, %p, %p)\n",
187 gc, token, _register_data);
188 if (!token) {
189 ggp_account_register_completed(register_data, FALSE);
190 return;
193 fields = purple_request_fields_new();
194 main_group = purple_request_field_group_new(NULL);
195 purple_request_fields_add_group(fields, main_group);
197 field = purple_request_field_string_new("email", _("Email"),
198 register_data->email, FALSE);
199 purple_request_field_set_required(field, TRUE);
200 purple_request_field_set_validator(field,
201 purple_request_field_email_validator, NULL);
202 purple_request_field_group_add_field(main_group, field);
204 password_group = purple_request_field_group_new(_("Password"));
205 purple_request_fields_add_group(fields, password_group);
207 field = purple_request_field_string_new("password1", _("Password"),
208 register_data->password, FALSE);
209 purple_request_field_set_required(field, TRUE);
210 purple_request_field_string_set_masked(field, TRUE);
211 purple_request_field_set_validator(field, ggp_validator_password, NULL);
212 purple_request_field_group_add_field(password_group, field);
213 field_password = field;
215 field = purple_request_field_string_new("password2",
216 _("Password (again)"), register_data->password, FALSE);
217 purple_request_field_set_required(field, TRUE);
218 purple_request_field_string_set_masked(field, TRUE);
219 purple_request_field_set_validator(field, ggp_validator_password_equal,
220 field_password);
221 purple_request_field_group_add_field(password_group, field);
223 field = purple_request_field_bool_new("password_remember",
224 _("Remember password"), register_data->password_remember);
225 purple_request_field_group_add_field(password_group, field);
227 token_group = purple_request_field_group_new(_("CAPTCHA"));
228 purple_request_fields_add_group(fields, token_group);
230 field = purple_request_field_string_new("token_value",
231 _("Enter text from image below"), register_data->token_value,
232 FALSE);
233 purple_request_field_set_required(field, TRUE);
234 purple_request_field_set_validator(field, ggp_validator_token, token);
235 purple_request_field_group_add_field(token_group, field);
236 purple_debug_info("gg", "token set %p\n", register_data->token);
238 field = purple_request_field_image_new("token_image", _("CAPTCHA"),
239 token->data, token->size);
240 purple_request_field_group_add_field(token_group, field);
242 register_data->token = token;
244 purple_request_fields(gc,
245 GGP_ACCOUNT_REGISTER_TITLE,
246 GGP_ACCOUNT_REGISTER_TITLE,
247 _("Please, fill in the following fields"), fields,
248 _("OK"), G_CALLBACK(ggp_account_register_dialog_ok),
249 _("Cancel"), G_CALLBACK(ggp_account_register_dialog_cancel),
250 purple_request_cpar_from_connection(gc), register_data);
253 static void ggp_account_register_dialog_cancel(
254 ggp_account_register_data *register_data, PurpleRequestFields *fields)
256 purple_debug_info("gg", "ggp_account_register_dialog_cancel(%p, %p)\n",
257 register_data, fields);
259 ggp_account_register_completed(register_data, FALSE);
262 static void ggp_account_register_dialog_ok(
263 ggp_account_register_data *register_data, PurpleRequestFields *fields)
265 struct gg_http *h;
267 purple_debug_misc("gg", "ggp_account_register_dialog_ok(%p, %p)\n",
268 register_data, fields);
270 g_free(register_data->email);
271 g_free(register_data->password);
272 g_free(register_data->token_value);
274 register_data->email = g_strdup(
275 purple_request_fields_get_string(fields, "email"));
276 register_data->password = g_strdup(
277 purple_request_fields_get_string(fields, "password1"));
278 register_data->password_remember =
279 purple_request_fields_get_bool(fields, "password_remember");
280 register_data->token_value = g_strdup(
281 purple_request_fields_get_string(fields, "token_value"));
283 g_assert(register_data->email != NULL);
284 g_assert(register_data->password != NULL);
285 g_assert(register_data->token_value != NULL);
287 h = gg_register3(register_data->email, register_data->password,
288 register_data->token->id, register_data->token_value, TRUE);
290 ggp_libgaduw_http_watch(register_data->gc, h,
291 ggp_account_register_response, register_data, TRUE);
294 static void ggp_account_register_response(struct gg_http *h, gboolean success,
295 gboolean cancelled, gpointer _register_data)
297 ggp_account_register_data *register_data = _register_data;
298 PurpleAccount *account =
299 purple_connection_get_account(register_data->gc);
300 struct gg_pubdir *register_result = h->data;
301 uin_t uin;
302 gchar *tmp;
304 g_assert(!(success && cancelled));
306 if (cancelled) {
307 purple_debug_info("gg", "ggp_account_register_response: "
308 "cancelled\n");
309 ggp_account_register_completed(register_data, FALSE);
310 return;
312 if (!success || !register_result->success) {
313 /* TODO (libgadu 1.12.x): check register_result->error */
314 purple_debug_error("gg", "ggp_account_register_response: "
315 "error\n");
316 purple_notify_error(NULL,
317 GGP_ACCOUNT_REGISTER_TITLE,
318 _("Unable to register new account. "
319 "An unknown error occurred."), NULL,
320 purple_request_cpar_from_account(account));
321 ggp_account_register_completed(register_data, FALSE);
322 return;
325 uin = register_result->uin;
326 purple_debug_info("gg", "ggp_account_register_response: "
327 "registered uin %u\n", uin);
329 purple_account_set_username(account, ggp_uin_to_str(uin));
330 purple_account_set_remember_password(account,
331 register_data->password_remember);
332 purple_account_set_password(account, register_data->password,
333 NULL, NULL);
335 tmp = g_strdup_printf(_("Your new GG number: %u."), uin);
336 purple_notify_info(account, GGP_ACCOUNT_REGISTER_TITLE,
337 _("Registration completed successfully!"), tmp,
338 purple_request_cpar_from_account(account));
339 g_free(tmp);
341 ggp_account_register_completed(register_data, TRUE);
344 static void ggp_account_register_completed(
345 ggp_account_register_data *register_data, gboolean success)
347 PurpleAccount *account =
348 purple_connection_get_account(register_data->gc);
350 purple_debug_misc("gg", "ggp_account_register_completed: %d\n",
351 success);
353 g_free(register_data->email);
354 g_free(register_data->password);
355 g_free(register_data->token_value);
356 ggp_account_token_free(register_data->token);
357 g_free(register_data);
359 purple_account_disconnect(account);
360 purple_account_register_completed(account, success);
363 /*******************************************************************************
364 * Password change.
365 ******************************************************************************/
367 typedef struct
369 ggp_account_token *token;
370 PurpleConnection *gc;
372 gchar *email;
373 gchar *password_current;
374 gchar *password_new;
375 gchar *token_value;
376 } ggp_account_chpass_data;
378 static void ggp_account_chpass_data_free(ggp_account_chpass_data *chpass_data);
379 static void ggp_account_chpass_dialog(PurpleConnection *gc,
380 ggp_account_token *token, gpointer _chpass_data);
381 static void ggp_account_chpass_dialog_ok(
382 ggp_account_chpass_data *chpass_data, PurpleRequestFields *fields);
383 static void ggp_account_chpass_dialog_invalid(
384 ggp_account_chpass_data *chpass_data, const gchar *message);
385 static void ggp_account_chpass_dialog_cancel(
386 ggp_account_chpass_data *chpass_data, PurpleRequestFields *fields);
387 static void ggp_account_chpass_response(struct gg_http *h, gboolean success,
388 gboolean cancelled, gpointer _chpass_data);
390 #define GGP_ACCOUNT_CHPASS_TITLE _("Password change")
392 /******************************************************************************/
394 static void ggp_account_chpass_data_free(ggp_account_chpass_data *chpass_data)
396 g_free(chpass_data->email);
397 g_free(chpass_data->password_current);
398 g_free(chpass_data->password_new);
399 g_free(chpass_data->token_value);
400 ggp_account_token_free(chpass_data->token);
401 g_free(chpass_data);
404 void ggp_account_chpass(PurpleConnection *gc)
406 ggp_account_chpass_data *chpass_data;
408 purple_debug_info("gg", "ggp_account_chpass\n");
410 chpass_data = g_new0(ggp_account_chpass_data, 1);
411 chpass_data->gc = gc;
413 ggp_account_token_request(gc, ggp_account_chpass_dialog, chpass_data);
416 static void ggp_account_chpass_dialog(PurpleConnection *gc,
417 ggp_account_token *token, gpointer _chpass_data)
419 ggp_account_chpass_data *chpass_data = _chpass_data;
420 PurpleAccount *account = purple_connection_get_account(chpass_data->gc);
421 PurpleRequestFields *fields;
422 PurpleRequestFieldGroup *main_group, *password_group, *token_group;
423 PurpleRequestField *field, *field_password;
424 gchar *primary;
426 purple_debug_info("gg", "ggp_account_chpass_dialog(%p, %p, %p)\n",
427 gc, token, _chpass_data);
428 if (!token) {
429 ggp_account_chpass_data_free(chpass_data);
430 return;
433 fields = purple_request_fields_new();
434 main_group = purple_request_field_group_new(NULL);
435 purple_request_fields_add_group(fields, main_group);
437 field = purple_request_field_string_new("email",
438 _("New email address"), chpass_data->email, FALSE);
439 purple_request_field_set_required(field, TRUE);
440 purple_request_field_set_validator(field,
441 purple_request_field_email_validator, NULL);
442 purple_request_field_group_add_field(main_group, field);
444 password_group = purple_request_field_group_new(_("Password"));
445 purple_request_fields_add_group(fields, password_group);
447 field = purple_request_field_string_new("password_current",
448 _("Current password"), chpass_data->password_current, FALSE);
449 purple_request_field_set_required(field, TRUE);
450 purple_request_field_string_set_masked(field, TRUE);
451 purple_request_field_group_add_field(password_group, field);
453 field = purple_request_field_string_new("password_new1",
454 _("Password"), chpass_data->password_new, FALSE);
455 purple_request_field_set_required(field, TRUE);
456 purple_request_field_string_set_masked(field, TRUE);
457 purple_request_field_set_validator(field, ggp_validator_password, NULL);
458 purple_request_field_group_add_field(password_group, field);
459 field_password = field;
461 field = purple_request_field_string_new("password_new2",
462 _("Password (retype)"), chpass_data->password_new, FALSE);
463 purple_request_field_set_required(field, TRUE);
464 purple_request_field_string_set_masked(field, TRUE);
465 purple_request_field_set_validator(field, ggp_validator_password_equal,
466 field_password);
467 purple_request_field_group_add_field(password_group, field);
469 token_group = purple_request_field_group_new(_("CAPTCHA"));
470 purple_request_fields_add_group(fields, token_group);
472 field = purple_request_field_string_new("token_value",
473 _("Enter text from image below"), chpass_data->token_value,
474 FALSE);
475 purple_request_field_set_required(field, TRUE);
476 purple_request_field_set_validator(field, ggp_validator_token, token);
477 purple_request_field_group_add_field(token_group, field);
479 field = purple_request_field_image_new("token_image", _("CAPTCHA"),
480 token->data, token->size);
481 purple_request_field_group_add_field(token_group, field);
483 chpass_data->token = token;
485 primary = g_strdup_printf(_("Change password for %s"),
486 purple_account_get_username(account));
488 purple_request_fields(gc, GGP_ACCOUNT_CHPASS_TITLE, primary,
489 _("Please enter your current password and your new password."),
490 fields,
491 _("OK"), G_CALLBACK(ggp_account_chpass_dialog_ok),
492 _("Cancel"), G_CALLBACK(ggp_account_chpass_dialog_cancel),
493 purple_request_cpar_from_connection(gc), chpass_data);
495 g_free(primary);
498 static void ggp_account_chpass_dialog_ok(
499 ggp_account_chpass_data *chpass_data, PurpleRequestFields *fields)
501 PurpleAccount *account = purple_connection_get_account(chpass_data->gc);
502 struct gg_http *h;
503 uin_t uin;
505 purple_debug_misc("gg", "ggp_account_chpass_dialog_ok(%p, %p)\n",
506 chpass_data, fields);
508 g_free(chpass_data->email);
509 g_free(chpass_data->password_current);
510 g_free(chpass_data->password_new);
511 g_free(chpass_data->token_value);
513 chpass_data->email = g_strdup(
514 purple_request_fields_get_string(fields, "email"));
515 chpass_data->password_current = g_strdup(
516 purple_request_fields_get_string(fields, "password_current"));
517 chpass_data->password_new = g_strdup(
518 purple_request_fields_get_string(fields, "password_new1"));
519 chpass_data->token_value = g_strdup(
520 purple_request_fields_get_string(fields, "token_value"));
522 g_assert(chpass_data->email != NULL);
523 g_assert(chpass_data->password_current != NULL);
524 g_assert(chpass_data->password_new != NULL);
525 g_assert(chpass_data->token_value != NULL);
527 if (g_utf8_collate(chpass_data->password_current,
528 purple_connection_get_password(chpass_data->gc)) != 0)
530 g_free(chpass_data->password_current);
531 chpass_data->password_current = NULL;
532 ggp_account_chpass_dialog_invalid(chpass_data,
533 _("Your current password is different from the one that"
534 " you specified."));
535 return;
537 if (g_utf8_collate(chpass_data->password_current,
538 chpass_data->password_new) == 0)
540 g_free(chpass_data->password_new);
541 chpass_data->password_new = NULL;
542 ggp_account_chpass_dialog_invalid(chpass_data,
543 _("New password have to be different from the current "
544 "one."));
545 return;
548 uin = ggp_str_to_uin(purple_account_get_username(account));
549 purple_debug_info("gg", "ggp_account_chpass_dialog_ok: validation ok "
550 "[token id=%s, value=%s]\n",
551 chpass_data->token->id, chpass_data->token_value);
552 h = gg_change_passwd4(uin, chpass_data->email,
553 chpass_data->password_current, chpass_data->password_new,
554 chpass_data->token->id, chpass_data->token_value, TRUE);
556 ggp_libgaduw_http_watch(chpass_data->gc, h,
557 ggp_account_chpass_response, chpass_data, TRUE);
560 static void ggp_account_chpass_dialog_invalid(
561 ggp_account_chpass_data *chpass_data, const gchar *message)
563 purple_debug_warning("gg", "ggp_account_chpass_dialog_invalid: %s\n",
564 message);
565 ggp_account_chpass_dialog(chpass_data->gc, chpass_data->token,
566 chpass_data);
567 purple_notify_error(purple_connection_get_account(chpass_data->gc),
568 GGP_ACCOUNT_CHPASS_TITLE, message, NULL,
569 purple_request_cpar_from_connection(chpass_data->gc));
572 static void ggp_account_chpass_dialog_cancel(
573 ggp_account_chpass_data *chpass_data, PurpleRequestFields *fields)
575 ggp_account_chpass_data_free(chpass_data);
578 static void ggp_account_chpass_response(struct gg_http *h, gboolean success,
579 gboolean cancelled, gpointer _chpass_data)
581 ggp_account_chpass_data *chpass_data = _chpass_data;
582 PurpleAccount *account =
583 purple_connection_get_account(chpass_data->gc);
584 struct gg_pubdir *chpass_result = h->data;
586 g_assert(!(success && cancelled));
588 if (cancelled) {
589 purple_debug_info("gg", "ggp_account_chpass_response: "
590 "cancelled\n");
591 ggp_account_chpass_data_free(chpass_data);
592 return;
594 if (!success || !chpass_result->success) {
595 /* TODO (libgadu 1.12.x): check chpass_result->error */
596 purple_debug_error("gg", "ggp_account_chpass_response: "
597 "error\n");
598 purple_notify_error(NULL,
599 GGP_ACCOUNT_CHPASS_TITLE,
600 _("Unable to change password. "
601 "An unknown error occurred."), NULL,
602 purple_request_cpar_from_connection(chpass_data->gc));
603 ggp_account_chpass_data_free(chpass_data);
604 return;
607 purple_debug_info("gg", "ggp_account_chpass_response: "
608 "password changed\n");
610 purple_account_set_password(account, chpass_data->password_new,
611 NULL, NULL);
613 purple_notify_info(account, GGP_ACCOUNT_CHPASS_TITLE,
614 _("Your password has been changed."), NULL,
615 purple_request_cpar_from_connection(chpass_data->gc));
617 ggp_account_chpass_data_free(chpass_data);
619 /* TODO: reconnect / check how it is done in original client */
620 purple_account_disconnect(account);