gnome-keyring r1198 - in trunk: . common daemon daemon/pkcs11 daemon/ssh daemon/ui



Author: nnielsen
Date: Thu Jul 24 04:07:27 2008
New Revision: 1198
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1198&view=rev

Log:
	* common/gkr-async.c:
	* common/gkr-async.h:
	* common/gkr-daemon-util.c:
	* common/gkr-daemon-util.h:
	* daemon/gkr-daemon-io.c:
	* daemon/pkcs11/gkr-pkcs11-daemon-session.c:
	* daemon/ssh/gkr-ssh-daemon-io.c:
	* daemon/ui/gkr-ask-daemon.c:
	* daemon/ui/gkr-ask-request.c:
	* daemon/ui/gkr-ask-request.h: Don't prompt for the same prompt twice 
	while servicing the same client connection. Fixes bug #544373


Modified:
   trunk/ChangeLog
   trunk/common/gkr-async.c
   trunk/common/gkr-async.h
   trunk/common/gkr-daemon-util.c
   trunk/common/gkr-daemon-util.h
   trunk/daemon/gkr-daemon-io.c
   trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c
   trunk/daemon/ssh/gkr-ssh-daemon-io.c
   trunk/daemon/ui/gkr-ask-daemon.c
   trunk/daemon/ui/gkr-ask-request.c
   trunk/daemon/ui/gkr-ask-request.h

Modified: trunk/common/gkr-async.c
==============================================================================
--- trunk/common/gkr-async.c	(original)
+++ trunk/common/gkr-async.c	Thu Jul 24 04:07:27 2008
@@ -373,6 +373,10 @@
 	worker->cancelled = 0;
 	worker->stopped = 0;
 	
