~ubuntu-branches/ubuntu/trusty/unity-control-center/trusty

« back to all changes in this revision

Viewing changes to panels/user-accounts/um-password-dialog.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-01-08 16:29:18 UTC
  • Revision ID: package-import@ubuntu.com-20140108162918-g29dd08tr913y2qh
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright 2009-2010  Red Hat, Inc,
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * Written by: Matthias Clasen <mclasen@redhat.com>
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <unistd.h>
 
25
#include <stdlib.h>
 
26
#include <sys/types.h>
 
27
#include <sys/wait.h>
 
28
 
 
29
#include <glib.h>
 
30
#include <glib/gi18n.h>
 
31
#include <gtk/gtk.h>
 
32
 
 
33
#include "um-password-dialog.h"
 
34
#include "um-user-manager.h"
 
35
#include "um-utils.h"
 
36
#include "run-passwd.h"
 
37
#include "pw-utils.h"
 
38
 
 
39
struct _UmPasswordDialog {
 
40
        GtkWidget *dialog;
 
41
        GtkWidget *user_icon;
 
42
        GtkWidget *user_name;
 
43
        GtkWidget *action_label;
 
44
        GtkWidget *action_combo;
 
45
        GtkWidget *password_entry;
 
46
        GtkWidget *verify_entry;
 
47
        GtkWidget *strength_indicator;
 
48
        GtkWidget *strength_indicator_label;
 
49
        GtkWidget *normal_hint_entry;
 
50
        GtkWidget *normal_hint_label;
 
51
        GtkWidget *show_password_button;
 
52
        GtkWidget *ok_button;
 
53
 
 
54
        UmUser *user;
 
55
        gboolean using_ecryptfs;
 
56
 
 
57
        GtkWidget *old_password_label;
 
58
        GtkWidget *old_password_entry;
 
59
        gboolean   old_password_ok;
 
60
 
 
61
        PasswdHandler *passwd_handler;
 
62
};
 
63
 
 
64
static void
 
65
generate_one_password (GtkWidget        *widget,
 
66
                       UmPasswordDialog *um)
 
67
{
 
68
        gchar *pwd;
 
69
 
 
70
        pwd = pw_generate ();
 
71
 
 
72
        gtk_entry_set_text (GTK_ENTRY (um->password_entry), pwd);
 
73
        gtk_entry_set_text (GTK_ENTRY (um->verify_entry), "");
 
74
 
 
75
 
 
76
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (um->show_password_button),
 
77
                                      TRUE);
 
78
 
 
79
        g_free (pwd);
 
80
}
 
81
 
 
82
static void
 
83
activate_icon (GtkEntry             *entry,
 
84
               GtkEntryIconPosition  pos,
 
85
               GdkEventButton       *event,
 
86
               UmPasswordDialog     *um)
 
87
{
 
88
        generate_one_password (GTK_WIDGET (entry), um);
 
89
}
 
90
 
 
91
static void
 
92
populate_menu (GtkEntry         *entry,
 
93
               GtkMenu          *menu,
 
94
               UmPasswordDialog *um)
 
95
{
 
96
        GtkWidget *item;
 
97
 
 
98
        item = gtk_menu_item_new_with_mnemonic (_("_Generate a password"));
 
99
        g_signal_connect (item, "activate",
 
100
                          G_CALLBACK (generate_one_password), um);
 
101
        gtk_widget_show (item);
 
102
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 
103
}
 
104
 
 
105
static void
 
106
finish_password_change (UmPasswordDialog *um)
 
107
{
 
108
        gtk_widget_hide (um->dialog);
 
109
 
 
110
        gtk_entry_set_text (GTK_ENTRY (um->password_entry), " ");
 
111
        gtk_entry_set_text (GTK_ENTRY (um->verify_entry), "");
 
112
        gtk_entry_set_text (GTK_ENTRY (um->normal_hint_entry), "");
 
113
        gtk_entry_set_text (GTK_ENTRY (um->old_password_entry), "");
 
114
 
 
115
        um_password_dialog_set_user (um, NULL);
 
116
}
 
117
 
 
118
static void
 
