2
* Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
4
* This library is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published by
6
* the Free Software Foundation.
8
* This library is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this library. If not, see <http://www.gnu.org/licenses/>.
23
#include <glib/gi18n-lib.h>
27
#include <libedataserver/libedataserver.h>
29
#include "e-credentials-prompter.h"
30
#include "e-credentials-prompter-impl-password.h"
32
struct _ECredentialsPrompterImplPasswordPrivate {
37
ENamedParameters *credentials;
40
gulong show_dialog_idle_id;
43
G_DEFINE_TYPE (ECredentialsPrompterImplPassword, e_credentials_prompter_impl_password, E_TYPE_CREDENTIALS_PROMPTER_IMPL)
46
password_dialog_map_event_cb (GtkWidget *dialog,
48
GtkWidget *password_entry)
50
gtk_widget_grab_focus (password_entry);
56
credentials_prompter_impl_password_get_prompt_strings (ESource *source,
58
GString **prompt_description)
63
gchar *host_name = NULL;
75
} type = TYPE_UNKNOWN;
77
/* XXX This is kind of a hack but it should work for now. Build a
78
* suitable password prompt by checking for various extensions
79
* in the ESource. If no recognizable extensions are found, or
80
* if the result is ambiguous, just refer to the data source as
83
display_name = e_source_dup_display_name (source);
85
if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
86
ESourceAuthentication *extension;
88
extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
89
host_name = e_source_authentication_dup_host (extension);
92
if (e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK)) {
93
type = TYPE_ADDRESS_BOOK;
96
if (e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR)) {
97
if (type == TYPE_UNKNOWN)
100
type = TYPE_AMBIGUOUS;
103
if (e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_ACCOUNT)) {
104
if (type == TYPE_UNKNOWN)
105
type = TYPE_MAIL_ACCOUNT;
107
type = TYPE_AMBIGUOUS;
110
if (e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_TRANSPORT)) {
111
if (type == TYPE_UNKNOWN)
112
type = TYPE_MAIL_TRANSPORT;
114
type = TYPE_AMBIGUOUS;
117
if (e_source_has_extension (source, E_SOURCE_EXTENSION_MEMO_LIST)) {
118
if (type == TYPE_UNKNOWN)
119
type = TYPE_MEMO_LIST;
121
type = TYPE_AMBIGUOUS;
124
if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST)) {
125
if (type == TYPE_UNKNOWN)
126
type = TYPE_TASK_LIST;
128
type = TYPE_AMBIGUOUS;
132
case TYPE_ADDRESS_BOOK:
133
message = _("Address book authentication request");
138
message = _("Calendar authentication request");
140
case TYPE_MAIL_ACCOUNT:
141
case TYPE_MAIL_TRANSPORT:
142
message = _("Mail authentication request");
144
default: /* generic account prompt */
145
message = _("Authentication request");
149
description = g_string_sized_new (256);
151
g_string_append_printf (description, "<big><b>%s</b></big>\n\n", message);
154
case TYPE_ADDRESS_BOOK:
155
g_string_append_printf (description,
156
_("Please enter the password for address book \"%s\"."), display_name);
159
g_string_append_printf (description,
160
_("Please enter the password for calendar \"%s\"."), display_name);
162
case TYPE_MAIL_ACCOUNT:
163
g_string_append_printf (description,
164
_("Please enter the password for mail account \"%s\"."), display_name);
166
case TYPE_MAIL_TRANSPORT:
167
g_string_append_printf (description,
168
_("Please enter the password for mail transport \"%s\"."), display_name);
171
g_string_append_printf (description,
172
_("Please enter the password for memo list \"%s\"."), display_name);
175
g_string_append_printf (description,
176
_("Please enter the password for task list \"%s\"."), display_name);
178
default: /* generic account prompt */
179
g_string_append_printf (description,
180
_("Please enter the password for account \"%s\"."), display_name);
184
if (host_name != NULL)
185
g_string_append_printf (
186
description, "\n(host: %s)", host_name);
188
*prompt_title = g_strdup (message);
189
*prompt_description = description;
191
g_free (display_name);
196
e_credentials_prompter_impl_password_show_dialog (ECredentialsPrompterImplPassword *prompter_password)
198
GtkWidget *dialog, *content_area, *widget;
200
GtkEntry *username_entry = NULL;
201
GtkEntry *password_entry;
202
GtkToggleButton *remember_toggle = NULL;
203
GtkWindow *dialog_parent;
204
ECredentialsPrompter *prompter;
206
GString *info_markup;
208
ESourceAuthentication *auth_extension = NULL;
211
g_return_val_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_PASSWORD (prompter_password), FALSE);
212
g_return_val_if_fail (prompter_password->priv->prompt_id != NULL, FALSE);
213
g_return_val_if_fail (prompter_password->priv->dialog == NULL, FALSE);
215
prompter = e_credentials_prompter_impl_get_credentials_prompter (E_CREDENTIALS_PROMPTER_IMPL (prompter_password));
216
g_return_val_if_fail (prompter != NULL, FALSE);
218
dialog_parent = e_credentials_prompter_get_dialog_parent (prompter);
220
credentials_prompter_impl_password_get_prompt_strings (prompter_password->priv->auth_source, &title, &info_markup);
221
if (prompter_password->priv->error_text && *prompter_password->priv->error_text) {
222
gchar *escaped = g_markup_printf_escaped ("%s", prompter_password->priv->error_text);
224
g_string_append_printf (info_markup, "\n\n%s", escaped);
228
dialog = gtk_dialog_new_with_buttons (title, dialog_parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
229
_("_Cancel"), GTK_RESPONSE_CANCEL,
230
_("_OK"), GTK_RESPONSE_OK,
233
prompter_password->priv->dialog = GTK_DIALOG (dialog);
234
gtk_dialog_set_default_response (prompter_password->priv->dialog, GTK_RESPONSE_OK);
235
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
237
gtk_window_set_transient_for (GTK_WINDOW (dialog), dialog_parent);
238
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
239
gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
241
widget = gtk_dialog_get_action_area (prompter_password->priv->dialog);
242
content_area = gtk_dialog_get_content_area (prompter_password->priv->dialog);
244
/* Override GtkDialog defaults */
245
gtk_box_set_spacing (GTK_BOX (widget), 12);
246
gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
247
gtk_box_set_spacing (GTK_BOX (content_area), 12);
248
gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
250
grid = GTK_GRID (gtk_grid_new ());
251
gtk_grid_set_column_spacing (grid, 12);
252
gtk_grid_set_row_spacing (grid, 6);
254
gtk_box_pack_start (GTK_BOX (content_area), GTK_WIDGET (grid), FALSE, TRUE, 0);
257
widget = gtk_image_new_from_icon_name ("dialog-password", GTK_ICON_SIZE_DIALOG);
260
"halign", GTK_ALIGN_START,
262
"valign", GTK_ALIGN_START,
265
gtk_grid_attach (grid, widget, 0, row, 1, 1);
268
widget = gtk_label_new (NULL);
269
gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
270
gtk_label_set_markup (GTK_LABEL (widget), info_markup->str);
274
"halign", GTK_ALIGN_FILL,
275
"valign", GTK_ALIGN_CENTER,
277
"max-width-chars", 80,
281
gtk_grid_attach (grid, widget, 1, row, 1, 1);
284
if (e_source_has_extension (prompter_password->priv->cred_source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
285
auth_extension = e_source_get_extension (prompter_password->priv->cred_source, E_SOURCE_EXTENSION_AUTHENTICATION);
287
if (e_source_get_writable (prompter_password->priv->cred_source)) {
290
username = e_source_authentication_dup_user (auth_extension);
291
if ((!username || !*username) &&
292
e_source_has_extension (prompter_password->priv->cred_source, E_SOURCE_EXTENSION_COLLECTION)) {
293
ESourceCollection *collection_extension;
296
collection_extension = e_source_get_extension (prompter_password->priv->cred_source, E_SOURCE_EXTENSION_COLLECTION);
298
tmp = e_source_collection_dup_identity (collection_extension);
308
username_entry = GTK_ENTRY (gtk_entry_new ());
310
G_OBJECT (username_entry),
312
"halign", GTK_ALIGN_FILL,
315
gtk_grid_attach (grid, GTK_WIDGET (username_entry), 1, row, 1, 1);
318
if (username && *username) {
319
gtk_entry_set_text (username_entry, username);
326
password_entry = GTK_ENTRY (gtk_entry_new ());
327
gtk_entry_set_visibility (password_entry, FALSE);
328
gtk_entry_set_activates_default (password_entry, TRUE);
330
G_OBJECT (password_entry),
332
"halign", GTK_ALIGN_FILL,
334
if (e_named_parameters_get (prompter_password->priv->credentials, E_SOURCE_CREDENTIAL_PASSWORD))
335
gtk_entry_set_text (password_entry, e_named_parameters_get (prompter_password->priv->credentials, E_SOURCE_CREDENTIAL_PASSWORD));
337
g_signal_connect (dialog, "map-event", G_CALLBACK (password_dialog_map_event_cb), password_entry);
339
gtk_grid_attach (grid, GTK_WIDGET (password_entry), 1, row, 1, 1);
342
if (username_entry && password_entry) {
343
widget = gtk_label_new_with_mnemonic (_("_User Name:"));
348
"halign", GTK_ALIGN_END,
349
"valign", GTK_ALIGN_CENTER,
352
gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (username_entry));
353
gtk_grid_attach (grid, widget, 0, row - 2, 1, 1);
355
widget = gtk_label_new_with_mnemonic (_("_Password:"));
360
"halign", GTK_ALIGN_END,
361
"valign", GTK_ALIGN_CENTER,
364
gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (password_entry));
366
gtk_grid_attach (grid, widget, 0, row - 1, 1, 1);
369
if (auth_extension) {
370
/* Remember password check */
371
widget = gtk_check_button_new_with_mnemonic (_("_Add this password to your keyring"));
372
remember_toggle = GTK_TOGGLE_BUTTON (widget);
373
gtk_toggle_button_set_active (remember_toggle, e_source_authentication_get_remember_password (auth_extension));
377
"halign", GTK_ALIGN_FILL,
378
"valign", GTK_ALIGN_FILL,
382
gtk_grid_attach (grid, widget, 1, row, 1, 1);
385
gtk_widget_show_all (GTK_WIDGET (grid));
387
success = gtk_dialog_run (prompter_password->priv->dialog) == GTK_RESPONSE_OK;
391
e_named_parameters_set (prompter_password->priv->credentials,
392
E_SOURCE_CREDENTIAL_USERNAME, gtk_entry_get_text (username_entry));
393
e_named_parameters_set (prompter_password->priv->credentials,
394
E_SOURCE_CREDENTIAL_PASSWORD, gtk_entry_get_text (password_entry));
396
if (auth_extension && remember_toggle) {
397
e_source_authentication_set_remember_password (auth_extension,
398
gtk_toggle_button_get_active (remember_toggle));
402
gtk_widget_destroy (dialog);
403
prompter_password->priv->dialog = NULL;
405
g_string_free (info_markup, TRUE);
412
e_credentials_prompter_impl_password_free_prompt_data (ECredentialsPrompterImplPassword *prompter_password)
414
g_return_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_PASSWORD (prompter_password));
416
prompter_password->priv->prompt_id = NULL;
418
g_clear_object (&prompter_password->priv->auth_source);
419
g_clear_object (&prompter_password->priv->cred_source);
421
g_free (prompter_password->priv->error_text);
422
prompter_password->priv->error_text = NULL;
424
e_named_parameters_free (prompter_password->priv->credentials);
425
prompter_password->priv->credentials = NULL;
429
e_credentials_prompter_impl_password_show_dialog_idle_cb (gpointer user_data)
431
ECredentialsPrompterImplPassword *prompter_password = user_data;
433
if (g_source_is_destroyed (g_main_current_source ()))
436
g_return_val_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_PASSWORD (prompter_password), FALSE);
438
if (g_source_get_id (g_main_current_source ()) == prompter_password->priv->show_dialog_idle_id) {
441
prompter_password->priv->show_dialog_idle_id = 0;
443
g_warn_if_fail (prompter_password->priv->dialog == NULL);
445
success = e_credentials_prompter_impl_password_show_dialog (prompter_password);
447
e_credentials_prompter_impl_prompt_finish (
448
E_CREDENTIALS_PROMPTER_IMPL (prompter_password),
449
prompter_password->priv->prompt_id,
450
success ? prompter_password->priv->credentials : NULL);
452
e_credentials_prompter_impl_password_free_prompt_data (prompter_password);
459
e_credentials_prompter_impl_password_process_prompt (ECredentialsPrompterImpl *prompter_impl,
461
ESource *auth_source,
462
ESource *cred_source,
463
const gchar *error_text,
464
const ENamedParameters *credentials)
466
ECredentialsPrompterImplPassword *prompter_password;
468
g_return_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_PASSWORD (prompter_impl));
470
prompter_password = E_CREDENTIALS_PROMPTER_IMPL_PASSWORD (prompter_impl);
471
g_return_if_fail (prompter_password->priv->prompt_id == NULL);
472
g_return_if_fail (prompter_password->priv->show_dialog_idle_id == 0);
474
prompter_password->priv->prompt_id = prompt_id;
475
prompter_password->priv->auth_source = g_object_ref (auth_source);
476
prompter_password->priv->cred_source = g_object_ref (cred_source);
477
prompter_password->priv->error_text = g_strdup (error_text);
478
prompter_password->priv->credentials = e_named_parameters_new_clone (credentials);
479
prompter_password->priv->show_dialog_idle_id = g_idle_add (
480
e_credentials_prompter_impl_password_show_dialog_idle_cb,
485
e_credentials_prompter_impl_password_cancel_prompt (ECredentialsPrompterImpl *prompter_impl,
488
ECredentialsPrompterImplPassword *prompter_password;
490
g_return_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_PASSWORD (prompter_impl));
492
prompter_password = E_CREDENTIALS_PROMPTER_IMPL_PASSWORD (prompter_impl);
493
g_return_if_fail (prompter_password->priv->prompt_id == prompt_id);
495
/* This also closes the dialog. */
496
gtk_dialog_response (prompter_password->priv->dialog, GTK_RESPONSE_CANCEL);
500
e_credentials_prompter_impl_password_dispose (GObject *object)
502
ECredentialsPrompterImplPassword *prompter_password = E_CREDENTIALS_PROMPTER_IMPL_PASSWORD (object);
504
if (prompter_password->priv->show_dialog_idle_id) {
505
g_source_remove (prompter_password->priv->show_dialog_idle_id);
506
prompter_password->priv->show_dialog_idle_id = 0;
509
g_warn_if_fail (prompter_password->priv->prompt_id == NULL);
510
g_warn_if_fail (prompter_password->priv->dialog == NULL);
512
e_credentials_prompter_impl_password_free_prompt_data (prompter_password);
514
/* Chain up to parent's method. */
515
G_OBJECT_CLASS (e_credentials_prompter_impl_password_parent_class)->dispose (object);
519
e_credentials_prompter_impl_password_class_init (ECredentialsPrompterImplPasswordClass *class)
521
static const gchar *authentication_methods[] = {
522
"", /* register as the default credentials prompter */
526
GObjectClass *object_class;
527
ECredentialsPrompterImplClass *prompter_impl_class;
529
g_type_class_add_private (class, sizeof (ECredentialsPrompterImplPasswordPrivate));
531
object_class = G_OBJECT_CLASS (class);
532
object_class->dispose = e_credentials_prompter_impl_password_dispose;
534
prompter_impl_class = E_CREDENTIALS_PROMPTER_IMPL_CLASS (class);
535
prompter_impl_class->authentication_methods = (const gchar * const *) authentication_methods;
536
prompter_impl_class->process_prompt = e_credentials_prompter_impl_password_process_prompt;
537
prompter_impl_class->cancel_prompt = e_credentials_prompter_impl_password_cancel_prompt;
541
e_credentials_prompter_impl_password_init (ECredentialsPrompterImplPassword *prompter_password)
543
prompter_password->priv = G_TYPE_INSTANCE_GET_PRIVATE (prompter_password,
544
E_TYPE_CREDENTIALS_PROMPTER_IMPL_PASSWORD, ECredentialsPrompterImplPasswordPrivate);
548
* e_credentials_prompter_impl_password_new:
550
* Creates a new instance of an #ECredentialsPrompterImplPassword.
552
* Returns: (transfer full): a newly created #ECredentialsPrompterImplPassword,
553
* which should be freed with g_object_unref() when no longer needed.
557
ECredentialsPrompterImpl *
558
e_credentials_prompter_impl_password_new (void)
560
return g_object_new (E_TYPE_CREDENTIALS_PROMPTER_IMPL_PASSWORD, NULL);