+	/* 
+	 * Don't change this to a thread pool too lightly. Assumptions are made 
+	 * that worker threads are not shared throughout the code.
+	 */
 	worker->thread = g_thread_create (async_worker_thread, worker, TRUE, &err);
 	if (!worker->thread) {
 		g_warning ("couldn't create new worker thread: %s", err->message);

Modified: trunk/common/gkr-async.h
==============================================================================
--- trunk/common/gkr-async.h	(original)
+++ trunk/common/gkr-async.h	Thu Jul 24 04:07:27 2008
@@ -34,7 +34,7 @@
 typedef struct _GkrAsyncWait GkrAsyncWait;
 
 /* 
- * Create a new wait condition 
+ * Create a new wait condition. Use instead of GCond.
  */
 GkrAsyncWait*      gkr_async_wait_new            (void);
 
@@ -53,6 +53,18 @@
  */
 void               gkr_async_notify              (GkrAsyncWait *wait);
 
+/*
+ * Per Async Worker Storage. This is currently exactly the same 
+ * as GPrivate, however that may change in the future, so use this
+ * API instead.
+ */
+
+typedef GPrivate GkrAsyncPrivate;
+#define gkr_async_private_new(x) g_private_new (x)
+#define gkr_async_private_get(x) g_private_get (x)
+#define gkr_async_private_set(x, y) g_private_set (x, y)
+#define gkr_async_private_free(x) 
+
 /* -----------------------------------------------------------------------------
  * GENERAL ASYNC CALLS
  */

Modified: trunk/common/gkr-daemon-util.c
==============================================================================
--- trunk/common/gkr-daemon-util.c	(original)
+++ trunk/common/gkr-daemon-util.c	Thu Jul 24 04:07:27 2008
@@ -23,15 +23,230 @@
 
 #include "config.h"
 
-#include "common/gkr-daemon-util.h"
-#include "common/gkr-cleanup.h"
+#include "gkr-async.h"
+#include "gkr-daemon-util.h"
+#include "gkr-cleanup.h"
 
 #include <glib.h>
 
 #include <sys/stat.h>
+
 #include <errno.h>
+#include <string.h>
 #include <unistd.h>
 
+enum {
+	PROP_0,
+	PROP_PID,
+	PROP_APP_PATH,
+	PROP_APP_DISPLAY
+};
+
+enum {
+	DISCONNECTED,
+	LAST_SIGNAL
+};
+
+G_DEFINE_TYPE (GkrDaemonClient, gkr_daemon_client, G_TYPE_OBJECT);
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GkrAsyncPrivate *current_client = NULL;
+
+/* -----------------------------------------------------------------------------
+ * HELPERS
+ */
+
+static void
+unregister_client (gpointer data)
+{
+	g_assert (GKR_IS_DAEMON_CLIENT (data));
+	g_signal_emit (data, signals[DISCONNECTED], 0);
+	g_object_unref (data);
+}
+
+static void
+register_client (GkrDaemonClient *client)
+{
+	g_assert (GKR_IS_DAEMON_CLIENT (client));
+	g_assert (current_client);
+	gkr_async_private_set (current_client, client);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gkr_daemon_client_init (GkrDaemonClient *obj)
+{
+
+}
+
+static void
+gkr_daemon_client_get_property (GObject *obj, guint prop_id, GValue *value, 
+                                GParamSpec *pspec)
+{
+	GkrDaemonClient *client = GKR_DAEMON_CLIENT (obj);
+
+	switch (prop_id) {
+	case PROP_PID:
+		g_value_set_uint (value, client->pid);
+		break;
+	case PROP_APP_PATH:
+		g_value_set_string (value, client->app_path);
+		break;
+	case PROP_APP_DISPLAY:
+		g_value_set_string (value, client->app_display);
+		break;
+	}
+}
+
+static void
+gkr_daemon_client_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                                GParamSpec *pspec)
+{
+	GkrDaemonClient *client = GKR_DAEMON_CLIENT (obj);
+
+	switch (prop_id) {
+	case PROP_PID:
+		g_return_if_fail (!client->pid);
+		client->pid = g_value_get_uint (value);
+		break;
+	case PROP_APP_PATH:
+		g_return_if_fail (!client->app_path);
+		client->app_path = g_value_dup_string (value);
+		break;
+	case PROP_APP_DISPLAY:
+		g_free (client->app_display);
+		client->app_display = g_value_dup_string (value);
+		break;
+	}
+}
+
+static void
+gkr_daemon_client_finalize (GObject *obj)
+{
+	GkrDaemonClient *client = GKR_DAEMON_CLIENT (obj);
+	 
+	if (client->app_path)
+		g_free (client->app_path);
+	if (client->app_display)
+		g_free (client->app_display);
+	
+	G_OBJECT_CLASS (gkr_daemon_client_parent_class)->finalize (obj);
+}
+
+static void
+gkr_daemon_client_class_init (GkrDaemonClientClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*) klass;
+	gkr_daemon_client_parent_class = g_type_class_peek_parent (klass);
+	
+	gobject_class->get_property = gkr_daemon_client_get_property;
+	gobject_class->set_property = gkr_daemon_client_set_property;
+	gobject_class->finalize = gkr_daemon_client_finalize;
+
+	g_object_class_install_property (gobject_class, PROP_PID,
+		g_param_spec_uint ("pid", "Process ID", "Process ID of client",
+		                   0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+		                   
+	g_object_class_install_property (gobject_class, PROP_APP_PATH,
+		g_param_spec_string ("app-path", "Application Path", "Client application path",
+		                     NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+		                     
+	g_object_class_install_property (gobject_class, PROP_APP_DISPLAY,
+		g_param_spec_string ("app-display", "Application Display Name", "Client application display name",
+		                     NULL, G_PARAM_READWRITE));
+		                     
+	signals[DISCONNECTED] = g_signal_new ("disconnected", GKR_TYPE_DAEMON_CLIENT, 
+			G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkrDaemonClientClass, disconnected),
+			NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+	
+	current_client = gkr_async_private_new (unregister_client);
+}
+
+/* -------------------------------------------------------------------------------------
+ * PUBLIC STUFF
+ */
+
+GkrDaemonClient*
+gkr_daemon_client_set_current (pid_t pid, const gchar *app_path, const gchar *app_display)
+{
+	GkrDaemonClient *client;
+	gchar *path = NULL;
+	
+	/* Try and figure out the path from the pid */
+#if defined(__linux__) || defined(__FreeBSD__)
+	if (pid > 0 && !app_path) {
+		char *buffer;
+		int len;
+		char *path = NULL;
+			
+#if defined(__linux__)
+		path = g_strdup_printf ("/proc/%d/exe", (gint)pid);
+#elif defined(__FreeBSD__)
+		path = g_strdup_printf ("/proc/%d/file", (gint)pid);
+#endif
+		buffer = g_file_read_link (path, NULL);
+		g_free (path);
+
+		len = (buffer != NULL) ? strlen (buffer) : 0;
+		if (len > 0) {
+			path = g_strndup (buffer, len);
+			app_path = path;
+		}
+		
+		g_free (buffer);
+	}
+#endif
+	
+	client = g_object_new (GKR_TYPE_DAEMON_CLIENT, "pid", pid, "app-path", app_path, 
+	                       "app-display", app_display, NULL);
+	
+	register_client (client);
+	g_free (path);
+	
+	return client;
+}
+
+GkrDaemonClient*
+gkr_daemon_client_get_current (void)
+{
+	if (!current_client)
+		return NULL;
+	return gkr_async_private_get (current_client);
+}
+
+pid_t
+gkr_daemon_client_get_app_pid (GkrDaemonClient* client)
+{
+	if (!client)
+		client = gkr_daemon_client_get_current ();
+	g_return_val_if_fail (GKR_IS_DAEMON_CLIENT (client), 0);
+	return client->pid;
+}
+
+const gchar*
+gkr_daemon_client_get_app_display (GkrDaemonClient* client)
+{
+	if (!client)
+		client = gkr_daemon_client_get_current ();
+	g_return_val_if_fail (GKR_IS_DAEMON_CLIENT (client), 0);
+	return client->app_display;
+}
+
+const gchar*
+gkr_daemon_client_get_app_path (GkrDaemonClient* client)
+{
+	if (!client)
+		client = gkr_daemon_client_get_current ();
+	g_return_val_if_fail (GKR_IS_DAEMON_CLIENT (client), 0);
+	return client->app_path;
+}
+
+/* -------------------------------------------------------------------------------------- */
+
 static gchar* master_directory = NULL;
 static GArray* published_environ = NULL;
 
@@ -325,3 +540,4 @@
   else
     return template;
 }
+

Modified: trunk/common/gkr-daemon-util.h
==============================================================================
--- trunk/common/gkr-daemon-util.h	(original)
+++ trunk/common/gkr-daemon-util.h	Thu Jul 24 04:07:27 2008
@@ -1,7 +1,7 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /* gkr-daemon-util.h - Helper utilities for the daemon
 
-   Copyright (C) 2007, Stefan Walter
+   Copyright (C) 2008, Stefan Walter
 
    The Gnome Keyring Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -24,7 +24,10 @@
 #ifndef GKRMASTERDIRECTORY_H_
 #define GKRMASTERDIRECTORY_H_
 
+G_BEGIN_DECLS
+
 #include <glib.h>
+#include <glib-object.h>
 
 const gchar*    gkr_daemon_util_get_master_directory    (void);
 
@@ -32,4 +35,40 @@
 
 const gchar**   gkr_daemon_util_get_environment         (void);
 
+#define GKR_TYPE_DAEMON_CLIENT             (gkr_daemon_client_get_type ())
+#define GKR_DAEMON_CLIENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKR_TYPE_DAEMON_CLIENT, GkrDaemonClient))
+#define GKR_DAEMON_CLIENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GKR_TYPE_DAEMON_CLIENT, GkrDaemonClientClass))
+#define GKR_IS_DAEMON_CLIENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKR_TYPE_DAEMON_CLIENT))
+#define GKR_IS_DAEMON_CLIENT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GKR_TYPE_DAEMON_CLIENT))
+#define GKR_DAEMON_CLIENT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GKR_TYPE_DAEMON_CLIENT, GkrDaemonClientClass))
+
+typedef struct _GkrDaemonClient GkrDaemonClient;
+typedef struct _GkrDaemonClientClass GkrDaemonClientClass;
+
+struct _GkrDaemonClient {
+	GObject parent;
+	pid_t pid;
+	gchar *app_path;
+	gchar *app_display;
+};
+
+struct _GkrDaemonClientClass {
+	GObjectClass parent_class;
+	void (*disconnected) (GkrDaemonClient *client);
+};
+
+GType                             gkr_daemon_client_get_type         (void);
+
+GkrDaemonClient*                  gkr_daemon_client_set_current      (pid_t pid, const gchar *app_path, const gchar *app_display);
+
+GkrDaemonClient*                  gkr_daemon_client_get_current      (void);
+
+pid_t                             gkr_daemon_client_get_app_pid      (GkrDaemonClient* client);
+
+const gchar*                      gkr_daemon_client_get_app_display  (GkrDaemonClient* client);
+
+const gchar*                      gkr_daemon_client_get_app_path     (GkrDaemonClient* client);
+
+G_END_DECLS
+
 #endif /*GKRMASTERDIRECTORY_H_*/

Modified: trunk/daemon/gkr-daemon-io.c
==============================================================================
--- trunk/daemon/gkr-daemon-io.c	(original)
+++ trunk/daemon/gkr-daemon-io.c	Thu Jul 24 04:07:27 2008
@@ -99,37 +99,14 @@
 }
 
 static GnomeKeyringApplicationRef*
-application_ref_new_from_pid (pid_t pid)
+application_ref_new_from_client ()
 {
 	GnomeKeyringApplicationRef *app_ref;
-
+	
 	app_ref = g_new0 (GnomeKeyringApplicationRef, 1);
-
-#if defined(__linux__) || defined(__FreeBSD__)
-	g_assert (pid > 0);
-	{
-		char *buffer;
-		int len;
-		char *path = NULL;
-		
-#if defined(__linux__)
-		path = g_strdup_printf ("/proc/%d/exe", (gint)pid);
-#elif defined(__FreeBSD__)
-		path = g_strdup_printf ("/proc/%d/file", (gint)pid);
-#endif
-		buffer = g_file_read_link (path, NULL);
-		g_free (path);
-
-		len = (buffer != NULL) ? strlen (buffer) : 0;
-		if (len > 0) {
-			app_ref->pathname = g_malloc (len + 1);
-			memcpy (app_ref->pathname, buffer, len);
-			app_ref->pathname[len] = 0;
-		}
-		g_free (buffer);
-	}
-#endif
-
+	app_ref->pathname = g_strdup (gkr_daemon_client_get_app_path (NULL));
+	app_ref->display_name = g_strdup (gkr_daemon_client_get_app_display (NULL));
+	
 	return app_ref;
 }
 
@@ -273,7 +250,9 @@
 		g_warning ("uid mismatch: %u, should be %u\n", (guint)uid, (guint)getuid());
 		return NULL;
 	}
-	client->app_ref = application_ref_new_from_pid (pid);
+	
+	gkr_daemon_client_set_current (pid, NULL, NULL);
+	client->app_ref = application_ref_new_from_client ();
 
 
 	/* 2. Read the connecting application display name */
@@ -286,6 +265,7 @@
 	if (!str)
 		return NULL;
 	debug_print (("got name: %s\n", str));
+	g_free (client->app_ref->display_name);
 	client->app_ref->display_name = str;
 
 

Modified: trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c
==============================================================================
--- trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c	(original)
+++ trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c	Thu Jul 24 04:07:27 2008
@@ -32,6 +32,7 @@
 #include "common/gkr-async.h"
 #include "common/gkr-buffer.h"
 #include "common/gkr-crypto.h"
+#include "common/gkr-daemon-util.h"
 #include "common/gkr-unix-credentials.h"
 
 #include "keyrings/gkr-keyring-login.h"
@@ -1572,6 +1573,9 @@
 		return NULL;
 	}
 	
