diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-12-30 00:06:10 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-12-30 00:06:10 +0100 |
commit | d77e7cab65c416f72ff1b52fa590b24ede512e75 (patch) | |
tree | f69e8c038d4723c60c348342b03e11ecb1611401 | |
parent | 987f3f2f2d4f7fd61c115323fb17e6889f1e1120 (diff) | |
download | anastasis-gtk-d77e7cab65c416f72ff1b52fa590b24ede512e75.tar.gz anastasis-gtk-d77e7cab65c416f72ff1b52fa590b24ede512e75.zip |
simplify pin entry by breaking up into groups and auto-completion (#7088)
-rw-r--r-- | contrib/anastasis_gtk_challenge_code.glade | 1 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk_autocomplete.c | 100 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk_handle-challenge-code.c | 25 |
3 files changed, 101 insertions, 25 deletions
diff --git a/contrib/anastasis_gtk_challenge_code.glade b/contrib/anastasis_gtk_challenge_code.glade index 8b4113e..176660e 100644 --- a/contrib/anastasis_gtk_challenge_code.glade +++ b/contrib/anastasis_gtk_challenge_code.glade | |||
@@ -235,6 +235,7 @@ Author: Christian Grothoff | |||
235 | <property name="primary-icon-stock">gtk-dialog-authentication</property> | 235 | <property name="primary-icon-stock">gtk-dialog-authentication</property> |
236 | <property name="placeholder-text" translatable="no">A-</property> | 236 | <property name="placeholder-text" translatable="no">A-</property> |
237 | <signal name="changed" handler="anastasis_gtk_c_code_dialog_answer_entry_changed_cb" swapped="no"/> | 237 | <signal name="changed" handler="anastasis_gtk_c_code_dialog_answer_entry_changed_cb" swapped="no"/> |
238 | <signal name="insert-text" handler="anastasis_gtk_pin_autocomplete_insert_text" swapped="no"/> | ||
238 | </object> | 239 | </object> |
239 | <packing> | 240 | <packing> |
240 | <property name="expand">False</property> | 241 | <property name="expand">False</property> |
diff --git a/src/anastasis/anastasis-gtk_autocomplete.c b/src/anastasis/anastasis-gtk_autocomplete.c index 1e3da34..c941d25 100644 --- a/src/anastasis/anastasis-gtk_autocomplete.c +++ b/src/anastasis/anastasis-gtk_autocomplete.c | |||
@@ -50,12 +50,41 @@ lookup_autocomplete (GtkEditable *editable) | |||
50 | } | 50 | } |
51 | json_array_foreach (ra, index, a) | 51 | json_array_foreach (ra, index, a) |
52 | { | 52 | { |
53 | const char *widget_name = json_string_value (json_object_get (a, | 53 | const char *autocomplete = NULL; |
54 | "widget")); | 54 | const char *widget_name = NULL; |
55 | if (editable == | 55 | const char *type = NULL; |
56 | GTK_EDITABLE (GCG_get_main_window_object (ai[i].widget_name))) | 56 | char *data_name; |
57 | return json_string_value (json_object_get (a, | 57 | bool match; |
58 | "autocomplete")); | 58 | struct GNUNET_JSON_Specification spec[] = { |
59 | GNUNET_JSON_spec_mark_optional ( | ||
60 | GNUNET_JSON_spec_string ("widget", | ||
61 | &widget_name)), | ||
62 | GNUNET_JSON_spec_mark_optional ( | ||
63 | GNUNET_JSON_spec_string ("autocomplete", | ||
64 | &autocomplete)), | ||
65 | GNUNET_JSON_spec_string ("type", | ||
66 | &type), | ||
67 | GNUNET_JSON_spec_end () | ||
68 | }; | ||
69 | |||
70 | if (GNUNET_OK != | ||
71 | GNUNET_JSON_parse (a, | ||
72 | spec, | ||
73 | NULL, NULL)) | ||
74 | { | ||
75 | GNUNET_break (0); | ||
76 | continue; | ||
77 | } | ||
78 | if ( (NULL == autocomplete) || | ||
79 | (NULL == widget_name) ) | ||
80 | continue; | ||
81 | data_name = AG_expand_name (widget_name, | ||
82 | type); | ||
83 | match = (editable == | ||
84 | GTK_EDITABLE (GCG_get_main_window_object (data_name))); | ||
85 | GNUNET_free (data_name); | ||
86 | if (match) | ||
87 | return autocomplete; | ||
59 | } | 88 | } |
60 | GNUNET_break (0); | 89 | GNUNET_break (0); |
61 | return NULL; | 90 | return NULL; |
@@ -115,10 +144,10 @@ anastasis_gtk_autocomplete_insert_text (GtkEditable *editable, | |||
115 | void *user_data) | 144 | void *user_data) |
116 | { | 145 | { |
117 | const char *ac; | 146 | const char *ac; |
118 | (void) user_data; | ||
119 | gint pos; | 147 | gint pos; |
120 | char *replacement; | 148 | char *replacement; |
121 | 149 | ||
150 | (void) user_data; | ||
122 | ac = lookup_autocomplete (editable); | 151 | ac = lookup_autocomplete (editable); |
123 | if (NULL == ac) | 152 | if (NULL == ac) |
124 | return; | 153 | return; |
@@ -141,3 +170,60 @@ anastasis_gtk_autocomplete_insert_text (GtkEditable *editable, | |||
141 | GNUNET_free (replacement); | 170 | GNUNET_free (replacement); |
142 | } | 171 | } |
143 | } | 172 | } |
173 | |||
174 | |||
175 | /** | ||
176 | * Function called from an auto-completed PIN widget upon text insertion. | ||
177 | * | ||
178 | * @param editable the widget | ||
179 | * @param new_text inserted text | ||
180 | * @param new_text_length number of bytes in @a new_text | ||
181 | * @param position insertion position | ||
182 | * @param user_data unused | ||
183 | */ | ||
184 | void | ||
185 | anastasis_gtk_pin_autocomplete_insert_text (GtkEditable *editable, | ||
186 | const char *new_text, | ||
187 | int new_text_length, | ||
188 | gpointer position, | ||
189 | void *user_data) | ||
190 | { | ||
191 | /* Use \? to break up trigraphs */ | ||
192 | const char *acn = "????\?-??\?-???\?-??\?"; | ||
193 | const char *aca = "A-????\?-??\?-???\?-??\?"; | ||
194 | const char *ac; | ||
195 | gint pos; | ||
196 | char *replacement; | ||
197 | gchar *pfx; | ||
198 | |||
199 | (void) user_data; | ||
200 | pfx = gtk_editable_get_chars (editable, | ||
201 | 0, | ||
202 | 2); | ||
203 | if (0 == strncasecmp (pfx, | ||
204 | "A-", | ||
205 | 2)) | ||
206 | ac = aca; | ||
207 | else | ||
208 | ac = acn; | ||
209 | g_free (pfx); | ||
210 | |||
211 | pos = gtk_editable_get_position (editable); | ||
212 | if (strlen (ac) <= pos + new_text_length) | ||
213 | return; | ||
214 | if (ac[pos+new_text_length] != '?') | ||
215 | { | ||
216 | g_signal_stop_emission_by_name (editable, | ||
217 | "insert-text"); | ||
218 | GNUNET_asprintf (&replacement, | ||
219 | "%.*s%c", | ||
220 | new_text_length, | ||
221 | new_text, | ||
222 | ac[pos+new_text_length]); | ||
223 | gtk_editable_insert_text (editable, | ||
224 | replacement, | ||
225 | -1, | ||
226 | position); | ||
227 | GNUNET_free (replacement); | ||
228 | } | ||
229 | } | ||
diff --git a/src/anastasis/anastasis-gtk_handle-challenge-code.c b/src/anastasis/anastasis-gtk_handle-challenge-code.c index 7a993da..4f42023 100644 --- a/src/anastasis/anastasis-gtk_handle-challenge-code.c +++ b/src/anastasis/anastasis-gtk_handle-challenge-code.c | |||
@@ -49,6 +49,7 @@ anastasis_gtk_c_code_dialog_response_cb (GtkDialog *dialog, | |||
49 | json_t *args; | 49 | json_t *args; |
50 | unsigned long long pin; | 50 | unsigned long long pin; |
51 | char dummy; | 51 | char dummy; |
52 | char s[16]; | ||
52 | 53 | ||
53 | if (GTK_RESPONSE_OK != response_id) | 54 | if (GTK_RESPONSE_OK != response_id) |
54 | { | 55 | { |
@@ -65,20 +66,15 @@ anastasis_gtk_c_code_dialog_response_cb (GtkDialog *dialog, | |||
65 | q = GTK_ENTRY (gtk_builder_get_object (builder, | 66 | q = GTK_ENTRY (gtk_builder_get_object (builder, |
66 | "anastasis_gtk_c_code_entry")); | 67 | "anastasis_gtk_c_code_entry")); |
67 | qs = gtk_entry_get_text (q); | 68 | qs = gtk_entry_get_text (q); |
68 | if ( (NULL != qs) && | 69 | if (! ANASTASIS_scan_pin (qs, |
69 | (0 == strncasecmp ("a-", qs, 2)) ) | 70 | &pin)) |
70 | qs += 2; /* skip "A-" prefix if present */ | ||
71 | if (1 != sscanf (qs, | ||
72 | "%llu%c", | ||
73 | &pin, | ||
74 | &dummy)) | ||
75 | { | 71 | { |
76 | GNUNET_break (0); | 72 | GNUNET_break (0); |
77 | return; | 73 | return; |
78 | } | 74 | } |
79 | args = GNUNET_JSON_PACK ( | 75 | args = GNUNET_JSON_PACK ( |
80 | GNUNET_JSON_pack_uint64 ("pin", | 76 | GNUNET_JSON_pack_uint64 ("pin", |
81 | pin)); | 77 | (uint64_t) pin)); |
82 | gtk_widget_destroy (GTK_WIDGET (dialog)); | 78 | gtk_widget_destroy (GTK_WIDGET (dialog)); |
83 | g_object_unref (G_OBJECT (builder)); | 79 | g_object_unref (G_OBJECT (builder)); |
84 | AG_freeze (); | 80 | AG_freeze (); |
@@ -98,21 +94,14 @@ anastasis_gtk_c_code_dialog_answer_entry_changed_cb (GtkEntry *entry, | |||
98 | GtkBuilder *builder = GTK_BUILDER (user_data); | 94 | GtkBuilder *builder = GTK_BUILDER (user_data); |
99 | GtkEntry *a; | 95 | GtkEntry *a; |
100 | const char *as; | 96 | const char *as; |
101 | unsigned int pin; | 97 | unsigned long long pin; |
102 | char dummy; | ||
103 | bool ok; | 98 | bool ok; |
104 | 99 | ||
105 | a = GTK_ENTRY (gtk_builder_get_object (builder, | 100 | a = GTK_ENTRY (gtk_builder_get_object (builder, |
106 | "anastasis_gtk_c_code_entry")); | 101 | "anastasis_gtk_c_code_entry")); |
107 | as = gtk_entry_get_text (a); | 102 | as = gtk_entry_get_text (a); |
108 | if ( (NULL != as) && | 103 | ok = ANASTASIS_scan_pin (as, |
109 | (0 == strncasecmp ("a-", as, 2)) ) | 104 | &pin); |
110 | as += 2; /* skip "A-" prefix if present */ | ||
111 | ok = ( (NULL != as) && | ||
112 | (1 == sscanf (as, | ||
113 | "%u%c", | ||
114 | &pin, | ||
115 | &dummy)) ); | ||
116 | gtk_widget_set_sensitive ( | 105 | gtk_widget_set_sensitive ( |
117 | GTK_WIDGET (gtk_builder_get_object (builder, | 106 | GTK_WIDGET (gtk_builder_get_object (builder, |
118 | "anastasis_gtk_c_code_dialog_btn_ok")), | 107 | "anastasis_gtk_c_code_dialog_btn_ok")), |