119
cancel_password_dialog (GtkButton        *button,
 
120
                        UmPasswordDialog *um)
 
121
{
 
122
        finish_password_change (um);
 
123
}
 
124
 
 
125
static void
 
126
dialog_closed (GtkWidget        *dialog,
 
127
               gint              response_id,
 
128
               UmPasswordDialog *um)
 
129
{
 
130
        gtk_widget_destroy (dialog);
 
131
}
 
132
 
 
133
static void
 
134
password_changed_cb (PasswdHandler    *handler,
 
135
                     GError           *error,
 
136
                     UmPasswordDialog *um)
 
137
{
 
138
        GtkWidget *dialog;
 
139
        const gchar *primary_text;
 
140
        const gchar *secondary_text;
 
141
 
 
142
        gtk_widget_set_sensitive (um->dialog, TRUE);
 
143
        gdk_window_set_cursor (gtk_widget_get_window (um->dialog), NULL);
 
144
 
 
145
        if (!error) {
 
146
                finish_password_change (um);
 
147
                return;
 
148
        }
 
149
 
 
150
        if (error->code == PASSWD_ERROR_REJECTED) {
 
151
                primary_text = error->message;
 
152
                secondary_text = _("Please choose another password.");
 
153
 
 
154
                gtk_entry_set_text (GTK_ENTRY (um->password_entry), "");
 
155
                gtk_widget_grab_focus (um->password_entry);
 
156
 
 
157
                gtk_entry_set_text (GTK_ENTRY (um->verify_entry), "");
 
158
        }
 
159
        else if (error->code == PASSWD_ERROR_AUTH_FAILED) {
 
160
                primary_text = error->message;
 
161
                secondary_text = _("Please type your current password again.");
 
162
 
 
163
                gtk_entry_set_text (GTK_ENTRY (um->old_password_entry), "");
 
164
                gtk_widget_grab_focus (um->old_password_entry);
 
165
        }
 
166
        else {
 
167
                primary_text = _("Password could not be changed");
 
168
                secondary_text = error->message;
 
169
        }
 
170
 
 
171
        dialog = gtk_message_dialog_new (GTK_WINDOW (um->dialog),
 
172
                                         GTK_DIALOG_MODAL,
 
173
                                         GTK_MESSAGE_ERROR,
 
174
                                         GTK_BUTTONS_CLOSE,
 
175
                                         "%s", primary_text);
 
176
        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 
177
                                                  "%s", secondary_text);
 
178
        g_signal_connect (dialog, "response",
 
179
                          G_CALLBACK (dialog_closed), um);
 
180
        gtk_window_present (GTK_WINDOW (dialog));
 
181
 
 
182
}
 
183
 
 
184
static void
 
185
accept_password_dialog (GtkButton        *button,
 
186
                        UmPasswordDialog *um)
 
187
{
 
188
        GtkTreeModel *model;
 
189
        GtkTreeIter iter;
 
190
        gint mode;
 
191
        const gchar *hint;
 
192
        const gchar *password;
 
193
 
 
194
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (um->action_combo));
 
195
        gtk_combo_box_get_active_iter (GTK_COMBO_BOX (um->action_combo), &iter);
 
196
        gtk_tree_model_get (model, &iter, 1, &mode, -1);
 
197
 
 
198
        password = gtk_entry_get_text (GTK_ENTRY (um->password_entry));
 
199
        hint = gtk_entry_get_text (GTK_ENTRY (um->normal_hint_entry));
 
200
 
 
201
        if (mode == 0 && um_user_get_uid (um->user) == getuid ()) {
 
202
                GdkDisplay *display;
 
203
                GdkCursor *cursor;
 
204
 
 
205
                /* When setting a password for the current user,
 
206
                 * use passwd directly, to preserve the audit trail
 
207
                 * and to e.g. update the keyring password.
 
208
                 */
 
209
                passwd_change_password (um->passwd_handler, password, (PasswdCallback) password_changed_cb, um);
 
210
                gtk_widget_set_sensitive (um->dialog, FALSE);
 
211
                display = gtk_widget_get_display (um->dialog);
 
212
                cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
 
213
                gdk_window_set_cursor (gtk_widget_get_window (um->dialog), cursor);
 
214
                gdk_display_flush (display);
 
215
                g_object_unref (cursor);
 
216
        }
 