+	/* Note the current client application */
+	gkr_daemon_client_set_current (pid, NULL, NULL);
+	
 	/* Setup our buffers */
 	/* TODO: Do these need to be secure buffers? */
 	req = gkr_pkcs11_message_new ((GkrBufferAllocator)g_realloc);

Modified: trunk/daemon/ssh/gkr-ssh-daemon-io.c
==============================================================================
--- trunk/daemon/ssh/gkr-ssh-daemon-io.c	(original)
+++ trunk/daemon/ssh/gkr-ssh-daemon-io.c	Thu Jul 24 04:07:27 2008
@@ -168,6 +168,14 @@
 	SshClient *client = (SshClient*)user_data;
 	guchar op;
 	
+	/* 
+	 * Note the current client application. We actually don't know 
+	 * the pid, so this is just an empty application object, useful 
+	 * for other parts of the code to track the lifecycle of the 
+	 * connection.
+	 */
+	gkr_daemon_client_set_current (0, NULL, NULL);
+	
 	/* This array needs to be laid out properly */
 	g_assert ((sizeof (gkr_ssh_operations) / sizeof (gkr_ssh_operations[0])) == GKR_SSH_OP_MAX);
 

Modified: trunk/daemon/ui/gkr-ask-daemon.c
==============================================================================
--- trunk/daemon/ui/gkr-ask-daemon.c	(original)
+++ trunk/daemon/ui/gkr-ask-daemon.c	Thu Jul 24 04:07:27 2008
@@ -28,6 +28,7 @@
 
 #include "common/gkr-async.h"
 #include "common/gkr-cleanup.h"
