1 /*
2 * frogr-auth-dialog.c -- Authorization dialog
3 *
4 * Copyright (C) 2009-2018 Mario Sanchez Prada
5 * Authors: Mario Sanchez Prada <msanchez@gnome.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 3 of the GNU General Public
9 * License as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>
18 *
19 */
20
21 #include "frogr-auth-dialog.h"
22
23 #include "frogr-controller.h"
24 #include "frogr-global-defs.h"
25 #include "frogr-util.h"
26
27 #include <config.h>
28 #include <glib/gi18n.h>
29
30 #if GTK_CHECK_VERSION (3, 12, 0)
31 #define AUTH_DIALOG_FLAGS (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR)
32 #else
33 #define AUTH_DIALOG_FLAGS (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT)
34 #endif
35
36
37 /* Prototypes */
38
39 static void _ask_for_authorization (GtkWindow *parent);
40
41 static void _ask_for_authorization_response_cb (GtkDialog *dialog, gint response, gpointer data);
42
43 static void _ask_for_auth_confirmation (GtkWindow *parent);
44
45 static void _ask_for_auth_confirmation_response_cb (GtkDialog *dialog, gint response, gpointer data);
46
47 /* Private API */
48
49 static void
_ask_for_authorization(GtkWindow * parent)50 _ask_for_authorization (GtkWindow *parent)
51 {
52 GtkWidget *dialog = NULL;
53 g_autofree gchar *title = NULL;
54
55 dialog = gtk_message_dialog_new (parent,
56 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
57 GTK_MESSAGE_INFO,
58 GTK_BUTTONS_OK,
59 _("Please press the button to authorize %s "
60 "and then come back to complete the process."),
61 APP_SHORTNAME);
62
63 title = g_strdup_printf (_("Authorize %s"), APP_SHORTNAME);
64 gtk_window_set_title (GTK_WINDOW (dialog), title);
65
66 g_signal_connect (G_OBJECT (dialog), "response",
67 G_CALLBACK (_ask_for_authorization_response_cb), NULL);
68
69 gtk_widget_show (dialog);
70 }
71
72 static void
_ask_for_authorization_response_cb(GtkDialog * dialog,gint response,gpointer data)73 _ask_for_authorization_response_cb (GtkDialog *dialog, gint response, gpointer data)
74 {
75 if (response == GTK_RESPONSE_OK)
76 {
77 FrogrController *controller = frogr_controller_get_instance();
78 frogr_controller_open_auth_url (controller);
79 }
80
81 gtk_widget_destroy (GTK_WIDGET (dialog));
82 }
83
84 static void
_code_entry_text_inserted_cb(GtkEditable * editable,gchar * new_text,gint new_text_length,gint * position,gpointer data)85 _code_entry_text_inserted_cb (GtkEditable *editable, gchar *new_text,
86 gint new_text_length, gint *position,
87 gpointer data)
88 {
89 gint i = 0;
90 for (i = 0; i < new_text_length; i++)
91 {
92 /* Stop this signal's emission if one of the new characters is
93 not an integer, and stop searching, obviously */
94 if (!g_ascii_isdigit (new_text[i]))
95 {
96 g_signal_stop_emission_by_name (editable, "insert-text");
97 break;
98 }
99 }
100 }
101
102 static GtkWidget *
_build_verification_code_entry_widget(GtkWidget * dialog)103 _build_verification_code_entry_widget (GtkWidget *dialog)
104 {
105 GtkWidget *hbox = NULL;
106 GtkWidget *entry = NULL;
107 GtkWidget *separator = NULL;
108 gchar *entry_key = NULL;
109 gint i = 0;
110
111 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
112 gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
113 for (i = 0; i < 3; i++)
114 {
115 entry = gtk_entry_new ();
116 gtk_entry_set_max_length (GTK_ENTRY (entry), 3);
117 gtk_entry_set_width_chars (GTK_ENTRY (entry), 3);
118 gtk_entry_set_alignment (GTK_ENTRY (entry), 0.5);
119 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, FALSE, 6);
120 gtk_widget_show (entry);
121
122 entry_key = g_strdup_printf ("vercode-%d", i + 1);
123 g_object_set_data (G_OBJECT (dialog), entry_key, entry);
124 g_free (entry_key);
125
126 g_signal_connect (G_OBJECT (entry), "insert-text",
127 G_CALLBACK (_code_entry_text_inserted_cb),
128 NULL);
129 if (i < 2)
130 {
131 separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
132 gtk_box_pack_start (GTK_BOX (hbox), separator, TRUE, TRUE, 0);
133 gtk_widget_show (separator);
134 }
135 }
136
137 gtk_widget_show (hbox);
138 return hbox;
139 }
140
141 static void
_ask_for_auth_confirmation(GtkWindow * parent)142 _ask_for_auth_confirmation (GtkWindow *parent)
143 {
144 GtkWidget *dialog = NULL;
145 GtkWidget *content_area = NULL;
146 GtkWidget *vbox = NULL;
147 GtkWidget *ver_code_entry = NULL;
148 GtkWidget *label = NULL;
149 g_autofree gchar *title = NULL;
150
151 title = g_strdup_printf (_("Authorize %s"), APP_SHORTNAME);
152 dialog = gtk_dialog_new_with_buttons (title,
153 parent,
154 AUTH_DIALOG_FLAGS,
155 _("_Cancel"),
156 GTK_RESPONSE_CANCEL,
157 _("_Close"),
158 GTK_RESPONSE_CLOSE,
159 NULL);
160 gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
161
162 /* Fill action area */
163 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
164 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
165 gtk_widget_set_margin_bottom (vbox, 6);
166 gtk_widget_show (vbox);
167
168 /* Description label */
169 label = gtk_label_new (_("Enter verification code:"));
170 gtk_widget_set_halign (label, GTK_ALIGN_START);
171 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
172 gtk_widget_show (label);
173
174 /* Entry widgets for the verification code */
175 ver_code_entry = _build_verification_code_entry_widget (dialog);
176 gtk_box_pack_start (GTK_BOX (vbox), ver_code_entry, FALSE, FALSE, 0);
177 gtk_widget_show (ver_code_entry);
178
179 gtk_widget_show (content_area);
180 gtk_container_add (GTK_CONTAINER (content_area), vbox);
181
182 g_signal_connect (G_OBJECT (dialog), "response",
183 G_CALLBACK (_ask_for_auth_confirmation_response_cb), NULL);
184
185 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
186
187 gtk_window_set_default_size (GTK_WINDOW (dialog), 200, -1);
188 gtk_widget_show (dialog);
189 }
190
191 static const gchar*
_get_entry_code_for_dialog(GtkDialog * dialog,const gchar * entry_key)192 _get_entry_code_for_dialog (GtkDialog *dialog, const gchar *entry_key)
193 {
194 GtkWidget *entry = g_object_get_data (G_OBJECT (dialog), entry_key);
195 if (entry == NULL)
196 return NULL;
197
198 return gtk_entry_get_text (GTK_ENTRY (entry));
199 }
200
201 static void
_ask_for_auth_confirmation_response_cb(GtkDialog * dialog,gint response,gpointer data)202 _ask_for_auth_confirmation_response_cb (GtkDialog *dialog, gint response, gpointer data)
203 {
204 gboolean valid = FALSE;
205
206 if (response == GTK_RESPONSE_CLOSE)
207 {
208 const gchar *vercode_part1 = NULL;
209 const gchar *vercode_part2 = NULL;
210 const gchar *vercode_part3 = NULL;
211 g_autofree gchar *vercode_full = NULL;
212
213 vercode_part1 = _get_entry_code_for_dialog (dialog, "vercode-1");
214 vercode_part2 = _get_entry_code_for_dialog (dialog, "vercode-2");
215 vercode_part3 = _get_entry_code_for_dialog (dialog, "vercode-3");
216
217 vercode_full = g_strdup_printf ("%s-%s-%s", vercode_part1, vercode_part2, vercode_part3);
218
219 /* Ensure the user enters a valid verification code */
220 if (g_regex_match_simple ("[0-9]{3}(-[0-9]{3}){2}", vercode_full, 0, 0))
221 {
222 frogr_controller_complete_auth (frogr_controller_get_instance(), vercode_full);
223 valid = TRUE;
224 }
225 else
226 frogr_util_show_error_dialog (GTK_WINDOW (dialog), _("Invalid verification code"));
227 }
228
229 if (response == GTK_RESPONSE_CANCEL || valid)
230 gtk_widget_destroy (GTK_WIDGET (dialog));
231 }
232
233 /* Public API */
234
235 void
frogr_auth_dialog_show(GtkWindow * parent,FrogrAuthDialogStep step)236 frogr_auth_dialog_show (GtkWindow *parent, FrogrAuthDialogStep step)
237 {
238 switch (step) {
239 case REQUEST_AUTHORIZATION:
240 _ask_for_authorization (parent);
241 break;
242 case CONFIRM_AUTHORIZATION:
243 _ask_for_auth_confirmation (parent);
244 break;
245 default:
246 g_assert_not_reached();
247 }
248 }
249