No issues found
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /*
3 * Copyright 2012 Red Hat, Inc.
4 * 2012 Stef Walter <stefw@gnome.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Author: Stef Walter <stefw@gnome.org>
21 */
22
23 #include "config.h"
24
25 #include "shell-keyring-prompt.h"
26 #include "shell-secure-text-buffer.h"
27
28 #define GCR_API_SUBJECT_TO_CHANGE
29 #include <gcr/gcr-base.h>
30
31 #include <glib/gi18n.h>
32
33 #include <string.h>
34
35 typedef struct _ShellPasswordPromptClass ShellPasswordPromptClass;
36 typedef struct _ShellPasswordPromptPrivate ShellPasswordPromptPrivate;
37
38 typedef enum
39 {
40 PROMPTING_NONE,
41 PROMPTING_FOR_CONFIRM,
42 PROMPTING_FOR_PASSWORD
43 } PromptingMode;
44
45 struct _ShellKeyringPrompt
46 {
47 GObject parent;
48
49 gchar *title;
50 gchar *message;
51 gchar *description;
52 gchar *warning;
53 gchar *choice_label;
54 gboolean choice_chosen;
55 gboolean password_new;
56 guint password_strength;
57 gchar *continue_label;
58 gchar *cancel_label;
59
60 GcrPromptReply last_reply;
61 GSimpleAsyncResult *async_result;
62 ClutterText *password_actor;
63 ClutterText *confirm_actor;
64 PromptingMode mode;
65 gboolean shown;
66 };
67
68 typedef struct _ShellKeyringPromptClass
69 {
70 GObjectClass parent_class;
71 } ShellKeyringPromptClass;
72
73 enum {
74 PROP_0,
75 PROP_TITLE,
76 PROP_MESSAGE,
77 PROP_DESCRIPTION,
78 PROP_WARNING,
79 PROP_CHOICE_LABEL,
80 PROP_CHOICE_CHOSEN,
81 PROP_PASSWORD_NEW,
82 PROP_PASSWORD_STRENGTH,
83 PROP_CALLER_WINDOW,
84 PROP_CONTINUE_LABEL,
85 PROP_CANCEL_LABEL,
86 PROP_PASSWORD_VISIBLE,
87 PROP_CONFIRM_VISIBLE,
88 PROP_WARNING_VISIBLE,
89 PROP_CHOICE_VISIBLE,
90 PROP_PASSWORD_ACTOR,
91 PROP_CONFIRM_ACTOR
92 };
93
94 static void shell_keyring_prompt_iface (GcrPromptIface *iface);
95
96 G_DEFINE_TYPE_WITH_CODE (ShellKeyringPrompt, shell_keyring_prompt, G_TYPE_OBJECT,
97 G_IMPLEMENT_INTERFACE (GCR_TYPE_PROMPT, shell_keyring_prompt_iface);
98 );
99
100 enum {
101 SIGNAL_SHOW_PASSWORD,
102 SIGNAL_SHOW_CONFIRM,
103 SIGNAL_HIDE_PROMPT,
104 SIGNAL_LAST
105 };
106
107 static gint signals[SIGNAL_LAST];
108
109 static void
110 shell_keyring_prompt_init (ShellKeyringPrompt *self)
111 {
112
113 }
114
115 static void
116 shell_keyring_prompt_set_property (GObject *obj,
117 guint prop_id,
118 const GValue *value,
119 GParamSpec *pspec)
120 {
121 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
122
123 switch (prop_id) {
124 case PROP_TITLE:
125 g_free (self->title);
126 self->title = g_value_dup_string (value);
127 g_object_notify (obj, "title");
128 break;
129 case PROP_MESSAGE:
130 g_free (self->message);
131 self->message = g_value_dup_string (value);
132 g_object_notify (obj, "message");
133 break;
134 case PROP_DESCRIPTION:
135 g_free (self->description);
136 self->description = g_value_dup_string (value);
137 g_object_notify (obj, "description");
138 break;
139 case PROP_WARNING:
140 g_free (self->warning);
141 self->warning = g_value_dup_string (value);
142 if (!self->warning)
143 self->warning = g_strdup ("");
144 g_object_notify (obj, "warning");
145 g_object_notify (obj, "warning-visible");
146 break;
147 case PROP_CHOICE_LABEL:
148 g_free (self->choice_label);
149 self->choice_label = g_value_dup_string (value);
150 if (!self->choice_label)
151 self->choice_label = g_strdup ("");
152 g_object_notify (obj, "choice-label");
153 g_object_notify (obj, "choice-visible");
154 break;
155 case PROP_CHOICE_CHOSEN:
156 self->choice_chosen = g_value_get_boolean (value);
157 g_object_notify (obj, "choice-chosen");
158 break;
159 case PROP_PASSWORD_NEW:
160 self->password_new = g_value_get_boolean (value);
161 g_object_notify (obj, "password-new");
162 g_object_notify (obj, "confirm-visible");
163 break;
164 case PROP_CALLER_WINDOW:
165 /* ignored */
166 break;
167 case PROP_CONTINUE_LABEL:
168 g_free (self->continue_label);
169 self->continue_label = g_value_dup_string (value);
170 g_object_notify (obj, "continue-label");
171 break;
172 case PROP_CANCEL_LABEL:
173 g_free (self->cancel_label);
174 self->cancel_label = g_value_dup_string (value);
175 g_object_notify (obj, "cancel-label");
176 break;
177 case PROP_PASSWORD_ACTOR:
178 shell_keyring_prompt_set_password_actor (self, g_value_get_object (value));
179 break;
180 case PROP_CONFIRM_ACTOR:
181 shell_keyring_prompt_set_confirm_actor (self, g_value_get_object (value));
182 break;
183 default:
184 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
185 break;
186 }
187 }
188
189 static void
190 shell_keyring_prompt_get_property (GObject *obj,
191 guint prop_id,
192 GValue *value,
193 GParamSpec *pspec)
194 {
195 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
196
197 switch (prop_id) {
198 case PROP_TITLE:
199 g_value_set_string (value, self->title ? self->title : "");
200 break;
201 case PROP_MESSAGE:
202 g_value_set_string (value, self->message ? self->message : "");
203 break;
204 case PROP_DESCRIPTION:
205 g_value_set_string (value, self->description ? self->description : "");
206 break;
207 case PROP_WARNING:
208 g_value_set_string (value, self->warning ? self->warning : "");
209 break;
210 case PROP_CHOICE_LABEL:
211 g_value_set_string (value, self->choice_label ? self->choice_label : "");
212 break;
213 case PROP_CHOICE_CHOSEN:
214 g_value_set_boolean (value, self->choice_chosen);
215 break;
216 case PROP_PASSWORD_NEW:
217 g_value_set_boolean (value, self->password_new);
218 break;
219 case PROP_PASSWORD_STRENGTH:
220 g_value_set_int (value, self->password_strength);
221 break;
222 case PROP_CALLER_WINDOW:
223 g_value_set_string (value, "");
224 break;
225 case PROP_CONTINUE_LABEL:
226 g_value_set_string (value, self->continue_label);
227 break;
228 case PROP_CANCEL_LABEL:
229 g_value_set_string (value, self->cancel_label);
230 break;
231 case PROP_PASSWORD_VISIBLE:
232 g_value_set_boolean (value, self->mode == PROMPTING_FOR_PASSWORD);
233 break;
234 case PROP_CONFIRM_VISIBLE:
235 g_value_set_boolean (value, self->password_new &&
236 self->mode == PROMPTING_FOR_PASSWORD);
237 break;
238 case PROP_WARNING_VISIBLE:
239 g_value_set_boolean (value, self->warning && self->warning[0]);
240 break;
241 case PROP_CHOICE_VISIBLE:
242 g_value_set_boolean (value, self->choice_label && self->choice_label[0]);
243 break;
244 case PROP_PASSWORD_ACTOR:
245 g_value_set_object (value, shell_keyring_prompt_get_password_actor (self));
246 break;
247 case PROP_CONFIRM_ACTOR:
248 g_value_set_object (value, shell_keyring_prompt_get_confirm_actor (self));
249 break;
250 default:
251 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
252 break;
253 }
254 }
255
256 static void
257 shell_keyring_prompt_dispose (GObject *obj)
258 {
259 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
260
261 if (self->shown) {
262 self->shown = FALSE;
263 g_signal_emit (self, signals[SIGNAL_HIDE_PROMPT], 0);
264 }
265
266 if (self->async_result)
267 shell_keyring_prompt_cancel (self);
268 g_assert (self->async_result == NULL);
269
270 shell_keyring_prompt_set_password_actor (self, NULL);
271 shell_keyring_prompt_set_confirm_actor (self, NULL);
272
273 G_OBJECT_CLASS (shell_keyring_prompt_parent_class)->dispose (obj);
274 }
275
276 static void
277 shell_keyring_prompt_finalize (GObject *obj)
278 {
279 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
280
281 g_free (self->title);
282 g_free (self->message);
283 g_free (self->description);
284 g_free (self->warning);
285 g_free (self->choice_label);
286 g_free (self->continue_label);
287 g_free (self->cancel_label);
288
289 G_OBJECT_CLASS (shell_keyring_prompt_parent_class)->finalize (obj);
290 }
291
292 static void
293 shell_keyring_prompt_class_init (ShellKeyringPromptClass *klass)
294 {
295 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
296
297 gobject_class->get_property = shell_keyring_prompt_get_property;
298 gobject_class->set_property = shell_keyring_prompt_set_property;
299 gobject_class->dispose = shell_keyring_prompt_dispose;
300 gobject_class->finalize = shell_keyring_prompt_finalize;
301
302 g_object_class_override_property (gobject_class, PROP_TITLE, "title");
303
304 g_object_class_override_property (gobject_class, PROP_MESSAGE, "message");
305
306 g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
307
308 g_object_class_override_property (gobject_class, PROP_WARNING, "warning");
309
310 g_object_class_override_property (gobject_class, PROP_PASSWORD_NEW, "password-new");
311
312 g_object_class_override_property (gobject_class, PROP_PASSWORD_STRENGTH, "password-strength");
313
314 g_object_class_override_property (gobject_class, PROP_CHOICE_LABEL, "choice-label");
315
316 g_object_class_override_property (gobject_class, PROP_CHOICE_CHOSEN, "choice-chosen");
317
318 g_object_class_override_property (gobject_class, PROP_CALLER_WINDOW, "caller-window");
319
320 g_object_class_override_property (gobject_class, PROP_CONTINUE_LABEL, "continue-label");
321
322 g_object_class_override_property (gobject_class, PROP_CANCEL_LABEL, "cancel-label");
323
324 /**
325 * ShellKeyringPrompt:password-visible:
326 *
327 * Whether the password entry is visible or not.
328 */
329 g_object_class_install_property (gobject_class, PROP_PASSWORD_VISIBLE,
330 g_param_spec_boolean ("password-visible", "Password visible", "Password field is visible",
331 FALSE, G_PARAM_READABLE));
332
333 /**
334 * ShellKeyringPrompt:confirm-visible:
335 *
336 * Whether the password confirm entry is visible or not.
337 */
338 g_object_class_install_property (gobject_class, PROP_CONFIRM_VISIBLE,
339 g_param_spec_boolean ("confirm-visible", "Confirm visible", "Confirm field is visible",
340 FALSE, G_PARAM_READABLE));
341
342 /**
343 * ShellKeyringPrompt:warning-visible:
344 *
345 * Whether the warning label is visible or not.
346 */
347 g_object_class_install_property (gobject_class, PROP_WARNING_VISIBLE,
348 g_param_spec_boolean ("warning-visible", "Warning visible", "Warning is visible",
349 FALSE, G_PARAM_READABLE));
350
351 /**
352 * ShellKeyringPrompt:choice-visible:
353 *
354 * Whether the choice check box is visible or not.
355 */
356 g_object_class_install_property (gobject_class, PROP_CHOICE_VISIBLE,
357 g_param_spec_boolean ("choice-visible", "Choice visible", "Choice is visible",
358 FALSE, G_PARAM_READABLE));
359
360 /**
361 * ShellKeyringPrompt:password-actor:
362 *
363 * Text field for password
364 */
365 g_object_class_install_property (gobject_class, PROP_PASSWORD_ACTOR,
366 g_param_spec_object ("password-actor", "Password actor", "Text field for password",
367 CLUTTER_TYPE_TEXT, G_PARAM_READWRITE));
368
369 /**
370 * ShellKeyringPrompt:confirm-actor:
371 *
372 * Text field for confirmation password
373 */
374 g_object_class_install_property (gobject_class, PROP_CONFIRM_ACTOR,
375 g_param_spec_object ("confirm-actor", "Confirm actor", "Text field for confirming password",
376 CLUTTER_TYPE_TEXT, G_PARAM_READWRITE));
377
378 signals[SIGNAL_SHOW_PASSWORD] = g_signal_new ("show-password", G_TYPE_FROM_CLASS (klass),
379 0, 0, NULL, NULL,
380 g_cclosure_marshal_VOID__VOID,
381 G_TYPE_NONE, 0);
382
383 signals[SIGNAL_SHOW_CONFIRM] = g_signal_new ("show-confirm", G_TYPE_FROM_CLASS (klass),
384 0, 0, NULL, NULL,
385 g_cclosure_marshal_VOID__VOID,
386 G_TYPE_NONE, 0);
387
388 signals[SIGNAL_HIDE_PROMPT] = g_signal_new ("hide-prompt", G_TYPE_FROM_CLASS (klass),
389 0, 0, NULL, NULL,
390 g_cclosure_marshal_VOID__VOID,
391 G_TYPE_NONE, 0);
392 }
393
394 static void
395 shell_keyring_prompt_password_async (GcrPrompt *prompt,
396 GCancellable *cancellable,
397 GAsyncReadyCallback callback,
398 gpointer user_data)
399 {
400 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
401 GObject *obj;
402
403 if (self->async_result != NULL) {
404 g_warning ("this prompt can only show one prompt at a time");
405 return;
406 }
407
408 self->mode = PROMPTING_FOR_PASSWORD;
409 self->async_result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
410 shell_keyring_prompt_password_async);
411
412 obj = G_OBJECT (self);
413 g_object_notify (obj, "password-visible");
414 g_object_notify (obj, "confirm-visible");
415 g_object_notify (obj, "warning-visible");
416 g_object_notify (obj, "choice-visible");
417
418 self->shown = TRUE;
419 g_signal_emit (self, signals[SIGNAL_SHOW_PASSWORD], 0);
420 }
421
422 static const gchar *
423 shell_keyring_prompt_password_finish (GcrPrompt *prompt,
424 GAsyncResult *result,
425 GError **error)
426 {
427 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
428
429 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (prompt),
430 shell_keyring_prompt_password_async), NULL);
431
432 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
433 return NULL;
434
435 if (self->last_reply == GCR_PROMPT_REPLY_CONTINUE)
436 return clutter_text_get_text (self->password_actor);
437
438 return NULL;
439 }
440
441 static void
442 shell_keyring_prompt_confirm_async (GcrPrompt *prompt,
443 GCancellable *cancellable,
444 GAsyncReadyCallback callback,
445 gpointer user_data)
446 {
447 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
448 GObject *obj;
449
450 if (self->async_result != NULL) {
451 g_warning ("this prompt is already prompting");
452 return;
453 }
454
455 self->mode = PROMPTING_FOR_CONFIRM;
456 self->async_result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
457 shell_keyring_prompt_confirm_async);
458
459 obj = G_OBJECT (self);
460 g_object_notify (obj, "password-visible");
461 g_object_notify (obj, "confirm-visible");
462 g_object_notify (obj, "warning-visible");
463 g_object_notify (obj, "choice-visible");
464
465 self->shown = TRUE;
466 g_signal_emit (self, signals[SIGNAL_SHOW_CONFIRM], 0);
467 }
468
469 static GcrPromptReply
470 shell_keyring_prompt_confirm_finish (GcrPrompt *prompt,
471 GAsyncResult *result,
472 GError **error)
473 {
474 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
475
476 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (prompt),
477 shell_keyring_prompt_confirm_async), GCR_PROMPT_REPLY_CANCEL);
478
479 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
480 return GCR_PROMPT_REPLY_CANCEL;
481
482 return self->last_reply;
483 }
484
485 static void
486 shell_keyring_prompt_iface (GcrPromptIface *iface)
487 {
488 iface->prompt_password_async = shell_keyring_prompt_password_async;
489 iface->prompt_password_finish = shell_keyring_prompt_password_finish;
490 iface->prompt_confirm_async = shell_keyring_prompt_confirm_async;
491 iface->prompt_confirm_finish = shell_keyring_prompt_confirm_finish;
492 }
493
494 /**
495 * shell_keyring_prompt_new:
496 *
497 * Create new internal prompt base
498 *
499 * Returns: (transfer full): new internal prompt
500 */
501 ShellKeyringPrompt *
502 shell_keyring_prompt_new (void)
503 {
504 return g_object_new (SHELL_TYPE_KEYRING_PROMPT, NULL);
505 }
506
507 /**
508 * shell_keyring_prompt_get_password_actor:
509 * @self: the internal prompt
510 *
511 * Get the prompt password text actor
512 *
513 * Returns: (transfer none) (allow-none): the password actor
514 */
515 ClutterText *
516 shell_keyring_prompt_get_password_actor (ShellKeyringPrompt *self)
517 {
518 g_return_val_if_fail (SHELL_IS_KEYRING_PROMPT (self), NULL);
519 return self->password_actor;
520 }
521
522 /**
523 * shell_keyring_prompt_get_confirm_actor:
524 * @self: the internal prompt
525 *
526 * Get the prompt password text actor
527 *
528 * Returns: (transfer none) (allow-none): the password actor
529 */
530 ClutterText *
531 shell_keyring_prompt_get_confirm_actor (ShellKeyringPrompt *self)
532 {
533 g_return_val_if_fail (SHELL_IS_KEYRING_PROMPT (self), NULL);
534 return self->confirm_actor;
535 }
536
537 static guint
538 calculate_password_strength (const gchar *password)
539 {
540 int upper, lower, digit, misc;
541 gdouble pwstrength;
542 int length, i;
543
544 /*
545 * This code is based on the Master Password dialog in Firefox
546 * (pref-masterpass.js)
547 * Original code triple-licensed under the MPL, GPL, and LGPL
548 * so is license-compatible with this file
549 */
550
551 length = strlen (password);
552
553 /* Always return 0 for empty passwords */
554 if (length == 0)
555 return 0;
556
557 upper = 0;
558 lower = 0;
559 digit = 0;
560 misc = 0;
561
562 for (i = 0; i < length ; i++)
563 {
564 if (g_ascii_isdigit (password[i]))
565 digit++;
566 else if (g_ascii_islower (password[i]))
567 lower++;
568 else if (g_ascii_isupper (password[i]))
569 upper++;
570 else
571 misc++;
572 }
573
574 if (length > 5)
575 length = 5;
576 if (digit > 3)
577 digit = 3;
578 if (upper > 3)
579 upper = 3;
580 if (misc > 3)
581 misc = 3;
582
583 pwstrength = ((length * 1) - 2) +
584 (digit * 1) +
585 (misc * 1.5) +
586 (upper * 1);
587
588 /* Always return 1+ for non-empty passwords */
589 if (pwstrength < 1.0)
590 pwstrength = 1.0;
591 if (pwstrength > 10.0)
592 pwstrength = 10.0;
593
594 return (guint)pwstrength;
595 }
596
597 static void
598 on_password_changed (ClutterText *text,
599 gpointer user_data)
600 {
601 ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (user_data);
602 const gchar *password;
603
604 password = clutter_text_get_text (self->password_actor);
605
606 self->password_strength = calculate_password_strength (password);
607 g_object_notify (G_OBJECT (self), "password-strength");
608 }
609
610 /**
611 * shell_keyring_prompt_set_password_actor:
612 * @self: the internal prompt
613 * @password_actor: (allow-none): the password actor
614 *
615 * Set the prompt password text actor
616 */
617 void
618 shell_keyring_prompt_set_password_actor (ShellKeyringPrompt *self,
619 ClutterText *password_actor)
620 {
621 ClutterTextBuffer *buffer;
622
623 g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self));
624 g_return_if_fail (password_actor == NULL || CLUTTER_IS_TEXT (password_actor));
625
626 if (password_actor)
627 {
628 buffer = shell_secure_text_buffer_new ();
629 clutter_text_set_buffer (password_actor, buffer);
630 g_object_unref (buffer);
631
632 g_signal_connect (password_actor, "text-changed", G_CALLBACK (on_password_changed), self);
633 g_object_ref (password_actor);
634 }
635 if (self->password_actor)
636 {
637 g_signal_handlers_disconnect_by_func (self->password_actor, on_password_changed, self);
638 g_object_unref (self->password_actor);
639 }
640
641 self->password_actor = password_actor;
642 g_object_notify (G_OBJECT (self), "password-actor");
643 }
644
645 /**
646 * shell_keyring_prompt_set_confirm_actor:
647 * @self: the internal prompt
648 * @confirm_actor: (allow-none): the confirm password actor
649 *
650 * Set the prompt password confirmation text actor
651 */
652 void
653 shell_keyring_prompt_set_confirm_actor (ShellKeyringPrompt *self,
654 ClutterText *confirm_actor)
655 {
656 ClutterTextBuffer *buffer;
657
658 g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self));
659 g_return_if_fail (confirm_actor == NULL || CLUTTER_IS_TEXT (confirm_actor));
660
661 if (confirm_actor)
662 {
663 buffer = shell_secure_text_buffer_new ();
664 clutter_text_set_buffer (confirm_actor, buffer);
665 g_object_unref (buffer);
666
667 g_object_ref (confirm_actor);
668 }
669 if (self->confirm_actor)
670 g_object_unref (self->confirm_actor);
671 self->confirm_actor = confirm_actor;
672 g_object_notify (G_OBJECT (self), "confirm-actor");
673 }
674
675 /**
676 * shell_keyring_prompt_complete:
677 * @self: the internal prompt
678 *
679 * Called by the implementation when the prompt completes. There are various
680 * checks done. %TRUE is returned if the prompt actually should complete.
681 *
682 * Returns: whether the prompt completed
683 */
684 gboolean
685 shell_keyring_prompt_complete (ShellKeyringPrompt *self)
686 {
687 GSimpleAsyncResult *res;
688 const gchar *password;
689 const gchar *confirm;
690 const gchar *env;
691
692 g_return_val_if_fail (SHELL_IS_KEYRING_PROMPT (self), FALSE);
693 g_return_val_if_fail (self->mode != PROMPTING_NONE, FALSE);
694 g_return_val_if_fail (self->async_result != NULL, FALSE);
695
696 if (self->mode == PROMPTING_FOR_PASSWORD)
697 {
698 password = clutter_text_get_text (self->password_actor);
699
700 /* Is it a new password? */
701 if (self->password_new)
702 {
703 confirm = clutter_text_get_text (self->confirm_actor);
704
705 /* Do the passwords match? */
706 if (!g_str_equal (password, confirm))
707 {
708 gcr_prompt_set_warning (GCR_PROMPT (self), _("Passwords do not match."));
709 return FALSE;
710 }
711
712 /* Don't allow blank passwords if in paranoid mode */
713 env = g_getenv ("GNOME_KEYRING_PARANOID");
714 if (env && *env)
715 {
716 gcr_prompt_set_warning (GCR_PROMPT (self), _("Password cannot be blank"));
717 return FALSE;
718 }
719 }
720
721 self->password_strength = calculate_password_strength (password);
722 g_object_notify (G_OBJECT (self), "password-strength");
723 }
724
725 self->last_reply = GCR_PROMPT_REPLY_CONTINUE;
726
727 res = self->async_result;
728 self->async_result = NULL;
729 self->mode = PROMPTING_NONE;
730
731 g_simple_async_result_complete (res);
732 g_object_unref (res);
733
734 return TRUE;
735 }
736
737 /**
738 * shell_keyring_prompt_cancel:
739 * @self: the internal prompt
740 *
741 * Called by implementation when the prompt is cancelled.
742 */
743 void
744 shell_keyring_prompt_cancel (ShellKeyringPrompt *self)
745 {
746 GSimpleAsyncResult *res;
747
748 g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self));
749 g_return_if_fail (self->mode != PROMPTING_NONE);
750 g_return_if_fail (self->async_result != NULL);
751
752 self->last_reply = GCR_PROMPT_REPLY_CANCEL;
753
754 res = self->async_result;
755 self->async_result = NULL;
756 self->mode = PROMPTING_NONE;
757
758 g_simple_async_result_complete (res);
759 g_object_unref (res);
760 }