+#include "common/gkr-daemon-util.h"
 
 #include <glib.h>
 
@@ -66,6 +67,52 @@
 	gkr_cleanup_register (ask_daemon_cleanup, NULL);
 }
 
+static gboolean
+check_previously_denied (GkrAskRequest *ask)
+{
+	GkrDaemonClient *client;
+	GHashTable *denied;
+	gchar *unique;
+	gboolean ret;
+	
+	client = gkr_daemon_client_get_current ();
+	g_return_val_if_fail (client, FALSE);
+	
+	denied = g_object_get_data (G_OBJECT (client), "gkr-ask-daemon.denied");
+	if (!denied)
+		return FALSE;
+	
+	unique = gkr_ask_request_make_unique (ask);
+	g_return_val_if_fail (unique, FALSE);
+	ret = g_hash_table_lookup (denied, unique) ? TRUE : FALSE;
+	g_free (unique);
+	return ret;
+}
+
+static void
+note_previously_denied (GkrAskRequest *ask)
+{
+	GkrDaemonClient *client;
+	GHashTable *denied;
+	gchar *unique;
+
+	unique = gkr_ask_request_make_unique (ask);
+	g_return_if_fail (unique);
+	
+	client = gkr_daemon_client_get_current ();
+	g_return_if_fail (client);
+
+	/* Associate the denied table with the current client */
+	denied = g_object_get_data (G_OBJECT (client), "gkr-ask-daemon.denied");
+	if (!denied) {
+		denied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+		g_object_set_data_full (G_OBJECT (client), "gkr-ask-daemon.denied", 
+		                        denied, (GDestroyNotify)g_hash_table_unref);
+	}
+	
+	g_hash_table_insert (denied, unique, unique);
+}
+
 void
 gkr_ask_daemon_process (GkrAskRequest* ask)
 {
@@ -73,7 +120,9 @@
 	
 	g_assert (GKR_IS_ASK_REQUEST (ask));
 	g_assert (!gkr_ask_request_is_complete (ask));
-	
+
+	g_object_ref (ask);
+
 	/* 
 	 * Hand it off to the hook. This is used in the test harnesses
 	 * to verify that a prompt or no prompt was run.
@@ -93,23 +142,44 @@
 	/* Wait until no other asks are prompting */
 	while (current_ask)
 		gkr_async_wait (wait_condition);
+
+	/* 
+	 * See if the user already denied this request.
+	 * 
+	 * The logic here is, that if the user denied the request, 
+	 * then we won't prompt them again for the same string. 
+	 * They'll probably deny it again. 
+	 * 
+	 * We only keep this cache for the current client connection. 
+	 */
+	if (check_previously_denied (ask)) {
+		gkr_ask_request_deny (ask);
+		goto done;
+	}
 	
 	g_assert (ask_daemon_inited);
-	
-	g_object_ref (ask);
 	current_ask = ask;
 	
-	if (!gkr_ask_request_check (ask))
+	if (!gkr_ask_request_check (ask)) {
 		gkr_ask_request_prompt (ask);
+		
+		/* 
+		 * Note that this prompt was explicitly denied, so we 
+		 * can prevent prompting again on the same client
+		 * connection. See above.
+		 */ 
+		if (ask->response == GKR_ASK_RESPONSE_DENY)
+			note_previously_denied (ask);
+	}
 
 	current_ask = NULL;
-	g_object_unref (ask);
 	
 	g_assert (wait_condition);
 	gkr_async_notify (wait_condition);
 	
 done:
 	g_assert (gkr_ask_request_is_complete (ask));
+	g_object_unref (ask);
 }
 
 void