217
        else {
 
218
                um_user_set_password (um->user, mode, password, hint);
 
219
                finish_password_change (um);
 
220
        }
 
221
}
 
222
 
 
223
static void
 
224
update_sensitivity (UmPasswordDialog *um)
 
225
{
 
226
        const gchar *password, *verify;
 
227
        const gchar *old_password;
 
228
        const gchar *tooltip;
 
229
        gboolean can_change;
 
230
 
 
231
        password = gtk_entry_get_text (GTK_ENTRY (um->password_entry));
 
232
        verify = gtk_entry_get_text (GTK_ENTRY (um->verify_entry));
 
233
        old_password = gtk_entry_get_text (GTK_ENTRY (um->old_password_entry));
 
234
 
 
235
        if (strlen (password) < pw_min_length ()) {
 
236
                can_change = FALSE;
 
237
                if (password[0] == '\0') {
 
238
                        tooltip = _("You need to enter a new password");
 
239
                }
 
240
                else {
 
241
                        tooltip = _("The new password is too short");
 
242
                }
 
243
        }
 
244
        else if (strcmp (password, verify) != 0) {
 
245
                can_change = FALSE;
 
246
                if (verify[0] == '\0') {
 
247
                        tooltip = _("You need to confirm the password");
 
248
                }
 
249
                else {
 
250
                        tooltip = _("The passwords do not match");
 
251
                }
 
252
        }
 
253
        else if (!um->old_password_ok) {
 
254
                can_change = FALSE;
 
255
                if (old_password[0] == '\0') {
 
256
                        tooltip = _("You need to enter your current password");
 
257
                }
 
258
                else {
 
259
                        tooltip = _("The current password is not correct");
 
260
                }
 
261
        }
 
262
        else {
 
263
                can_change = TRUE;
 
264
                tooltip = NULL;
 
265
        }
 
266
 
 
267
        gtk_widget_set_sensitive (um->ok_button, can_change);
 
268
        gtk_widget_set_tooltip_text (um->ok_button, tooltip);
 
269
}
 
270
 
 
271
static void
 
272
action_changed (GtkComboBox      *combo,
 
273
                UmPasswordDialog *um)
 
274
{
 
275
        gint active;
 
276
 
 
277
        active = gtk_combo_box_get_active (combo);
 
278
        if (active == 0) {
 
279
                gtk_widget_set_sensitive (um->password_entry, TRUE);
 
280
                gtk_entry_set_icon_sensitive (GTK_ENTRY (um->password_entry), GTK_ENTRY_ICON_SECONDARY, TRUE);
 
281
                gtk_widget_set_sensitive (um->verify_entry, TRUE);
 
282
                gtk_widget_set_sensitive (um->old_password_entry, TRUE);
 
283
                gtk_widget_set_sensitive (um->normal_hint_entry, TRUE);
 
284
                gtk_widget_set_sensitive (um->normal_hint_label, TRUE);
 
285
                gtk_widget_set_sensitive (um->strength_indicator_label, TRUE);
 
286
                gtk_widget_set_sensitive (um->show_password_button, TRUE);
 
287
 
 
288
                update_sensitivity (um);
 
289
        }
 
290
        else {
 
291
                gtk_widget_set_sensitive (um->password_entry, FALSE);
 
292
                gtk_entry_set_icon_sensitive (GTK_ENTRY (um->password_entry), GTK_ENTRY_ICON_SECONDARY, FALSE);
 
293
                gtk_widget_set_sensitive (um->verify_entry, FALSE);
 
294
                gtk_widget_set_sensitive (um->old_password_entry, FALSE);
 
295
                gtk_widget_set_sensitive (um->normal_hint_entry, FALSE);
 
296
                gtk_widget_set_sensitive (um->normal_hint_label, FALSE);
 
297
                gtk_widget_set_sensitive (um->strength_indicator_label, FALSE);
 
298
                gtk_widget_set_sensitive (um->show_password_button, FALSE);
 
299
                gtk_widget_set_sensitive (um->ok_button, TRUE);
 
300
        }
 
301
}
 
