1 /* passphrase.c - GTK+ based passphrase callback
2 * Copyright (C) 2001 Werner Koch (dd9jn)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <sys/types.h>
29 #include <glib/gi18n.h>
30 #include <gdk/gdkkeysyms.h>
31 #include <gtk/gtkmain.h>
32 #include <gtk/gtkwidget.h>
33 #include <gtk/gtkwindow.h>
34 #include <gtk/gtkvbox.h>
35 #include <gtk/gtktable.h>
36 #include <gtk/gtklabel.h>
37 #include <gtk/gtkentry.h>
38 #include <gtk/gtkhbbox.h>
39 #include <gtk/gtkbutton.h>
40 #include <gtk/gtkfilesel.h>
41 #include <gtk/gtksignal.h>
42 #ifdef GDK_WINDOWING_X11
43 #include <gdk/gdkx.h> /* GDK_DISPLAY() */
44 #endif /* GDK_WINDOWING_X11 */
46 #include "passphrase.h"
47 #include "prefs_common.h"
48 #include "manage_window.h"
50 #include "prefs_gpg.h"
52 static int grab_all = 0;
54 static gboolean pass_ack;
55 static gchar *last_pass = NULL;
57 static void passphrase_ok_cb(GtkWidget *widget, gpointer data);
58 static void passphrase_cancel_cb(GtkWidget *widget, gpointer data);
59 static gint passphrase_deleted(GtkWidget *widget, GdkEventAny *event,
61 static gboolean passphrase_key_pressed(GtkWidget *widget, GdkEventKey *event,
63 static gchar* passphrase_mbox (const gchar *desc);
66 static GtkWidget *create_description (const gchar *desc);
69 gpgmegtk_set_passphrase_grab (gint yes)
71 #warning "passphrase grab does not work"
80 passphrase_mbox (const gchar *desc)
82 gchar *the_passphrase = NULL;
84 GtkWidget *confirm_box;
86 GtkWidget *pass_entry;
88 GtkWidget *cancel_button;
91 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
92 gtk_window_set_title(GTK_WINDOW(window), _("Passphrase"));
93 gtk_widget_set_size_request(window, 450, -1);
94 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
95 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
96 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
97 g_signal_connect(G_OBJECT(window), "delete_event",
98 G_CALLBACK(passphrase_deleted), NULL);
99 g_signal_connect(G_OBJECT(window), "key_press_event",
100 G_CALLBACK(passphrase_key_pressed), NULL);
101 MANAGE_WINDOW_SIGNALS_CONNECT(window);
102 manage_window_set_transient(GTK_WINDOW(window));
104 vbox = gtk_vbox_new(FALSE, 8);
105 gtk_container_add(GTK_CONTAINER(window), vbox);
106 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
110 label = create_description (desc);
111 gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
114 pass_entry = gtk_entry_new();
115 gtk_box_pack_start(GTK_BOX(vbox), pass_entry, FALSE, FALSE, 0);
116 gtk_entry_set_visibility(GTK_ENTRY(pass_entry), FALSE);
117 gtk_widget_grab_focus(pass_entry);
119 gtkut_stock_button_set_create(&confirm_box, &ok_button, GTK_STOCK_OK,
120 &cancel_button, GTK_STOCK_CANCEL,
122 gtk_box_pack_end(GTK_BOX(vbox), confirm_box, FALSE, FALSE, 0);
123 gtk_widget_grab_default(ok_button);
125 g_signal_connect(G_OBJECT(ok_button), "clicked",
126 G_CALLBACK(passphrase_ok_cb), NULL);
127 g_signal_connect(G_OBJECT(pass_entry), "activate",
128 G_CALLBACK(passphrase_ok_cb), NULL);
129 g_signal_connect(G_OBJECT(cancel_button), "clicked",
130 G_CALLBACK(passphrase_cancel_cb), NULL);
133 g_object_set (G_OBJECT(window), "type", GTK_WINDOW_POPUP, NULL);
134 gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER);
136 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
138 gtk_widget_show_all(window);
140 /* don't use XIM on entering passphrase */
141 gtkut_editable_disable_im(GTK_EDITABLE(pass_entry));
144 #ifdef GDK_WINDOWING_X11
145 XGrabServer(GDK_DISPLAY());
146 #endif /* GDK_WINDOWING_X11 */
147 if ( grab_result = gdk_pointer_grab ( window->window, TRUE, 0,
148 NULL, NULL, GDK_CURRENT_TIME)) {
149 #ifdef GDK_WINDOWING_X11
150 XUngrabServer ( GDK_DISPLAY() );
151 #endif /* GDK_WINDOWING_X11 */
152 g_warning ("OOPS: Could not grab mouse (grab status %d)\n",
154 gtk_widget_destroy (window);
157 if ( grab_result = gdk_keyboard_grab( window->window, FALSE,
158 GDK_CURRENT_TIME )) {
159 gdk_pointer_ungrab (GDK_CURRENT_TIME);
160 #ifdef GDK_WINDOWING_X11
161 XUngrabServer ( GDK_DISPLAY() );
162 #endif /* GDK_WINDOWING_X11 */
163 g_warning ("OOPS: Could not grab keyboard (grab status %d)\n",
165 gtk_widget_destroy (window);
173 #ifdef GDK_WINDOWING_X11
174 XUngrabServer (GDK_DISPLAY());
175 #endif /* GDK_WINDOWING_X11 */
176 gdk_pointer_ungrab (GDK_CURRENT_TIME);
177 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
181 manage_window_focus_out(window, NULL, NULL);
184 const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(pass_entry));
185 if (entry_text) /* Hmmm: Do we really need this? */
186 the_passphrase = g_strdup (entry_text);
188 gtk_widget_destroy (window);
190 return the_passphrase;
195 passphrase_ok_cb(GtkWidget *widget, gpointer data)
202 passphrase_cancel_cb(GtkWidget *widget, gpointer data)
210 passphrase_deleted(GtkWidget *widget, GdkEventAny *event, gpointer data)
212 passphrase_cancel_cb(NULL, NULL);
218 passphrase_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
220 if (event && event->keyval == GDK_Escape)
221 passphrase_cancel_cb(NULL, NULL);
226 linelen (const gchar *s)
230 for (i = 0; *s && *s != '\n'; s++, i++)
237 create_description (const gchar *desc)
239 const gchar *cmd = NULL, *uid = NULL, *info = NULL;
244 uid = strchr (cmd, '\n');
246 info = strchr (++uid, '\n');
252 uid = _("[no user id]");
256 buf = g_strdup_printf (_("%sPlease enter the passphrase for:\n\n"
259 !strncmp (cmd, "TRY_AGAIN", 9 ) ?
260 _("Bad passphrase! Try again...\n\n") : "",
261 linelen (uid), uid, linelen (info), info);
263 label = gtk_label_new (buf);
264 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
270 static int free_passphrase(gpointer _unused)
272 if (last_pass != NULL) {
273 munlock(last_pass, strlen(last_pass));
276 debug_print("%% passphrase removed");
283 gpgmegtk_passphrase_cb (void *opaque, const char *desc, void **r_hd)
285 struct passphrase_cb_info_s *info = opaque;
286 GpgmeCtx ctx = info ? info->c : NULL;
290 /* FIXME: cleanup by looking at *r_hd */
293 if (prefs_gpg_get_config()->store_passphrase && last_pass != NULL &&
294 strncmp(desc, "TRY_AGAIN", 9) != 0)
295 return g_strdup(last_pass);
297 gpgmegtk_set_passphrase_grab (prefs_gpg_get_config()->passphrase_grab);
298 debug_print ("%% requesting passphrase for `%s': ", desc);
299 pass = passphrase_mbox (desc);
300 gpgmegtk_free_passphrase();
302 debug_print ("%% cancel passphrase entry");
306 if (prefs_gpg_get_config()->store_passphrase) {
307 last_pass = g_strdup(pass);
308 if (mlock(last_pass, strlen(last_pass)) == -1)
309 debug_print("%% locking passphrase failed");
311 if (prefs_gpg_get_config()->store_passphrase_timeout > 0) {
312 gtk_timeout_add(prefs_gpg_get_config()->store_passphrase_timeout*60*1000,
313 free_passphrase, NULL);
316 debug_print ("%% sending passphrase");
322 void gpgmegtk_free_passphrase(void)
324 (void)free_passphrase(NULL); /* could be inline */
327 #endif /* USE_GPGME */