Modified: trunk/daemon/ui/gkr-ask-request.c
==============================================================================
--- trunk/daemon/ui/gkr-ask-request.c	(original)
+++ trunk/daemon/ui/gkr-ask-request.c	Thu Jul 24 04:07:27 2008
@@ -260,7 +260,7 @@
 }
 
 static void 
-cancel_ask_if_active (GkrAskRequest *ask)
+kill_ask_if_active (GkrAskRequest *ask)
 {
 	GkrAskRequestPrivate *pv = GKR_ASK_REQUEST_GET_PRIVATE (ask);
 	if (pv->ask_pid) {
@@ -268,8 +268,6 @@
 		kill_ask_process (ask);
 		g_assert (pv->ask_pid == 0);
 	}
-	
-	mark_completed (ask, GKR_ASK_RESPONSE_FAILURE);
 }
 
 static void
@@ -643,7 +641,8 @@
 	pv->object = NULL;
 	
 	/* Cancel any goings on */
-	cancel_ask_if_active (ask);
+	kill_ask_if_active (ask);
+	mark_completed (ask, GKR_ASK_RESPONSE_FAILURE);
 }
 
 static gboolean
@@ -699,7 +698,8 @@
 	GkrAskRequest *ask = GKR_ASK_REQUEST (obj);
 	GkrAskRequestPrivate *pv = GKR_ASK_REQUEST_GET_PRIVATE (ask);
 	
