summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2008-10-12 12:17:53 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2008-10-12 12:17:53 +0200
commitfc649fb9d8d2edd3eef0ba6ba54b769c956ab3cb (patch)
treebd06d1167bb04e03871eaa18bbe5ac560da83cc3
parentd7f3e7e44eb7ccb2026da7006c254e5c4c60c3ce (diff)
downloadtuxcmd-modules-0.6.53.tar.xz
GVFS plugin: Implement question and password callbacksv0.6.53
-rw-r--r--common/vfs_types.h36
-rw-r--r--gvfs/gvfs.c228
2 files changed, 200 insertions, 64 deletions
diff --git a/common/vfs_types.h b/common/vfs_types.h
index 753f5c5..583ffe6 100644
--- a/common/vfs_types.h
+++ b/common/vfs_types.h
@@ -30,11 +30,47 @@
typedef int TVFSResult;
+/* Compatible with gio/GAskPasswordFlags */
+typedef enum {
+ VFS_ASK_PASSWORD_NEED_PASSWORD = 1<<0,
+ VFS_ASK_PASSWORD_NEED_USERNAME = 1<<1,
+ VFS_ASK_PASSWORD_NEED_DOMAIN = 1<<2,
+ VFS_ASK_PASSWORD_SAVING_SUPPORTED = 1<<3,
+ VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED = 1<<4
+} TVFSAskPasswordFlags;
+
+/* Compatible with gio/GPasswordSave */
+typedef enum {
+ VFS_PASSWORD_SAVE_NEVER,
+ VFS_PASSWORD_SAVE_FOR_SESSION,
+ VFS_PASSWORD_SAVE_PERMANENTLY
+} TVFSPasswordSave;
+
typedef void (* TVFSLogFunc)(char *s);
typedef int (* TVFSCopyCallBackFunc)(u_int64_t iPos, u_int64_t iMax, void *data);
typedef void *TVFSFileDes;
+/* Return index of the choice selected or negative number when dialog has been cancelled */
+typedef void (* TVFSAskQuestionCallback)
+ (const char *message,
+ const char *choices[],
+ int *choice,
+ void *user_data);
+
+typedef int (* TVFSAskPasswordCallback)
+ (const char *message,
+ const char *default_user,
+ const char *default_domain,
+ TVFSAskPasswordFlags flags,
+ char **username,
+ char **password,
+ int *anonymous,
+ char **domain,
+ TVFSPasswordSave *password_save,
+ void *user_data);
+
+
static const int cVFSVersion = 4; // current version of the VFS API
// Capabilities
diff --git a/gvfs/gvfs.c b/gvfs/gvfs.c
index 8ffa70e..5baef7d 100644
--- a/gvfs/gvfs.c
+++ b/gvfs/gvfs.c
@@ -31,10 +31,9 @@
-#define VERSION "0.1.1"
-#define BUILD_DATE "2008-10-06"
+#define VERSION "0.1.2"
+#define BUILD_DATE "2008-10-11"
#define DEFAULT_BLOCK_SIZE 0x10000 /* 64kB */
-#define ANON_FTP_PASS "ftpuser@tuxcmd.net"
#define CONST_DEFAULT_QUERY_INFO_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME "," \
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," \
@@ -51,10 +50,15 @@ struct TVFSGlobs {
GMainLoop *mount_main_loop;
TVFSResult mount_result;
gchar *mount_password;
+ int mount_try;
gboolean ftp_anonymous;
gboolean break_get_dir_size;
guint32 block_size;
+
+ TVFSAskQuestionCallback callback_ask_question;
+ TVFSAskPasswordCallback callback_ask_password;
+ void *callbacks_data;
};
@@ -123,42 +127,108 @@ ask_password_cb (GMountOperation *op,
gpointer user_data)
{
struct TVFSGlobs *globs;
+ char *username;
+ char *password;
+ int anonymous;
+ char *domain;
+ TVFSPasswordSave password_save;
+ int result;
+
globs = (struct TVFSGlobs*) user_data;
g_assert (globs != NULL);
+ globs->mount_try++;
+
+ /* First pass, we have a password to supply */
+ if (globs->mount_try == 1) {
+ if ((flags & G_ASK_PASSWORD_NEED_PASSWORD) && globs->mount_password) {
+ printf ("(WW) ask_password_cb: mount_try = %d, setting password extracted from URI...\n", globs->mount_try);
+ g_mount_operation_set_password (op, globs->mount_password);
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
+ return;
+ } else
+ if ((flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED) && globs->ftp_anonymous) {
+ printf ("(WW) ask_password_cb: mount_try = %d, trying FTP anonymous login...\n", globs->mount_try);
+ g_mount_operation_set_anonymous (op, TRUE);
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
+ return;
+ }
+ }
- g_print ("(WW) ask_password_cb: message = '%s'\n", message);
- if (globs->ftp_anonymous)
- g_print ("(II) Trying anonymous FTP login...\n");
+ /* Ask user for password */
+ g_print ("(WW) ask_password_cb: mount_try = %d, message = '%s'\n", globs->mount_try, message);
+
+ username = NULL;
+ domain = NULL;
+ password = NULL;
+ anonymous = FALSE;
+ password_save = VFS_PASSWORD_SAVE_NEVER;
+
+ if (globs->callback_ask_password) {
+ fprintf (stderr, " (II) Spawning callback_ask_password (0x%.16llX)...\n", (unsigned long long) globs->callback_ask_password);
+ result = globs->callback_ask_password (message, default_user, default_domain, flags,
+ &username, &password, &anonymous, &domain, &password_save,
+ globs->callbacks_data);
+ fprintf (stderr, " (II) Received result = %d\n", result);
+ if (result) {
+ if (flags & G_ASK_PASSWORD_NEED_USERNAME)
+ g_mount_operation_set_username (op, username);
+ if (flags & G_ASK_PASSWORD_NEED_DOMAIN)
+ g_mount_operation_set_domain (op, domain);
+ if (flags & G_ASK_PASSWORD_NEED_PASSWORD)
+ g_mount_operation_set_password (op, password);
+ if (flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED)
+ g_mount_operation_set_anonymous (op, anonymous);
+ if (flags & G_ASK_PASSWORD_SAVING_SUPPORTED)
+ g_mount_operation_set_password_save (op, password_save);
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
+ }
+ else
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED);
+ return;
+ }
+ /* Unhandled, abort */
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED);
+}
- if (flags & G_ASK_PASSWORD_NEED_USERNAME)
- {
- g_print (" need username...\n");
- if (globs->ftp_anonymous)
- g_mount_operation_set_username (op, "anonymous");
+static void
+ask_question_cb (GMountOperation *op,
+ const gchar *message,
+ const gchar *choices[],
+ gpointer user_data)
+{
+ struct TVFSGlobs *globs;
+ int len;
+ int choice;
-/* FIXME: need proper API to spawn a callback
- g_mount_operation_set_username (op, s); */
- }
+ globs = (struct TVFSGlobs*) user_data;
+ g_assert (globs != NULL);
- if (flags & G_ASK_PASSWORD_NEED_DOMAIN)
- {
- g_print (" need domain...\n");
-/* FIXME: need proper API to spawn a callback
- g_mount_operation_set_domain (op, s); */
- }
+ g_print ("(WW) ask_question_cb: message = '%s'\n", message);
- if (flags & G_ASK_PASSWORD_NEED_PASSWORD)
- {
- g_print (" need password...\n");
- if (globs->mount_password)
- g_mount_operation_set_password (op, globs->mount_password);
- else
- if (globs->ftp_anonymous)
- g_mount_operation_set_password (op, ANON_FTP_PASS);
+ len = 0;
+ while (choices[len] != NULL) {
+ g_print ("(WW) ask_question_cb: choice[%d] = '%s'\n", len, choices[len]);
+ len++;
+ }
+
+ choice = -1;
+ if (globs->callback_ask_question) {
+ fprintf (stderr, " (II) Spawning callback_ask_question (0x%.16llX)...\n", (unsigned long long) globs->callback_ask_question);
+ globs->callback_ask_question (message, choices, &choice, globs->callbacks_data);
+ fprintf (stderr, " (II) Received choice = %d\n", choice);
+
+ if (choice >= 0) {
+ g_mount_operation_set_choice (op, choice);
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
+ }
+ else {
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED);
}
+ return;
+ }
- g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_UNHANDLED);
}
static void
@@ -196,8 +266,10 @@ vfs_handle_mount (struct TVFSGlobs *globs, GFile *file)
g_print ("(II) Mounting location...\n");
op = g_mount_operation_new ();
- g_signal_connect (op, "ask_password", (GCallback)ask_password_cb, globs);
+ g_signal_connect (op, "ask-password", (GCallback)ask_password_cb, globs);
+ g_signal_connect (op, "ask-question", (GCallback)ask_question_cb, globs);
globs->mount_result = cVFS_Failed;
+ globs->mount_try = 0;
/* Inspiration taken from Bastien Nocera's http://svn.gnome.org/viewvc/totem-pl-parser/trunk/plparse/totem-disc.c?view=markup */
globs->mount_main_loop = g_main_loop_new (NULL, FALSE);
@@ -228,10 +300,25 @@ VFSNew (TVFSLogFunc log_func)
globs->break_get_dir_size = FALSE;
globs->block_size = DEFAULT_BLOCK_SIZE;
+ globs->callbacks_data = NULL;
+ globs->callback_ask_question = NULL;
+ globs->callback_ask_password = NULL;
+
return globs;
}
void
+VFSSetCallbacks (struct TVFSGlobs *globs,
+ TVFSAskQuestionCallback ask_question_callback,
+ TVFSAskPasswordCallback ask_password_callback,
+ void *data)
+{
+ globs->callback_ask_question = ask_question_callback;
+ globs->callback_ask_password = ask_password_callback;
+ globs->callbacks_data = data;
+}
+
+void
VFSFree (struct TVFSGlobs *globs)
{
globs->log_func ("GVFS plugin: VFSDestroy");
@@ -292,7 +379,6 @@ VFSOpen (struct TVFSGlobs *globs, char *sName)
GFileInfo *info;
GError *error;
TVFSResult res;
- gboolean try_again;
gchar **uri_matched;
char *uri_schema, *uri_username, *uri_password, *uri_service;
gchar *uri;
@@ -358,28 +444,27 @@ VFSOpen (struct TVFSGlobs *globs, char *sName)
globs->ftp_anonymous = strcasestr (sName, "ftp://") == sName;
}
-
g_print ("(II) VFSOpen: opening URI '%s'\n", uri ? uri : sName);
f = g_file_new_for_commandline_arg (uri ? uri : sName);
if (uri)
g_free (uri);
- try_again = FALSE;
while (1) {
error = NULL;
info = g_file_query_info (f, CONST_DEFAULT_QUERY_INFO_ATTRIBUTES,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error);
+
/* Fallback to parent directory if specified path doesn't exist */
if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
f2 = g_file_get_parent (f);
if (f2) {
g_object_unref (f);
f = f2;
- try_again = TRUE;
g_error_free (error);
continue;
}
}
+ /* Mount the target */
if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) {
g_error_free (error);
error = NULL;
@@ -389,6 +474,7 @@ VFSOpen (struct TVFSGlobs *globs, char *sName)
else
continue;
}
+ /* Any other errors --> report */
if (error) {
g_print ("(EE) VFSOpen: g_file_query_info() error: %s\n", error->message);
res = g_error_to_TVFSResult (error);
@@ -513,41 +599,55 @@ VFSChangeDir (struct TVFSGlobs *globs, char *NewPath)
return cVFS_Failed;
}
- error = NULL;
res = cVFS_OK;
- en = g_file_enumerate_children (f, CONST_DEFAULT_QUERY_INFO_ATTRIBUTES,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error);
-
- /* if the target is shortcut, change the URI */
- if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY)) {
- error_shortcut = NULL;
- info = g_file_query_info (f, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error_shortcut);
- if (info) {
- target_uri = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI));
- g_object_unref (info);
- if (target_uri) {
- g_print ("(WW) VFSChangeDir: following shortcut, changing URI to '%s'\n", target_uri);
+ while (1) {
+ error = NULL;
+ en = g_file_enumerate_children (f, CONST_DEFAULT_QUERY_INFO_ATTRIBUTES,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error);
+
+ /* if the target is shortcut, change the URI */
+ if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY)) {
+ error_shortcut = NULL;
+ info = g_file_query_info (f, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error_shortcut);
+ if (info) {
+ target_uri = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI));
+ g_object_unref (info);
+ if (target_uri) {
+ g_print ("(WW) VFSChangeDir: following shortcut, changing URI to '%s'\n", target_uri);
+ g_object_unref (f);
+ f = g_file_new_for_uri (target_uri);
+ g_free (target_uri);
+ g_error_free (error);
+ continue;
+ }
+ }
+ if (error_shortcut)
+ g_error_free (error_shortcut);
+ }
+ /* Mount the target */
+ if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) {
+ g_error_free (error);
+ res = vfs_handle_mount (globs, f);
+ if (res != cVFS_OK) {
g_object_unref (f);
- f = g_file_new_for_uri (target_uri);
- g_free (target_uri);
- g_error_free (error);
- error = NULL;
- en = g_file_enumerate_children (f, CONST_DEFAULT_QUERY_INFO_ATTRIBUTES,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error);
+ return res;
}
+ else
+ continue;
}
- if (error_shortcut)
- g_error_free (error_shortcut);
+ /* Any other errors --> report */
+ if (error) {
+ g_print ("(EE) VFSChangeDir: g_file_enumerate_children() error: %s\n", error->message);
+ res = g_error_to_TVFSResult (error);
+ g_error_free (error);
+ g_object_unref (f);
+ return res;
+ }
+ /* everything ok? */
+ break;
}
- if (error) {
- g_print ("(EE) VFSChangeDir: g_file_enumerate_children() error: %s\n", error->message);
- res = g_error_to_TVFSResult (error);
- g_error_free (error);
- g_object_unref (f);
- return res;
- }
globs->enumerator = en;
g_object_unref (globs->file);
globs->file = f;
@@ -1372,6 +1472,6 @@ VFSCopyIn (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName,
* - block size settings for GIO subsystem
* - variable block size for different protocols?
* - support for appending in VFSCopyIn
- * - authentication improvements (needs new VFS API)
+ * DONE- authentication improvements (needs new VFS API)
*
***/