302
 
 
303
static void
 
304
show_password_toggled (GtkToggleButton  *button,
 
305
                       UmPasswordDialog *um)
 
306
{
 
307
        gboolean active;
 
308
 
 
309
        active = gtk_toggle_button_get_active (button);
 
310
        gtk_entry_set_visibility (GTK_ENTRY (um->password_entry), active);
 
311
        gtk_entry_set_visibility (GTK_ENTRY (um->verify_entry), active);
 
312
}
 
313
 
 
314
static void
 
315
update_password_strength (UmPasswordDialog *um)
 
316
{
 
317
        const gchar *password;
 
318
        const gchar *old_password;
 
319
        const gchar *username;
 
320
        gint strength_level;
 
321
        const gchar *hint;
 
322
        const gchar *long_hint;
 
323
 
 
324
        password = gtk_entry_get_text (GTK_ENTRY (um->password_entry));
 
325
        old_password = gtk_entry_get_text (GTK_ENTRY (um->old_password_entry));
 
326
        username = um_user_get_user_name (um->user);
 
327
 
 
328
        pw_strength (password, old_password, username,
 
329
                     &hint, &long_hint, &strength_level);
 
330
 
 
331
        gtk_level_bar_set_value (GTK_LEVEL_BAR (um->strength_indicator), strength_level);
 
332
        gtk_label_set_label (GTK_LABEL (um->strength_indicator_label), hint);
 
333
        gtk_widget_set_tooltip_text (um->strength_indicator, long_hint);
 
334
        gtk_widget_set_tooltip_text (um->strength_indicator_label, long_hint);
 
335
}
 
336
 
 
337
static void
 
338
update_password_match (UmPasswordDialog *um)
 
339
{
 
340
        const char *password;
 
341
        const char *verify;
 
342
 
 
343
        password = gtk_entry_get_text (GTK_ENTRY (um->password_entry));
 
344
        verify = gtk_entry_get_text (GTK_ENTRY (um->verify_entry));
 
345
 
 
346
        if (strlen (password) > 0 && strlen (verify) > 0) {
 
347
                if (strcmp (password, verify) != 0) {
 
348
                        set_entry_validation_error (GTK_ENTRY (um->verify_entry),
 
349
                                                    _("Passwords do not match"));
 
350
                }
 
351
                else {
 
352
                        clear_entry_validation_error (GTK_ENTRY (um->verify_entry));
 
353
                }
 
354
        }
 
355
}
 
356
 
 
357
static void
 
358
password_entry_changed (GtkEntry         *entry,
 
359
                        GParamSpec       *pspec,
 
360
                        UmPasswordDialog *um)
 
361
{
 
362
        update_password_strength (um);
 
363
        update_sensitivity (um);
 
364
        update_password_match (um);
 
365
}
 
366
 
 
367
static gboolean
 
368
password_entry_focus_out (GtkWidget        *entry,
 
369
                          GdkEventFocus    *event,
 
370
                          UmPasswordDialog *um)
 
371
{
 
372
        update_password_match (um);
 
373
        return FALSE;
 
374
}
 
375
 
 
376
static void
 
377
verify_entry_changed (GtkEntry         *entry,
 
378
                      GParamSpec       *pspec,
 
379
                      UmPasswordDialog *um)
 
380
{
 
381
        clear_entry_validation_error (GTK_ENTRY (entry));
 
382
        update_password_strength (um);
 
383
        update_sensitivity (um);
 
384
}
 
385
 
 
386
static gboolean
 
387
verify_entry_focus_out (GtkWidget        *entry,
 
388
                        GdkEventFocus    *event,
 
389
                        UmPasswordDialog *um)
 
390
{
 
391
        update_password_match (um);
 
392
        return FALSE;
 
393
}
 
394
 
 
395
static void
 
396
entry_size_changed (GtkWidget     *entry,
 
397
                    GtkAllocation *allocation,
 
398
                    GtkWidget     *label)
 