-	cancel_ask_if_active (ask);
+	kill_ask_if_active (ask);
+	mark_completed (ask, GKR_ASK_RESPONSE_FAILURE);
 	g_assert (pv->ask_pid == 0);
 	
 	gkr_secure_strfree (ask->original_password);
@@ -906,14 +906,19 @@
 }
 
 void
+gkr_ask_request_deny (GkrAskRequest *ask)
+{
+	g_assert (GKR_IS_ASK_REQUEST (ask));
+	kill_ask_if_active (ask);
+	mark_completed (ask, GKR_ASK_RESPONSE_DENY);
+}
+
+void
 gkr_ask_request_cancel (GkrAskRequest *ask)
 {
-	GkrAskRequestPrivate *pv = GKR_ASK_REQUEST_GET_PRIVATE (ask);
 	g_assert (GKR_IS_ASK_REQUEST (ask));
-	
-	cancel_ask_if_active (ask);
-	if (!pv->completed)
-		mark_completed (ask, GKR_ASK_RESPONSE_FAILURE);
+	kill_ask_if_active (ask);
+	mark_completed (ask, GKR_ASK_RESPONSE_FAILURE);
 }
 
 gboolean
@@ -939,3 +944,21 @@
 	g_assert (GKR_IS_ASK_REQUEST (ask));
 	pv->location = loc;
 }
+
+gchar*
+gkr_ask_request_make_unique (GkrAskRequest *ask)
+{
+	GkrAskRequestPrivate *pv = GKR_ASK_REQUEST_GET_PRIVATE (ask);
+	g_assert (GKR_IS_ASK_REQUEST (ask));
+
+	/* 
+	 * This string is used to uniquely identify another
+	 * prompt with the same text as this one. Usually used
+	 * so we can be intelligent about prompting the user.
+	 */
+	
+	return g_strconcat (pv->title ? pv->title : "", "|", 
+	                    pv->primary ? pv->primary : "", "|",
+	                    pv->secondary ? pv->secondary : "", "|",
+	                    NULL);
+}

Modified: trunk/daemon/ui/gkr-ask-request.h
==============================================================================
--- trunk/daemon/ui/gkr-ask-request.h	(original)
+++ trunk/daemon/ui/gkr-ask-request.h	Thu Jul 24 04:07:27 2008
@@ -123,10 +123,14 @@
 
 void               gkr_ask_request_prompt           (GkrAskRequest *ask);
 
+void               gkr_ask_request_deny             (GkrAskRequest *ask);
+
 void               gkr_ask_request_cancel           (GkrAskRequest *ask);
 
 gboolean           gkr_ask_request_is_complete      (GkrAskRequest *ask);
 
+gchar*             gkr_ask_request_make_unique      (GkrAskRequest *ask);
+
 G_END_DECLS
 
 #endif /* __GKR_ASK_REQUEST_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]