diff --git a/telegram-base.c b/telegram-base.c index 3770e22..808554a 100644 --- a/telegram-base.c +++ b/telegram-base.c @@ -247,13 +247,11 @@ void read_dc (struct tgl_state *TLS, int auth_file_fd, int id, unsigned ver) { bl_do_dc_signed (TLS, id); } -int error_if_val_false (struct tgl_state *TLS, int val, const char *cause, const char *msg) { - if (!val) { +int tgp_error_if_false (struct tgl_state *TLS, int val, const char *cause, const char *msg) { + if (! val) { connection_data *conn = TLS->ev_base; purple_connection_error_reason (conn->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, msg); - - purple_notify_message (_telegram_protocol, PURPLE_NOTIFY_MSG_ERROR, - cause, msg, NULL, NULL, NULL); + purple_notify_message (_telegram_protocol, PURPLE_NOTIFY_MSG_ERROR, cause, msg, NULL, NULL, NULL); return TRUE; } return 0; @@ -319,7 +317,6 @@ void read_auth_file (struct tgl_state *TLS) { close (auth_file_fd); } - void write_secret_chat (tgl_peer_t *_P, void *extra) { struct tgl_secret_chat *P = (void *)_P; if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) { return; } @@ -472,33 +469,6 @@ gchar *get_download_dir (struct tgl_state *TLS) { return dir; } -gboolean assert_file_exists (PurpleConnection *gc, const char *filepath, const char *format) { - if (!g_file_test (filepath, G_FILE_TEST_EXISTS)) { - gchar *msg = g_strdup_printf (format, filepath); - purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR, msg); - g_free (msg); - return 0; - } - return 1; -} - -void export_auth_callback (struct tgl_state *TLS, void *extra, int success) { - if (!error_if_val_false (TLS, success, _("Login canceled"), _("Authentication export to remote data centers failed, login not possible."))) { - telegram_export_authorization (TLS); - } -} - -void telegram_export_authorization (struct tgl_state *TLS) { - int i; - for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i])) { - debug ("tgl_do_export_auth(%d)", i); - tgl_do_export_auth (TLS, i, export_auth_callback, (void*)(long)TLS->DC_list[i]); - return; - } - write_auth_file (TLS); - on_ready (TLS); -} - void write_secret_chat_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_secret_chat *_) { if (!success) { tgp_notify_on_error_gw (TLS, NULL, success); @@ -535,70 +505,6 @@ void tgp_create_group_chat_by_usernames (struct tgl_state *TLS, const char *titl } } - -static void sign_in_callback (struct tgl_state *TLS, void *extra, int success, int registered, const char *mhash) { - connection_data *conn = TLS->ev_base; - if (! error_if_val_false (TLS, success, _("Invalid phone number"), - _("Please enter only numbers in the international phone number format, " - "a leading + following by the country prefix and the phone number.\n" - "Do not use any other special chars."))) { - conn->hash = strdup (mhash); - if (registered) { - request_code (TLS, telegram_export_authorization); - } else { - request_name_and_code (TLS); - } - } -} - -static void telegram_send_sms (struct tgl_state *TLS) { - if (tgl_signed_dc (TLS, TLS->DC_working)) { - telegram_export_authorization (TLS); - return; - } - connection_data *conn = TLS->ev_base; - char const *username = purple_account_get_username(conn->pa); - tgl_do_send_code (TLS, username, (int) strlen(username), sign_in_callback, NULL); -} - -static int all_authorized (struct tgl_state *TLS) { - int i; - for (i = 0; i <= TLS->max_dc_num; i++) { - if (TLS->DC_list[i]) { - tgl_dc_authorize (TLS, TLS->DC_list[i]); - if (!tgl_signed_dc (TLS, TLS->DC_list[i]) && !tgl_authorized_dc (TLS, TLS->DC_list[i])) { - return 0; - } - } - } - return 1; -} - -static int check_all_authorized (gpointer arg) { - struct tgl_state *TLS = arg; - - if (all_authorized (TLS)) { - ((connection_data *)TLS->ev_base)->login_timer = 0; - telegram_send_sms (TLS); - return FALSE; - } else { - return TRUE; - } -} - -void telegram_login (struct tgl_state *TLS) { - connection_data *conn = TLS->ev_base; - - read_auth_file (TLS); - read_state_file (TLS); - read_secret_chat_file (TLS); - if (all_authorized (TLS)) { - telegram_send_sms (TLS); - return; - } - conn->login_timer = purple_timeout_add (100, check_all_authorized, TLS); -} - /** * This function generates a png image to visualize the sha1 key from an encrypted chat. */ diff --git a/telegram-base.h b/telegram-base.h index d061b52..2b2f6e9 100644 --- a/telegram-base.h +++ b/telegram-base.h @@ -39,18 +39,14 @@ void read_secret_chat_file (struct tgl_state *TLS); void write_secret_chat_file (struct tgl_state *TLS); void write_secret_chat_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_secret_chat *E); -void telegram_login (struct tgl_state *TLS); -void telegram_export_authorization (struct tgl_state *TLS); - gchar *get_config_dir (char const *username); gchar *get_user_pk_path (); gchar *get_download_dir (struct tgl_state *TLS); -gboolean assert_file_exists (PurpleConnection *gc, const char *filepath, const char *format); - int tgp_visualize_key (struct tgl_state *TLS, unsigned char* sha1_key); void tgp_create_group_chat_by_usernames (struct tgl_state *TLS, const char *title, const char *users[], int num_users, int print_names); void tgp_notify_on_error_gw (struct tgl_state *TLS, void *extra, int success); +int tgp_error_if_false (struct tgl_state *TLS, int val, const char *cause, const char *msg); #endif diff --git a/telegram-purple.c b/telegram-purple.c index e97fe9b..7afd00a 100644 --- a/telegram-purple.c +++ b/telegram-purple.c @@ -65,9 +65,8 @@ #include "tgp-msg.h" #include "tgp-request.h" #include "tgp-blist.h" +#include "tgp-structs.h" -static void get_password (struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, - void (*callback)(struct tgl_state *TLS, const char *string[], void *arg), void *arg); static void update_message_handler (struct tgl_state *TLS, struct tgl_message *M); static void update_user_handler (struct tgl_state *TLS, struct tgl_user *U, unsigned flags); static void update_user_status_handler (struct tgl_state *TLS, struct tgl_user *U); @@ -75,6 +74,7 @@ static void update_chat_handler (struct tgl_state *TLS, struct tgl_chat *C, unsi static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret_chat *C, unsigned flags); static void update_user_typing (struct tgl_state *TLS, struct tgl_user *U, enum tgl_typing_status status); static void update_marked_read (struct tgl_state *TLS, int num, struct tgl_message *list[]); +static void update_on_ready (struct tgl_state *TLS); static char *format_print_name (struct tgl_state *TLS, tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4); static void on_user_get_info (struct tgl_state *TLS, void *info_data, int success, struct tgl_user *U); @@ -84,7 +84,8 @@ const char *pk_path = "/etc/telegram-purple/server.tglpub"; struct tgl_update_callback tgp_callback = { .logprintf = debug, - .get_values = get_password, + .get_values = request_value, + .started = update_on_ready, .new_msg = update_message_handler, .msg_receive = update_message_handler, .user_update = update_user_handler, @@ -286,21 +287,6 @@ static char *format_print_name (struct tgl_state *TLS, tgl_peer_id_t id, const c return tgl_strdup (s); } -static void get_password (struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, - void (*callback)(struct tgl_state *TLS, const char *string[], void *arg), void *arg) { - if (type == tgl_cur_password) { - connection_data *conn = TLS->ev_base; - const char *P = purple_account_get_string (conn->pa, TGP_KEY_PASSWORD_TWO_FACTOR, NULL); - - if (str_not_empty (P)) { - if (conn->password_retries++ < 1) { - callback (TLS, &P, arg); - return; - } - } - request_password (TLS, callback, arg); - } -} /* static void on_contact_added (struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_user *users[]) { @@ -405,20 +391,6 @@ void on_user_get_info (struct tgl_state *TLS, void *info_data, int success, stru } } -void on_ready (struct tgl_state *TLS) { - debug ("on_ready()."); - connection_data *conn = TLS->ev_base; - - purple_connection_set_state (conn->gc, PURPLE_CONNECTED); - purple_connection_set_display_name (conn->gc, purple_account_get_username (conn->pa)); - purple_blist_add_account (conn->pa); - - debug ("seq = %d, pts = %d, date = %d", TLS->seq, TLS->pts, TLS->date); - tgl_do_get_difference (TLS, purple_account_get_bool (conn->pa, "history-sync-all", FALSE), tgp_notify_on_error_gw, NULL); - tgl_do_get_dialog_list (TLS, 200, 0, on_get_dialog_list_done, NULL); - tgl_do_update_contact_list (TLS, 0, 0); -} - static const char *tgprpl_list_icon (PurpleAccount *acct, PurpleBuddy *buddy) { return "telegram"; } @@ -474,6 +446,8 @@ static void create_secret_chat_done (struct tgl_state *TLS, void *callback_extra return; } write_secret_chat_file (TLS); + + // show the created secret chat to the user } static void start_secret_chat (PurpleBlistNode *node, gpointer data) { @@ -516,12 +490,6 @@ void export_chat_link_checked (struct tgl_state *TLS, const char *name) { tgl_do_export_chat_link (TLS, C->id, create_chat_link_done, C); } -void leave_and_delete_chat_gw (PurpleBlistNode *node, gpointer data) { - PurpleChat *PC = (PurpleChat*)node; - tgl_peer_t *P = tgl_peer_get (pbn_get_conn (node)->TLS, p2tgl_chat_get_id (PC)); - leave_and_delete_chat (pbn_get_conn (node)->TLS, P); -} - void leave_and_delete_chat (struct tgl_state *TLS, tgl_peer_t *P) { g_return_if_fail (P); if (P && P->chat.users_num) { @@ -579,6 +547,22 @@ static GList* tgprpl_blist_node_menu (PurpleBlistNode *node) { return menu; } +static void update_on_ready (struct tgl_state *TLS) { + debug ("update_on_ready()."); + + write_auth_file (TLS); + + purple_connection_set_state (tg_get_conn (TLS), PURPLE_CONNECTED); + purple_connection_set_display_name (tg_get_conn (TLS), purple_account_get_username (tg_get_acc (TLS))); + purple_blist_add_account (tg_get_acc (TLS)); + + debug ("seq = %d, pts = %d, date = %d", TLS->seq, TLS->pts, TLS->date); + tgl_do_get_difference (TLS, purple_account_get_bool (tg_get_acc (TLS), "history-sync-all", FALSE), + tgp_notify_on_error_gw, NULL); + tgl_do_get_dialog_list (TLS, 200, 0, on_get_dialog_list_done, NULL); + tgl_do_update_contact_list (TLS, 0, 0); +} + static void tgprpl_login (PurpleAccount * acct) { debug ("tgprpl_login()"); @@ -638,46 +622,50 @@ static void tgprpl_login (PurpleAccount * acct) { if (! tgp_startswith (purple_account_get_username (acct), "+")) { char *cause = g_strdup_printf (_("Unable to sign on as %s: phone number lacks country prefix."), purple_account_get_username (acct)); - purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, cause); - purple_notify_message (_telegram_protocol, PURPLE_NOTIFY_MSG_ERROR, cause, - _("Numbers must start with the full international\n" - "prefix code, e.g. +49 for Germany."), NULL, NULL, NULL); - g_free (cause); - return; + purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, cause); + purple_notify_message (_telegram_protocol, PURPLE_NOTIFY_MSG_ERROR, cause, + _("Numbers must start with the full international\n" + "prefix code, e.g. +49 for Germany."), NULL, NULL, NULL); + g_free (cause); + return; } + read_auth_file (TLS); + read_state_file (TLS); + read_secret_chat_file (TLS); + purple_connection_set_state (conn->gc, PURPLE_CONNECTING); - - telegram_login (TLS); + + tgl_login (TLS); } static void tgprpl_close (PurpleConnection *gc) { debug ("tgprpl_close()"); - connection_data *conn = purple_connection_get_protocol_data (gc); - connection_data_free (conn); + connection_data_free (purple_connection_get_protocol_data (gc)); } static int tgprpl_send_im (PurpleConnection *gc, const char *who, const char *message, PurpleMessageFlags flags) { debug ("tgprpl_send_im()"); - - // this is part of a workaround to support clients without - // the request API (request.h), see telegram-base.c:request_code() - if (gc_get_conn (gc)->in_fallback_chat) { + + // workaround to support clients without the request API (request.h), see tgp-request.c:request_code() + if (gc_get_conn (gc)->request_code_data) { // OTR plugins may try to insert messages that don't contain the code if (tgp_startswith (message, "?OTR")) { - info ("Fallback SMS auth, skipping OTR message: '%s'", message); - return -1; + info ("Fallback SMS auth, skipping OTR message: '%s'", message); + return -1; } - request_code_entered (gc_get_conn (gc)->TLS, message); - gc_get_conn (gc)->in_fallback_chat = 0; + struct request_values_data *data = gc_get_conn (gc)->request_code_data; + data->callback (gc_get_conn(gc)->TLS, &message, data->arg); + free (data); + + gc_get_conn (gc)->request_code_data = NULL; return 1; } /* - Make sure that we only send messages to an existing peer by - searching it in the peer tree. This allows us to give immediate feedback - by returning an error-code in case the peer doesn't exist + Make sure that to only send messages to an existing peer by searching it in the peer tree, to give immediate + feedback by returning an error-code in case the peer doesn't exist. */ tgl_peer_t *peer = tgp_blist_peer_find (gc_get_conn (gc)->TLS, who); if (peer) { @@ -1002,4 +990,3 @@ static PurplePluginInfo plugin_info = { }; PURPLE_INIT_PLUGIN (telegram, tgprpl_init, plugin_info) - diff --git a/tgp-request.c b/tgp-request.c index d68babb..c9b4780 100644 --- a/tgp-request.c +++ b/tgp-request.c @@ -31,97 +31,71 @@ #include "telegram-base.h" #include "tgp-2prpl.h" #include "tgp-utils.h" +#include "tgp-structs.h" -static void code_receive_result (struct tgl_state *TLS, void *extra, int success, struct tgl_user *U) { - struct request_password_data *data = extra; - if (success) { - ((void (*) (struct tgl_state *TLS)) data->callback) (TLS); - } else { - debug ("bad code, retrying..."); - request_code (TLS, data->callback); - } - free (data); -} - -void request_code_entered (gpointer extra, const gchar *code) { - struct request_password_data *data = extra; - connection_data *conn = data->TLS->ev_base; - char const *username = purple_account_get_username (conn->pa); +static void request_code_entered (struct request_values_data *data, const gchar *code) { char *stripped = g_strstrip (purple_markup_strip_html (code)); debug ("sending code: '%s'\n", stripped); - - tgl_do_send_code_result (data->TLS, username, (int)strlen (username), conn->hash, (int)strlen (conn->hash), - stripped, (int)strlen (stripped), code_receive_result, data); + data->callback (data->TLS, (const char **)&stripped, data->arg); g_free (stripped); } -static void request_code_canceled (gpointer extra) { - struct request_password_data *data = extra; - connection_data *conn = data->TLS->ev_base; - - purple_connection_error_reason (conn->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, "registration canceled"); +static void request_code_canceled (struct request_values_data *data) { + purple_connection_error_reason (tg_get_conn (data->TLS), PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, "registration canceled"); free (data); } -void request_code (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS)) { - debug ("Client is not registered, registering..."); - connection_data *conn = TLS->ev_base; - - struct request_password_data *data = malloc (sizeof(struct request_password_data)); +static void request_code (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS, const char *string[], void *arg), + void *arg) { + debug ("client is not registered, registering..."); + + struct request_values_data *data = malloc (sizeof(struct request_values_data)); data->TLS = TLS; - data->arg = conn; + data->arg = arg; data->callback = callback; if (purple_account_get_bool (tg_get_acc (TLS), "compat-verification", 0) || - ! purple_request_input (conn->gc, _("Login code"), _("Enter login code"), _("Telegram wants to verify your " + ! purple_request_input (tg_get_conn (TLS), _("Login code"), _("Enter login code"), _("Telegram wants to verify your " "identity. Please enter the code that you have received via SMS."), NULL, 0, 0, _("the code"), _("OK"), - G_CALLBACK(request_code_entered), _("Cancel"), G_CALLBACK(request_code_canceled), conn->pa, NULL, NULL, data)) { + G_CALLBACK(request_code_entered), _("Cancel"), G_CALLBACK(request_code_canceled), tg_get_acc (TLS), NULL, NULL, data)) { - // purple request API is not available, so we create a new conversation (the Telegram system - // account "7770000") to prompt the user for the code - conn->in_fallback_chat = 1; - purple_connection_set_state (conn->gc, PURPLE_CONNECTED); - PurpleConversation *conv = purple_conversation_new (PURPLE_CONV_TYPE_IM, conn->pa, "777000"); - purple_conversation_write (conv, "777000", _("What is your SMS verification code?"), + // the purple request API is not supported, create a new conversation (the Telegram system account "Telegram") to + // prompt the user for the code. + tg_get_data (TLS)->request_code_data = data; + purple_connection_set_state (tg_get_conn (TLS), PURPLE_CONNECTED); + PurpleConversation *conv = purple_conversation_new (PURPLE_CONV_TYPE_IM, tg_get_acc (TLS), "Telegram"); + purple_conversation_write (conv, "Telegram", _("What is your SMS verification code?"), PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_SYSTEM, 0); - free (data); } } -static void code_auth_receive_result (struct tgl_state *TLS, void *extra, int success, struct tgl_user *U) { - if (! success) { - debug ("Bad code..."); - request_name_and_code (TLS); +static void request_name_and_code (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS, const char *string[], void *arg), void *arg); +static void request_name_code_entered (struct request_values_data *data, PurpleRequestFields* fields) { + char *names[] = { + g_strstrip (g_strdup (purple_request_fields_get_string (fields, "first_name"))), + g_strstrip (g_strdup (purple_request_fields_get_string (fields, "last_name"))), + g_strstrip (g_strdup (purple_request_fields_get_string (fields, "code"))) + }; + + if (str_not_empty (names[0]) && str_not_empty (names[1]) && str_not_empty (names[2])) { + data->callback (data->TLS, (const char **) names, data->arg); } else { - telegram_export_authorization (TLS); + request_name_and_code (data->TLS, data->callback, data->arg); } + + int j; + for (j = 0; j < 3; ++j) { + g_free (names[j]); + } + free (data); } -void request_name_code_entered (PurpleConnection* gc, PurpleRequestFields* fields) { - connection_data *conn = purple_connection_get_protocol_data (gc); - struct tgl_state *TLS = conn->TLS; - char const *username = purple_account_get_username (conn->pa); - - char* first = g_strstrip (g_strdup (purple_request_fields_get_string (fields, "first_name"))); - char* last = g_strstrip (g_strdup (purple_request_fields_get_string (fields, "last_name"))); - char* code = g_strstrip (g_strdup (purple_request_fields_get_string (fields, "code"))); - if (!first || !last || !code) { - request_name_and_code (TLS); - return; - } - tgl_do_send_code_result_auth (TLS, username, (int)strlen(username), conn->hash, - (int)strlen (conn->hash), code, (int)strlen (code), first, - (int)strlen (first), last, (int)strlen (last), - code_auth_receive_result, NULL); - g_free (first); - g_free (last); - g_free (code); -} +static void request_name_and_code (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS, const char *string[], void *arg), void *arg) { + debug ("phone is not registered, registering..."); -void request_name_and_code (struct tgl_state *TLS) { - debug ("Phone is not registered, registering..."); - - connection_data *conn = TLS->ev_base; + struct request_values_data *data = talloc0 (sizeof (struct request_values_data)); + data->callback = callback; + data->arg = arg; PurpleRequestFields* fields = purple_request_fields_new (); PurpleRequestField* field = 0; @@ -138,26 +112,25 @@ void request_name_and_code (struct tgl_state *TLS) { purple_request_field_group_add_field (group, field); purple_request_fields_add_group (fields, group); - if (!purple_request_fields (conn->gc, _("Register"), _("Please register your phone number."), NULL, fields, _("OK"), - G_CALLBACK(request_name_code_entered), _("Cancel"), NULL, conn->pa, NULL, NULL, conn->gc)) { + if (!purple_request_fields (tg_get_conn (TLS), _("Register"), _("Please register your phone number."), NULL, fields, + _("OK"), G_CALLBACK(request_name_code_entered), _("Cancel"), NULL, tg_get_acc (TLS), NULL, NULL, data)) { // purple_request API not available const char *error = _("Phone number is not registered. Please register your phone on a different client."); - purple_connection_error_reason (conn->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, error); + purple_connection_error_reason (tg_get_conn (data->TLS) , PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, error); purple_notify_error (_telegram_protocol, _("Not Registered"), _("Not Registered"), error); } } -static void request_password_entered (struct request_password_data *data, PurpleRequestFields* fields) { - const char* pass = purple_request_fields_get_string (fields, "password"); - ((void (*)(struct tgl_state *TLS, const char *string[], void *arg)) data->callback) (data->TLS, &pass, data->arg); +static void request_password_entered (struct request_values_data *data, PurpleRequestFields* fields) { + const char *pass = purple_request_fields_get_string (fields, "password"); + data->callback (data->TLS, &pass, data->arg); free (data); } -void request_password (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS, const char *string[], void *arg), - void *arg) { +void request_password (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS, const char *string[], void *arg), void *arg) { connection_data *conn = TLS->ev_base; - struct request_password_data *data = malloc (sizeof(struct request_password_data)); + struct request_values_data *data = malloc (sizeof(struct request_values_data)); data->TLS = TLS; data->arg = arg; data->callback = callback; @@ -180,11 +153,8 @@ void request_password (struct tgl_state *TLS, void (*callback) (struct tgl_state } } -static void accept_secret_chat_cb (gpointer _data, const gchar *code) { - struct accept_secret_chat_data *data = _data; - +static void accept_secret_chat_cb (struct accept_secret_chat_data *data, const gchar *code) { tgl_do_accept_encr_chat_request (data->TLS, data->U, write_secret_chat_gw, 0); - g_free (data); } @@ -212,8 +182,7 @@ void request_accept_secret_chat (struct tgl_state *TLS, struct tgl_secret_chat * g_free (message); } -static void create_group_chat_cb (void *_data, PurpleRequestFields* fields) { - struct accept_create_chat_data *data = _data; +static void create_group_chat_cb (struct accept_create_chat_data *data, PurpleRequestFields* fields) { // FIXME: Oh god. const char *users[3] = { purple_request_fields_get_string (fields, "user1"), @@ -233,9 +202,6 @@ static void cancel_group_chat_cb (gpointer data) { } void request_choose_user (struct accept_create_chat_data *data) { - struct tgl_state *TLS = data->TLS; - connection_data *conn = TLS->ev_base; - // Telegram doesn't allow to create chats with only one user, so we need to force // the user to specify at least one other one. PurpleRequestFields* fields = purple_request_fields_new(); @@ -256,13 +222,11 @@ void request_choose_user (struct accept_create_chat_data *data) { purple_request_field_group_add_field (group, field); purple_request_fields_add_group (fields, group); - purple_request_fields (conn->gc, _("Create group chat"), _("Invite users"), NULL, fields, _("OK"), - G_CALLBACK(create_group_chat_cb), _("Cancel"), G_CALLBACK(cancel_group_chat_cb), conn->pa, NULL, NULL, data); + purple_request_fields (tg_get_conn (data->TLS), _("Create group chat"), _("Invite users"), NULL, fields, _("OK"), + G_CALLBACK(create_group_chat_cb), _("Cancel"), G_CALLBACK(cancel_group_chat_cb), tg_get_acc (data->TLS), NULL, NULL, data); } void request_create_chat (struct tgl_state *TLS, const char *subject) { - connection_data *conn = TLS->ev_base; - struct accept_create_chat_data *data = malloc (sizeof (struct accept_create_chat_data)); data->title = g_strdup (subject); data->TLS = TLS; @@ -272,7 +236,52 @@ void request_create_chat (struct tgl_state *TLS, const char *subject) { // FIXME: This dialog is pointless. It only asks whether the user wants to create a new chat. // This should be merged with the next dialog. // TODO: This still displays "Cancel" and "Accept", no matter $LANG - purple_request_accept_cancel (conn->gc, _("Create group chat"), title, secondary, 1, conn->pa, NULL, + purple_request_accept_cancel (tg_get_conn (TLS), _("Create group chat"), title, secondary, 1, tg_get_acc (TLS), NULL, NULL, data, G_CALLBACK(request_choose_user), G_CALLBACK(cancel_group_chat_cb)); g_free (secondary); } + +void request_value (struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, + void (*callback) (struct tgl_state *TLS, const char *string[], void *arg), void *arg) { + + debug ("tgl requests user input, tgl_value_type: %d, prompt: %s, count: %d", type, prompt, num_values); + switch (type) { + case tgl_cur_password: { + const char *P = purple_account_get_string (tg_get_acc (TLS), TGP_KEY_PASSWORD_TWO_FACTOR, NULL); + if (str_not_empty (P)) { + if (tg_get_data (TLS)->password_retries ++ < 1) { + callback (TLS, &P, arg); + return; + } + } + request_password (TLS, callback, arg); + break; + } + + case tgl_register_info: + request_name_and_code (TLS, callback, arg); + break; + + case tgl_code: + request_code (TLS, callback, arg); + break; + + case tgl_phone_number: { + // if we arrive here for the second time the specified phone number is not valid. We do not + // ask for the phone number directly, cause in that case the account would still be created + // named with the invalid phone number, even though the login will work + tgp_error_if_false (TLS, tg_get_data(TLS)->login_retries++ < 1, _("Invalid phone number"), + _("Please enter only numbers in the international phone number format, " + "a leading + following by the country prefix and the phone number.\n" + "Do not use any other special chars.")); + + const char *username = purple_account_get_username (tg_get_acc (TLS)); + callback (TLS, &username, arg); + break; + } + + default: + assert (FALSE); + break; + } +} diff --git a/tgp-request.h b/tgp-request.h index 803328c..b3e73f7 100644 --- a/tgp-request.h +++ b/tgp-request.h @@ -26,10 +26,11 @@ #include "tgp-structs.h" -struct request_password_data { +struct request_values_data { struct tgl_state *TLS; - void *callback; + void (*callback) (struct tgl_state *TLS, const char *string[], void *arg); void *arg; + const char *string[]; }; struct accept_create_chat_data { @@ -42,11 +43,8 @@ struct accept_secret_chat_data { struct tgl_secret_chat *U; }; -void request_code (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS)); -void request_code_entered (gpointer extra, const gchar *code); -void request_name_code_entered (PurpleConnection* gc, PurpleRequestFields* fields); -void request_name_and_code (struct tgl_state *TLS); -void request_password (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, const char *string[], void *arg), void *arg); +void request_value (struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, + void (*callback) (struct tgl_state *TLS, const char *string[], void *arg), void *arg); void request_accept_secret_chat (struct tgl_state *TLS, struct tgl_secret_chat *U); void request_choose_user (struct accept_create_chat_data *data); void request_create_chat (struct tgl_state *TLS, const char *subject); diff --git a/tgp-structs.h b/tgp-structs.h index 6b3b8d1..3cd827a 100644 --- a/tgp-structs.h +++ b/tgp-structs.h @@ -39,8 +39,9 @@ typedef struct { guint write_timer; guint login_timer; guint out_timer; - int in_fallback_chat; + struct request_values_data *request_code_data; int password_retries; + int login_retries; PurpleRoomlist *roomlist; GHashTable *pending_chat_info; GHashTable *id_to_purple_name; @@ -78,8 +79,6 @@ struct tgp_msg_sending { void pending_reads_send_all (struct tgl_state *TLS); void pending_reads_add (GQueue *queue, tgl_peer_id_t id); -struct message_text *message_text_init (struct tgl_message *M, gchar *text); -void message_text_free (gpointer data); void used_images_add (connection_data *data, gint imgid); void *connection_data_free (connection_data *conn); connection_data *connection_data_init (struct tgl_state *TLS, PurpleConnection *gc, PurpleAccount *pa);