399
{
 
400
        gtk_widget_set_size_request (label, allocation->width, -1);
 
401
}
 
402
 
 
403
static void
 
404
auth_cb (PasswdHandler    *handler,
 
405
         GError           *error,
 
406
         UmPasswordDialog *um)
 
407
{
 
408
        if (error) {
 
409
                um->old_password_ok = FALSE;
 
410
                set_entry_validation_error (GTK_ENTRY (um->old_password_entry),
 
411
                                            _("Wrong password"));
 
412
        }
 
413
        else {
 
414
                um->old_password_ok = TRUE;
 
415
                clear_entry_validation_error (GTK_ENTRY (um->old_password_entry));
 
416
        }
 
417
 
 
418
        update_sensitivity (um);
 
419
}
 
420
 
 
421
static gboolean
 
422
old_password_entry_focus_out (GtkWidget        *entry,
 
423
                              GdkEventFocus    *event,
 
424
                              UmPasswordDialog *um)
 
425
{
 
426
        const char *text;
 
427
 
 
428
        text = gtk_entry_get_text (GTK_ENTRY (entry));
 
429
        if (strlen (text) > 0) {
 
430
                passwd_authenticate (um->passwd_handler, text,
 
431
                                     (PasswdCallback)auth_cb, um);
 
432
        }
 
433
 
 
434
        return FALSE;
 
435
}
 
436
 
 
437
static void
 
438
old_password_entry_activate (GtkWidget        *entry,
 
439
                             UmPasswordDialog *um)
 
440
{
 
441
        const char *text;
 
442
 
 
443
        text = gtk_entry_get_text (GTK_ENTRY (entry));
 
444
        if (strlen (text) > 0) {
 
445
                passwd_authenticate (um->passwd_handler, text,
 
446
                                     (PasswdCallback)auth_cb, um);
 
447
        }
 
448
}
 
449
 
 
450
 
 
451
static void
 
452
old_password_entry_changed (GtkEntry         *entry,
 
453
                            GParamSpec       *pspec,
 
454
                            UmPasswordDialog *um)
 
455
{
 
456
        clear_entry_validation_error (GTK_ENTRY (entry));
 
457
        um->old_password_ok = FALSE;
 
458
        update_sensitivity (um);
 
459
}
 
460
 
 
461
void
 
462
um_password_dialog_set_privileged (UmPasswordDialog *um,
 
463
                                   gboolean          privileged)
 
464
{
 
465
        if (privileged) {
 
466
                gtk_widget_set_visible (um->action_label, TRUE);
 
467
                gtk_widget_set_visible (um->action_combo, TRUE);
 
468
        }
 
469
        else {
 
470
                gtk_combo_box_set_active (GTK_COMBO_BOX (um->action_combo), 0);
 
471
                gtk_widget_set_visible (um->action_label, FALSE);
 
472
                gtk_widget_set_visible (um->action_combo, FALSE);
 
473
        }
 
474
}
 
475
 
 
476
int _is_gdm_running = -1;
 
477
gboolean
 
478
is_gdm_running (void)
 
479
{
 
480
        if (_is_gdm_running == -1) {
 
481
                GDBusProxy *proxy;
 
482
                gchar *owner_name;
 
483
 
 
484
                proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
 
485
                                                       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
 
486
                                                       G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
 
487
                                                       G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
 
488
                                                       NULL,
 
489
                                                       "org.gnome.DisplayManager",
 
490
                                                       "/org/gnome/DisplayManager/Manager",
 
491
                                                       "org.gnome.DisplayManager.Manager",
 
492
                                                       NULL, NULL);
 
493
 
 
494
                if (proxy == NULL)
 
495
                        return FALSE;
 
496
 
 
497
                owner_name = g_dbus_proxy_get_name_owner (proxy);
 
498
 
 
499
                g_object_unref (proxy);
 
500
                g_free (owner_name);
 
501
 
 
502
                _is_gdm_running = (owner_name != NULL) ? 1 : 0;
 
503
        }
 
504
 
 
505
        return _is_gdm_running;
 
