Patch for question callback
- From: Mattias Eriksson <snaggen acc umu se>
- To: "gnome-vfs-list gnome org" <gnome-vfs-list gnome org>
- Subject: Patch for question callback
- Date: Thu, 08 Apr 2004 14:19:57 +0200
Hi,
Here is the patch I have been working on to add a new question callback
to gnome-vfs and libgnomeui.
The main purpose was to make the sftp module ask the user what to do
when the authenticity of a host cant be determined.
As you can see I currently just pass the message from sftp to the user,
this is not so nice since it is a bad message and it is not
translatable. I'm not much of an usability guy so I need some help with
the message, so anyone with such talent feel free to help out.
//Snaggen
Index: libgnomevfs/GNOME_VFS_Daemon.idl
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/GNOME_VFS_Daemon.idl,v
retrieving revision 1.6
diff -u -r1.6 GNOME_VFS_Daemon.idl
--- libgnomevfs/GNOME_VFS_Daemon.idl 22 Jan 2004 15:35:01 -0000 1.6
+++ libgnomevfs/GNOME_VFS_Daemon.idl 8 Apr 2004 11:05:39 -0000
@@ -67,6 +67,13 @@
/* Standard module callbacks: */
+ struct ModuleCallbackQuestionIn {
+ string message;
+ sequence<string> choices;
+ };
+ struct ModuleCallbackQuestionOut {
+ short answer;
+ };
struct ModuleCallbackAuthenticationIn {
string uri;
string realm;
Index: libgnomevfs/gnome-vfs-module-callback-marshall.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-module-callback-marshall.c,v
retrieving revision 1.4
diff -u -r1.4 gnome-vfs-module-callback-marshall.c
--- libgnomevfs/gnome-vfs-module-callback-marshall.c 10 Dec 2003 12:39:23 -0000 1.4
+++ libgnomevfs/gnome-vfs-module-callback-marshall.c 8 Apr 2004 11:05:39 -0000
@@ -603,6 +603,143 @@
g_free (auth_out);
}
+static CORBA_any *
+question_marshal_in (gconstpointer in, gsize in_size)
+{
+ CORBA_any *retval;
+ GNOME_VFS_ModuleCallbackQuestionIn *ret_in;
+ const GnomeVFSModuleCallbackQuestionIn *question_in;
+ int cnt;
+
+ if (in_size != sizeof (GnomeVFSModuleCallbackQuestionIn)) {
+ return NULL;
+ }
+ question_in = in;
+
+ retval = CORBA_any_alloc ();
+ retval->_type = TC_GNOME_VFS_ModuleCallbackQuestionIn;
+ retval->_value = GNOME_VFS_ModuleCallbackQuestionIn__alloc ();
+ ret_in = retval->_value;
+
+ /* Set the values in ret_in, like ret_in->stuff=question_in->stuff */
+ ret_in->message = corba_string_or_null_dup(question_in->message);
+ if (question_in->choices) {
+
+ /* Just count the number of elements and allocate the memory */
+ for (cnt=0; question_in->choices[cnt] != NULL; cnt++);
+ ret_in->choices._maximum = cnt;
+ ret_in->choices._length = cnt;
+ ret_in->choices._buffer = CORBA_sequence_CORBA_string_allocbuf (cnt);
+ //FIXME
+ //CORBA_sequence_set_release (ret_in->choices, TRUE);
+
+ /* Insert the strings into the sequence */
+ for (cnt=0; question_in->choices[cnt] != NULL; cnt++) {
+ ret_in->choices._buffer[cnt] = corba_string_or_null_dup (question_in->choices[cnt]);
+ }
+ }
+ return retval;
+}
+
+static gboolean
+question_demarshal_in (const CORBA_any *any_in,
+ gpointer *in, gsize *in_size,
+ gpointer *out, gsize *out_size)
+{
+ GNOME_VFS_ModuleCallbackQuestionIn *corba_in;
+ GnomeVFSModuleCallbackQuestionIn *question_in;
+ GnomeVFSModuleCallbackQuestionOut *question_out;
+ int cnt;
+
+ if (!CORBA_TypeCode_equal (any_in->_type, TC_GNOME_VFS_ModuleCallbackQuestionIn, NULL)) {
+ return FALSE;
+ }
+
+ question_in = *in = g_new0 (GnomeVFSModuleCallbackQuestionIn, 1);
+ *in_size = sizeof (GnomeVFSModuleCallbackQuestionIn);
+ question_out = *out = g_new0 (GnomeVFSModuleCallbackQuestionOut, 1);
+ *out_size = sizeof (GnomeVFSModuleCallbackQuestionOut);
+
+ corba_in = (GNOME_VFS_ModuleCallbackQuestionIn *)any_in->_value;
+
+ if (corba_in) {
+ question_in->message = decode_corba_string_or_null (corba_in->message, FALSE);
+ question_in->choices = g_new(char *, corba_in->choices._length+1);
+ for(cnt=0; cnt<corba_in->choices._length; cnt++){
+ question_in->choices[cnt] = g_strdup(corba_in->choices._buffer[cnt]);
+ }
+ question_in->choices[corba_in->choices._length] = NULL;
+
+ question_out->answer = -1; /* Set a default value */
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static CORBA_any *
+question_marshal_out (gconstpointer out, gsize out_size)
+{
+ CORBA_any *retval;
+ GNOME_VFS_ModuleCallbackQuestionOut *ret_out;
+ const GnomeVFSModuleCallbackQuestionOut *question_out;
+
+ if (out_size != sizeof (GnomeVFSModuleCallbackQuestionOut)) {
+ return NULL;
+ }
+ question_out = out;
+
+ retval = CORBA_any_alloc();
+ retval->_type = TC_GNOME_VFS_ModuleCallbackQuestionOut;
+ retval->_value = GNOME_VFS_ModuleCallbackQuestionOut__alloc ();
+ ret_out = retval->_value;
+
+ g_message("Anser is:%d\n", question_out->answer);
+ ret_out->answer = question_out->answer;
+
+ return retval;
+}
+
+static gboolean
+question_demarshal_out (CORBA_any *any_out, gpointer out, gsize out_size)
+{
+ GNOME_VFS_ModuleCallbackQuestionOut *corba_out;
+ GnomeVFSModuleCallbackQuestionOut *question_out;
+
+ if (!CORBA_TypeCode_equal (any_out->_type, TC_GNOME_VFS_ModuleCallbackQuestionOut, NULL) ||
+ out_size != sizeof (GnomeVFSModuleCallbackQuestionOut)) {
+ return FALSE;
+ }
+ question_out = out;
+
+ corba_out = (GNOME_VFS_ModuleCallbackQuestionOut *)any_out->_value;
+
+ question_out->answer = corba_out->answer,TRUE;
+
+ return TRUE;
+}
+
+static void
+question_free_in (gpointer in)
+{
+ GnomeVFSModuleCallbackQuestionIn *question_in;
+
+ question_in = in;
+
+ g_free (question_in->message);
+ g_strfreev (question_in->choices);
+ g_free (question_in);
+}
+
+static void
+question_free_out (gpointer out)
+{
+ GnomeVFSModuleCallbackQuestionOut *question_out;
+
+ question_out = out;
+ g_free (question_out);
+}
+
struct ModuleCallbackMarshaller {
char *name;
CORBA_any *(*marshal_in)(gconstpointer in, gsize in_size);
@@ -654,6 +791,14 @@
save_auth_free_in,
save_auth_free_out
},
+ { GNOME_VFS_MODULE_CALLBACK_QUESTION,
+ question_marshal_in,
+ question_demarshal_in,
+ question_marshal_out,
+ question_demarshal_out,
+ question_free_in,
+ question_free_out
+ },
};
Index: libgnomevfs/gnome-vfs-standard-callbacks.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-standard-callbacks.h,v
retrieving revision 1.10
diff -u -r1.10 gnome-vfs-standard-callbacks.h
--- libgnomevfs/gnome-vfs-standard-callbacks.h 8 Jan 2004 19:46:37 -0000 1.10
+++ libgnomevfs/gnome-vfs-standard-callbacks.h 8 Apr 2004 11:05:39 -0000
@@ -83,6 +83,15 @@
*/
#define GNOME_VFS_MODULE_CALLBACK_HTTP_PROXY_AUTHENTICATION "http:proxy-authentication"
+/*
+ * hook name: "ask-question"
+ * In arg: GnomeVFSModuleCallbackQuestionIn *
+ * Out arg: GnomeVFSModuleCallbackQuestionOut *
+ *
+ * Called when access to a URI requires the user to make a choise
+ */
+#define GNOME_VFS_MODULE_CALLBACK_QUESTION "ask-question"
+
typedef struct {
char *uri; /* Full URI of operation */
char *protocol; /* The protocol of the request */
@@ -300,6 +309,31 @@
void *reserved2;
} GnomeVFSModuleCallbackStatusMessageOut;
+typedef struct {
+ char *message; /* A message explaining the question to the user or
+ * NULL if there is no message */
+ char **choices; /* The list of choices the user have to choose from,
+ the list must be NULL terminated.
+ The choices will be displayes so that choises[0]
+ will be to the left and choises[n] will be to the
+ right.
+ The last choice in the list should be affirmative
+ to comply with the button ordering in gnome */
+
+ /* Reserved "padding" to avoid future breaks in ABI compatibility */
+ void *reserved1;
+ void *reserved2;
+} GnomeVFSModuleCallbackQuestionIn;
+
+typedef struct {
+ int answer; /* The index of the choice in the choices list sent in
+ to the callback */
+
+ /* Reserved "padding" to avoid future breaks in ABI compatibility */
+ void *reserved1;
+ void *reserved2;
+} GnomeVFSModuleCallbackQuestionOut;
+
G_END_DECLS
#endif /* GNOME_VFS_STANDARD_CALLBACKS_H */
Index: libgnomeui/gnome-authentication-manager.c
===================================================================
RCS file: /cvs/gnome/libgnomeui/libgnomeui/gnome-authentication-manager.c,v
retrieving revision 1.7
diff -u -r1.7 gnome-authentication-manager.c
--- libgnomeui/gnome-authentication-manager.c 24 Mar 2004 10:40:55 -0000 1.7
+++ libgnomeui/gnome-authentication-manager.c 8 Apr 2004 11:09:59 -0000
@@ -703,6 +703,145 @@
DEBUG_MSG (("-%s\n", G_GNUC_FUNCTION));
}
+typedef struct {
+ const GnomeVFSModuleCallbackQuestionIn *in_args;
+ GnomeVFSModuleCallbackQuestionOut *out_args;
+
+ GnomeVFSModuleCallbackResponse response;
+ gpointer response_data;
+} QuestionCallbackInfo;
+
+static void
+question_dialog_button_clicked (GtkDialog *dialog,
+ gint button_number,
+ QuestionCallbackInfo *info)
+{
+ info->out_args->answer = button_number;
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+
+static void
+question_dialog_destroyed (GtkDialog *dialog, QuestionCallbackInfo *info)
+{
+ info->response (info->response_data);
+ g_free (info);
+}
+
+static void
+question_dialog_closed (GtkDialog *dialog, QuestionCallbackInfo *info)
+{
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static GtkWidget *create_question_dialog(char *msg, char **choices)
+{
+ GtkWidget *dialog;
+ int cnt;
+
+ dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, msg);
+ if (choices) {
+ for (cnt=0; choices[cnt] != NULL; cnt++) {
+ /* Maybe we should define some gnome-vfs stockbuttons and
+ * then replace them here with gtk-stockbuttons */
+ gtk_dialog_add_button(GTK_DIALOG(dialog), choices[cnt], cnt);
+ }
+ }
+ return (dialog);
+}
+
+static gint /* GtkFunction */
+present_question_dialog_nonblocking (QuestionCallbackInfo *info)
+{
+ GtkWidget *dialog;
+ GtkWidget *toplevel, *current_grab;
+
+ g_return_val_if_fail (info != NULL, 0);
+
+ dialog = create_question_dialog (info->in_args->message,info->in_args->choices);
+
+ toplevel = NULL;
+ current_grab = gtk_grab_get_current ();
+ if (current_grab) {
+ toplevel = gtk_widget_get_toplevel (current_grab);
+ }
+ if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) {
+ /* There is a modal window, so we need to be modal too in order to
+ * get input. We set the other modal dialog as parent, which
+ * hopefully gives us better window management.
+ */
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+ }
+
+ g_signal_connect (GTK_OBJECT(dialog), "response",
+ G_CALLBACK (question_dialog_button_clicked), info);
+ g_signal_connect (dialog, "close",
+ G_CALLBACK (question_dialog_closed), info);
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (question_dialog_destroyed), info);
+
+ gtk_widget_show (GTK_WIDGET (dialog));
+ return 0;
+}
+
+
+static void /* GnomeVFSAsyncModuleCallback */
+vfs_async_question_callback (gconstpointer in, size_t in_size,
+ gpointer out, size_t out_size,
+ gpointer user_data,
+ GnomeVFSModuleCallbackResponse response,
+ gpointer response_data)
+{
+ GnomeVFSModuleCallbackQuestionIn *in_real;
+ GnomeVFSModuleCallbackQuestionOut *out_real;
+ GtkWidget *dialog;
+ QuestionCallbackInfo *info;
+
+ g_return_if_fail (sizeof (GnomeVFSModuleCallbackQuestionIn) == in_size
+ && sizeof (GnomeVFSModuleCallbackQuestionOut) == out_size);
+
+ g_return_if_fail (in != NULL);
+ g_return_if_fail (out != NULL);
+
+ in_real = (GnomeVFSModuleCallbackQuestionIn *)in;
+ out_real = (GnomeVFSModuleCallbackQuestionOut *)out;
+
+ info = g_new (QuestionCallbackInfo, 1);
+
+ info->in_args = in_real;
+ info->out_args = out_real;
+ info->response = response;
+ info->response_data = response_data;
+
+ present_question_dialog_nonblocking(info);
+}
+
+static void /* GnomeVFSModuleCallback */
+vfs_question_callback (gconstpointer in, size_t in_size,
+ gpointer out, size_t out_size,
+ gpointer user_data)
+{
+ GnomeVFSModuleCallbackQuestionIn *in_real;
+ GnomeVFSModuleCallbackQuestionOut *out_real;
+ guint32 item;
+ GtkWidget *dialog;
+
+ g_return_if_fail (sizeof (GnomeVFSModuleCallbackQuestionIn) == in_size
+ && sizeof (GnomeVFSModuleCallbackQuestionOut) == out_size);
+
+ g_return_if_fail (in != NULL);
+ g_return_if_fail (out != NULL);
+
+ in_real = (GnomeVFSModuleCallbackQuestionIn *)in;
+ out_real = (GnomeVFSModuleCallbackQuestionOut *)out;
+
+ dialog = create_question_dialog (in_real->message,in_real->choices);
+ out_real->answer = gtk_dialog_run (GTK_DIALOG(dialog));
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
void
gnome_authentication_manager_init (void)
{
@@ -731,6 +870,10 @@
vfs_async_save_authentication_callback,
GINT_TO_POINTER (0),
NULL);
+ gnome_vfs_async_module_callback_set_default (GNOME_VFS_MODULE_CALLBACK_QUESTION,
+ vfs_async_question_callback,
+ GINT_TO_POINTER (0),
+ NULL);
/* These are in case someone makes a synchronous http call for
* some reason.
@@ -757,6 +900,10 @@
vfs_save_authentication_callback,
GINT_TO_POINTER (0),
NULL);
+ gnome_vfs_module_callback_set_default (GNOME_VFS_MODULE_CALLBACK_QUESTION,
+ vfs_question_callback,
+ GINT_TO_POINTER (0),
+ NULL);
}
@@ -784,6 +931,10 @@
vfs_async_save_authentication_callback,
GINT_TO_POINTER (0),
NULL);
+ gnome_vfs_async_module_callback_push (GNOME_VFS_MODULE_CALLBACK_QUESTION,
+ vfs_async_question_callback,
+ GINT_TO_POINTER (0),
+ NULL);
}
void
@@ -794,6 +945,7 @@
gnome_vfs_async_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_FILL_AUTHENTICATION);
gnome_vfs_async_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION);
gnome_vfs_async_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_SAVE_AUTHENTICATION);
+ gnome_vfs_async_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_QUESTION);
}
void
@@ -821,6 +973,10 @@
vfs_save_authentication_callback,
GINT_TO_POINTER (0),
NULL);
+ gnome_vfs_module_callback_push (GNOME_VFS_MODULE_CALLBACK_QUESTION,
+ vfs_question_callback,
+ GINT_TO_POINTER (0),
+ NULL);
}
void
@@ -831,5 +987,6 @@
gnome_vfs_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_FILL_AUTHENTICATION);
gnome_vfs_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION);
gnome_vfs_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_SAVE_AUTHENTICATION);
+ gnome_vfs_module_callback_pop (GNOME_VFS_MODULE_CALLBACK_QUESTION);
}
Index: sftp-method.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/sftp-method.c,v
retrieving revision 1.5
diff -u -r1.5 sftp-method.c
--- sftp-method.c 8 Mar 2004 18:53:47 -0000 1.5
+++ sftp-method.c 8 Apr 2004 11:07:57 -0000
@@ -944,7 +944,10 @@
GError *error = NULL;
gchar *args[20]; /* Enough for now, extend if you add more args */
-
+ gboolean invoked;
+ GnomeVFSModuleCallbackQuestionIn in_args;
+ GnomeVFSModuleCallbackQuestionOut out_args;
+
DEBUG (gchar *tmp);
/* Fill in the first few args */
@@ -1083,11 +1086,41 @@
}
done_auth = TRUE;
} else if (g_str_has_prefix (buffer, "The authenticity of host")) {
- /* FIXME: This should do a callback asking the user if the host id is ok */
- /* For now we just fail */
- res = GNOME_VFS_ERROR_ACCESS_DENIED;
- goto bail;
- }
+ //FIXME: Don't use message. Create a better translatable
+ // message to present to the user.
+ in_args.message = buffer;
+ in_args.choices = g_new(char *, 3);
+ //FIXME: Add stuff to translate the strings.
+ in_args.choices[0] = "Cancel";
+ in_args.choices[1] = "Accept New Host Key";
+ in_args.choices[2] = NULL;
+
+ invoked = gnome_vfs_module_callback_invoke
+ (GNOME_VFS_MODULE_CALLBACK_QUESTION,
+ &in_args, sizeof (in_args),
+ &out_args, sizeof (out_args));
+
+ if (invoked) {
+ if (out_args.answer == 1) {
+ g_io_channel_write_chars (tty_channel, "yes\n", -1, &len, NULL);
+ } else if (out_args.answer == 0) {
+ g_io_channel_write_chars (tty_channel, "no\n", -1, &len, NULL);
+ } else {
+ g_io_channel_write_chars (tty_channel, "no\n", -1, &len, NULL);
+ res = GNOME_VFS_ERROR_GENERIC;
+ goto bail;
+ }
+ g_io_channel_flush (tty_channel, NULL);
+ buffer[0]='\0';
+ } else {
+ g_io_channel_write_chars (tty_channel, "no\n", -1, &len, NULL);
+ g_io_channel_flush (tty_channel, NULL);
+ buffer[0]='\0';
+ res = GNOME_VFS_ERROR_ACCESS_DENIED;
+ goto bail;
+ }
+ }
+
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]