506
}
 
507
 
 
508
UmPasswordDialog *
 
509
um_password_dialog_new (void)
 
510
{
 
511
        GtkBuilder *builder;
 
512
        GError *error;
 
513
        const gchar *filename;
 
514
        UmPasswordDialog *um;
 
515
        GtkWidget *widget;
 
516
        const char *old_label;
 
517
        char *label;
 
518
        gint len;
 
519
 
 
520
        builder = gtk_builder_new ();
 
521
 
 
522
        error = NULL;
 
523
        filename = UIDIR "/password-dialog.ui";
 
524
        if (!g_file_test (filename, G_FILE_TEST_EXISTS))
 
525
                filename = "data/password-dialog.ui";
 
526
        if (!gtk_builder_add_from_file (builder, filename, &error)) {
 
527
                g_error ("%s", error->message);
 
528
                g_error_free (error);
 
529
                return NULL;
 
530
        }
 
531
 
 
532
        um = g_new0 (UmPasswordDialog, 1);
 
533
 
 
534
        um->action_label = (GtkWidget *) gtk_builder_get_object (builder, "action-label");
 
535
        widget = (GtkWidget *) gtk_builder_get_object (builder, "action-combo");
 
536
        g_signal_connect (widget, "changed",
 
537
                          G_CALLBACK (action_changed), um);
 
538
        um->action_combo = widget;
 
539
 
 
540
        widget = (GtkWidget *) gtk_builder_get_object (builder, "dialog");
 
541
        g_signal_connect (widget, "delete-event",
 
542
                          G_CALLBACK (gtk_widget_hide_on_delete), NULL);
 
543
        um->dialog = widget;
 
544
 
 
545
        um->user_icon = (GtkWidget *) gtk_builder_get_object (builder, "user-icon");
 
546
        um->user_name = (GtkWidget *) gtk_builder_get_object (builder, "user-name");
 
547
 
 
548
        widget = (GtkWidget *) gtk_builder_get_object (builder, "cancel-button");
 
549
        g_signal_connect (widget, "clicked",
 
550
                          G_CALLBACK (cancel_password_dialog), um);
 
551
 
 
552
        widget = (GtkWidget *) gtk_builder_get_object (builder, "ok-button");
 
553
        g_signal_connect (widget, "clicked",
 
554
                          G_CALLBACK (accept_password_dialog), um);
 
555
        gtk_widget_grab_default (widget);
 
556
        um->ok_button = widget;
 
557
 
 
558
        widget = (GtkWidget *) gtk_builder_get_object (builder, "password-normal-strength-hints-label");
 
559
        old_label = gtk_label_get_label (GTK_LABEL (widget));
 
560
        if (!g_strcmp0(g_getenv("XDG_CURRENT_DESKTOP"), "Unity"))
 
561
            label = g_strdup_printf ("<a href=\"%s\">%s</a>",
 
562
                                 "help:ubuntu-help/user-goodpassword",
 
563
                                  old_label);
 
564
        else
 
565
            label = g_strdup_printf ("<a href=\"%s\">%s</a>",
 
566
                                  "help:gnome-help/user-goodpassword",
 
567
                                  old_label);
 
568
        gtk_label_set_markup (GTK_LABEL (widget), label);
 
569
        g_free (label);
 
570
 
 
571
        widget = (GtkWidget *) gtk_builder_get_object (builder, "show-password-checkbutton");
 
572
        g_signal_connect (widget, "toggled",
 
573
                          G_CALLBACK (show_password_toggled), um);
 
574
        um->show_password_button = widget;
 
575
 
 
576
        widget = (GtkWidget *) gtk_builder_get_object (builder, "password-entry");
 
577
        g_signal_connect (widget, "notify::text",
 
578
                          G_CALLBACK (password_entry_changed), um);
 
579
        g_signal_connect_after (widget, "focus-out-event",
 
580
                                G_CALLBACK (password_entry_focus_out), um);
 
581
        gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE);
 
582
 
 
583
        g_signal_connect (widget, "icon-press",
 
584
                          G_CALLBACK (activate_icon), um);
 
585
        g_signal_connect (widget, "populate-popup",
 
586
                          G_CALLBACK (populate_menu), um);
 
587
 
 
588
        um->password_entry = widget;
 
589
 
 
590
        widget = (GtkWidget *) gtk_builder_get_object (builder, "old-password-entry");
 
591
        g_signal_connect_after (widget, "focus-out-event",
 
592
                                G_CALLBACK (old_password_entry_focus_out), um);
 
593
        g_signal_connect (widget, "notify::text",
 
594
                          G_CALLBACK (old_password_entry_changed), um);
 
595
        g_signal_connect (widget, "activate",
 
596
                          G_CALLBACK (old_password_entry_activate), um);
 
597
        um->old_password_entry = widget;
 
598
        um->old_password_label = (GtkWidget *) gtk_builder_get_object (builder, "old-password-label");
 
599
 
 
600
        widget = (GtkWidget *) gtk_builder_get_object (builder, "verify-entry");
 
601
        g_signal_connect (widget, "notify::text",
 
602
                          G_CALLBACK (verify_entry_changed), um);
 
603
        g_signal_connect_after (widget, "focus-out-event",
 
604
                                G_CALLBACK (verify_entry_focus_out), um);
 
605
        um->verify_entry = widget;
 
606
 
 
607
        len = 0;
 
608
        len = MAX (len, strlen (C_("Password strength", "Too short")));
 
609
        len = MAX (len, strlen (C_("Password strength", "Weak")));
 
610
        len = MAX (len, strlen (C_("Password strength", "Fair")));
 
611
        len = MAX (len, strlen (C_("Password strength", "Good")));
 
612
        len = MAX (len, strlen (C_("Password strength", "Strong")));
 
613
        len += 2;
 
614
 
 
615
        widget = (GtkWidget *) gtk_builder_get_object (builder, "strength-indicator-label");
 
616
        gtk_label_set_width_chars (GTK_LABEL (widget), len);
 
617
 
 
618
        um->normal_hint_entry = (GtkWidget *) gtk_builder_get_object (builder, "normal-hint-entry");
 
619
 
 
620
        /* Label size hack.
 
621
         * This only sort-of works because the dialog is non-resizable.
 
622
         */
 
623
        widget = (GtkWidget *)gtk_builder_get_object (builder, "password-normal-hint-description-label");
 
624
        g_signal_connect (um->normal_hint_entry, "size-allocate",
 
625
                          G_CALLBACK (entry_size_changed), widget);
 
626
        um->normal_hint_label = widget;
 
627
 
 
628
        if (!is_gdm_running ()) {
 
629
                widget = (GtkWidget *) gtk_builder_get_object (builder, "password-normal-hint-label");
 
630
                gtk_widget_hide (widget);
 
631
                gtk_widget_hide (um->normal_hint_entry);
 
632
                gtk_widget_hide (um->normal_hint_label);
 
633
        }
 
634
 
 
635
        um->strength_indicator = (GtkWidget *) gtk_builder_get_object (builder, "strength-indicator");
 
636
 
 
637
        um->strength_indicator_label = (GtkWidget *) gtk_builder_get_object (builder, "strength-indicator-label");
 
638
 
 
639
        g_object_unref (builder);
 
640
 
 
641
        return um;
 
642
}
 
643
 
 
644
void
 
645
um_password_dialog_free (UmPasswordDialog *um)
 
646
{
 
647
        gtk_widget_destroy (um->dialog);
 
648
 
 
649
        if (um->user)
 
650
                g_object_unref (um->user);
 
651
 
 
652
        if (um->passwd_handler)
 
653
                passwd_destroy (um->passwd_handler);
 
654
 
 
655
        g_free (um);
 
656
}
 
657
 
 
658
static gboolean
 
659
visible_func (GtkTreeModel     *model,
 
660
              GtkTreeIter      *iter,
 
661
              UmPasswordDialog *um)
 
662
{
 
663
        if (um->user) {
 
664
                gint mode; 
 
665
                gboolean locked = um_user_get_locked (um->user);
 
666
 
 
667
                gtk_tree_model_get (model, iter, 1, &mode, -1);
 
668
 
 
669
                if (mode == 1 && !is_gdm_running ())
 
670
                        return FALSE;
 
671
 
 
672
                if (mode == 2 && um->using_ecryptfs)
 
673
                        return FALSE;
 
674
 
 
675
                if (mode == 3 && locked)
 
676
                        return FALSE;
 
677
 
 
678
                if (mode == 4 && !locked)
 
679
                        return FALSE;
 
680
 
 
681
                return TRUE;
 
682
        }
 
683
 
 
684
        return TRUE;
 
685
}
 
686
 
 
687
void
 
688
um_password_dialog_set_user (UmPasswordDialog *um,
 
689
                             UmUser           *user)
 
690
{
 
691
        GdkPixbuf *pixbuf;
 
692
        GtkTreeModel *model;
 
693
 
 
694
        if (um->user) {
 
695
                g_object_unref (um->user);
 
696
                um->user = NULL;
 
697
        }
 
698
        if (user) {
 
699
                um->user = g_object_ref (user);
 
700
 
 
701
                um->using_ecryptfs = is_using_ecryptfs (um_user_get_user_name (user));
 
702
 
 
703
                pixbuf = um_user_render_icon (user, FALSE, 48);
 
704
                gtk_image_set_from_pixbuf (GTK_IMAGE (um->user_icon), pixbuf);
 
705
                g_object_unref (pixbuf);
 
706
 
 
707
                gtk_label_set_label (GTK_LABEL (um->user_name),
 
708
                                     um_user_get_real_name (user));
 
709
 
 
710
                gtk_entry_set_text (GTK_ENTRY (um->password_entry), "");
 
711
                gtk_entry_set_text (GTK_ENTRY (um->verify_entry), "");
 
712
                gtk_entry_set_text (GTK_ENTRY (um->normal_hint_entry), "");
 
713
                gtk_entry_set_text (GTK_ENTRY (um->old_password_entry), "");
 
714
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (um->show_password_button), FALSE);
 
715
                if (um_user_get_uid (um->user) == getuid () &&
 
716
                    um_user_get_password_mode (um->user) == UM_PASSWORD_MODE_REGULAR) {
 
717
                        gtk_widget_show (um->old_password_label);
 
718
                        gtk_widget_show (um->old_password_entry);
 
719
                        um->old_password_ok = FALSE;
 
720
                }
 
721
                else {
 
722
                        gtk_widget_hide (um->old_password_label);
 
723
                        gtk_widget_hide (um->old_password_entry);
 
724
                        um->old_password_ok = TRUE;
 
725
                }
 
726
                if (um_user_get_uid (um->user) == getuid()) {
 
727
                        if (um->passwd_handler != NULL)
 
728
                                passwd_destroy (um->passwd_handler);
 
729
                        um->passwd_handler = passwd_init ();
 
730
                }
 
731
        }
 
732
 
 
733
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (um->action_combo));
 
734
        if (!GTK_IS_TREE_MODEL_FILTER (model)) {
 
735
                model = gtk_tree_model_filter_new (model, NULL);
 
736
                gtk_combo_box_set_model (GTK_COMBO_BOX (um->action_combo), model);
 
737
                gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
 
738
                                                        (GtkTreeModelFilterVisibleFunc) visible_func,
 
739
                                                        um, NULL);
 
740
        }
 
741
 
 
742
        gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
 
743
        gtk_combo_box_set_active (GTK_COMBO_BOX (um->action_combo), 0);
 
744
}
 
745
 
 
746
void
 
747
um_password_dialog_show (UmPasswordDialog *um,
 
748
                         GtkWindow        *parent)
 
749
{
 
750
        gtk_window_set_transient_for (GTK_WINDOW (um->dialog), parent);
 
751
        gtk_window_present (GTK_WINDOW (um->dialog));
 
752
        if (um->old_password_ok == FALSE)
 
753
                gtk_widget_grab_focus (um->old_password_entry);
 
754
        else
 
755
                gtk_widget_grab_focus (um->password_entry);
 
756
}
 
757