summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kellner <gicmo@gnome.org>2008-01-17 19:00:39 +0000
committerChristian Kellner <gicmo@src.gnome.org>2008-01-17 19:00:39 +0000
commit9ffa2307efdf372ecb10aed76807661ff3a56963 (patch)
tree952f99d6bdc8972e15f37752ca6ed2e4b2c67294
parent8f8f428f0d823f1364a9dc4fb100a7f52af633b9 (diff)
downloadgvfs-9ffa2307efdf372ecb10aed76807661ff3a56963.tar.gz
Make g_mount_source_ask_password_async () public and add
2008-01-17 Christian Kellner <gicmo@gnome.org> * common/gmountsource.c: * common/gmountsource.h: Make g_mount_source_ask_password_async () public and add g_mount_source_ask_password_finish (). * daemon/gvfsbackenddav.c: Use g_mount_source_ask_password_async instead of the sync version so we don't hang during auth. Few cleanups. * programs/gvfs-mount.c: Don't echo the password, if possible. svn path=/trunk/; revision=1146
-rw-r--r--ChangeLog14
-rw-r--r--common/gmountsource.c261
-rw-r--r--common/gmountsource.h17
-rw-r--r--daemon/gvfsbackenddav.c355
-rw-r--r--programs/gvfs-mount.c44
5 files changed, 482 insertions, 209 deletions
diff --git a/ChangeLog b/ChangeLog
index e9a71c2b..54f9206d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-01-17 Christian Kellner <gicmo@gnome.org>
+
+ * common/gmountsource.c:
+ * common/gmountsource.h:
+ Make g_mount_source_ask_password_async () public and add
+ g_mount_source_ask_password_finish ().
+
+ * daemon/gvfsbackenddav.c:
+ Use g_mount_source_ask_password_async instead of the sync
+ version so we don't hang during auth. Few cleanups.
+
+ * programs/gvfs-mount.c:
+ Don't echo the password, if possible.
+
2008-01-17 Alexander Larsson <alexl@redhat.com>
* hal/ghalvolume.c:
diff --git a/common/gmountsource.c b/common/gmountsource.c
index 0ee8c243..4126280e 100644
--- a/common/gmountsource.c
+++ b/common/gmountsource.c
@@ -122,33 +122,55 @@ g_mount_source_get_obj_path (GMountSource *mount_source)
typedef struct AskPasswordData AskPasswordData;
struct AskPasswordData {
- void (*callback)(AskPasswordData *data);
+
+ /* results: */
+ gboolean aborted;
+ char *password;
+ char *username;
+ char *domain;
+};
+
+typedef struct AskPasswordSyncData AskPasswordSyncData;
+
+struct AskPasswordSyncData {
+
/* For sync calls */
GMutex *mutex;
GCond *cond;
- /* For async calls */
- GMountOperation *op;
/* results: */
- gboolean handled;
- gboolean aborted;
- char *password;
- char *username;
- char *domain;
-} ;
+ GAsyncResult *result;
+};
static void
+ask_password_data_free (gpointer _data)
+{
+ AskPasswordData *data = (AskPasswordData *) _data;
+ g_free (data->password);
+ g_free (data->username);
+ g_free (data->domain);
+ g_free (data);
+}
+
+/* the callback from dbus -> main thread */
+static void
ask_password_reply (DBusMessage *reply,
- GError *error,
- gpointer _data)
+ GError *error,
+ gpointer _data)
{
- AskPasswordData *data = _data;
+ GSimpleAsyncResult *result;
+ AskPasswordData *data;
dbus_bool_t handled, aborted, anonymous;
guint32 password_save;
const char *password, *username, *domain;
DBusMessageIter iter;
- data->handled = TRUE;
+ result = G_SIMPLE_ASYNC_RESULT (_data);
+ handled = TRUE;
+
+ data = g_new0 (AskPasswordData, 1);
+ g_simple_async_result_set_op_res_gpointer (result, data, ask_password_data_free);
+
if (reply == NULL)
{
data->aborted = TRUE;
@@ -168,7 +190,6 @@ ask_password_reply (DBusMessage *reply,
data->aborted = TRUE;
else
{
- data->handled = handled;
data->aborted = aborted;
data->password = g_strdup (password);
@@ -179,38 +200,35 @@ ask_password_reply (DBusMessage *reply,
}
}
- data->callback (data);
-}
-
-static gboolean
-password_non_handled_in_idle (gpointer _data)
-{
- AskPasswordData *data = _data;
+ if (handled == FALSE)
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, NULL);
+ }
- data->callback (data);
- return FALSE;
+ g_simple_async_result_complete (result);
}
-static void
-g_mount_source_ask_password_async (GMountSource *source,
- const char *message_string,
- const char *default_user,
- const char *default_domain,
- GAskPasswordFlags flags,
- AskPasswordData *data)
+void
+g_mount_source_ask_password_async (GMountSource *source,
+ const char *message_string,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
+ GSimpleAsyncResult *result;
DBusMessage *message;
guint32 flags_as_int;
+
/* If no dbus id specified, reply that we weren't handled */
if (source->dbus_id[0] == 0)
- {
- data->handled = FALSE;
-
- g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
- password_non_handled_in_idle,
- data,
- NULL);
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (source),
+ callback,
+ user_data,
+ G_IO_ERROR, G_IO_ERROR_FAILED, NULL);
return;
}
@@ -235,16 +253,72 @@ g_mount_source_ask_password_async (GMountSource *source,
DBUS_TYPE_UINT32, &flags_as_int,
0);
+ result = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+ g_mount_source_ask_password_async);
/* 30 minute timeout */
_g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
- ask_password_reply, data);
+ ask_password_reply, result);
dbus_message_unref (message);
+
+}
+
+gboolean
+g_mount_source_ask_password_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out)
+{
+ AskPasswordData *data;
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, NULL))
+ return FALSE;
+
+ data = (AskPasswordData *) g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (aborted)
+ *aborted = data->aborted;
+
+ if (password_out)
+ {
+ *password_out = data->password;
+ data->password = NULL;
+ }
+
+ if (user_out)
+ {
+ *user_out = data->username;
+ data->username = NULL;
+ }
+
+ if (domain_out)
+ {
+ *domain_out = data->domain;
+ data->domain = NULL;
+ }
+
+ return TRUE;
}
static void
-ask_password_reply_sync (AskPasswordData *data)
+ask_password_reply_sync (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
+ GMountSource *source;
+ AskPasswordSyncData *data;
+
+ source = G_MOUNT_SOURCE (source_object);
+
+ data = (AskPasswordSyncData *) user_data;
+
+ data->result = g_object_ref (res);
+
/* Wake up sync call thread */
g_mutex_lock (data->mutex);
g_cond_signal (data->cond);
@@ -257,13 +331,15 @@ g_mount_source_ask_password (GMountSource *source,
const char *default_user,
const char *default_domain,
GAskPasswordFlags flags,
- gboolean *aborted,
+ gboolean *aborted_out,
char **password_out,
char **user_out,
char **domain_out)
{
- AskPasswordData data = {NULL};
-
+ char *password, *username, *domain;
+ gboolean handled, aborted;
+ AskPasswordSyncData data = {NULL};
+
if (password_out)
*password_out = NULL;
if (user_out)
@@ -273,17 +349,17 @@ g_mount_source_ask_password (GMountSource *source,
data.mutex = g_mutex_new ();
data.cond = g_cond_new ();
- data.callback = ask_password_reply_sync;
g_mutex_lock (data.mutex);
g_mount_source_ask_password_async (source,
- message_string,
- default_user,
- default_domain,
- flags,
- &data);
+ message_string,
+ default_user,
+ default_domain,
+ flags,
+ ask_password_reply_sync,
+ &data);
g_cond_wait(data.cond, data.mutex);
g_mutex_unlock (data.mutex);
@@ -291,52 +367,80 @@ g_mount_source_ask_password (GMountSource *source,
g_cond_free (data.cond);
g_mutex_free (data.mutex);
- if (aborted)
- *aborted = data.aborted;
+
+ handled = g_mount_source_ask_password_finish (source,
+ data.result,
+ &aborted,
+ &password,
+ &username,
+ &domain);
+ g_object_unref (data.result);
+
+ if (aborted_out)
+ *aborted_out = aborted;
+
if (password_out)
- *password_out = data.password;
+ *password_out = password;
else
- g_free (data.password);
+ g_free (password);
+
if (user_out)
- *user_out = data.username;
+ *user_out = username;
else
- g_free (data.username);
+ g_free (username);
+
if (domain_out)
- *domain_out = data.domain;
+ *domain_out = domain;
else
- g_free (data.domain);
+ g_free (domain);
- return data.handled;
+ return handled;
}
static void
-ask_password_reply_async (AskPasswordData *data)
+op_ask_password_reply (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
GMountOperationResult result;
+ GMountOperation *op;
+ GMountSource *source;
+ gboolean handled, aborted;
+ char *username;
+ char *password;
+ char *domain;
+
+ source = G_MOUNT_SOURCE (source_object);
+ op = G_MOUNT_OPERATION (user_data);
+ username = NULL;
+ password = NULL;
+ domain = NULL;
- if (!data->handled)
+ handled = g_mount_source_ask_password_finish (source,
+ res,
+ &aborted,
+ &username,
+ &password,
+ &domain);
+
+ if (!handled)
result = G_MOUNT_OPERATION_UNHANDLED;
- else if (data->aborted)
+ else if (aborted)
result = G_MOUNT_OPERATION_ABORTED;
else
{
result = G_MOUNT_OPERATION_HANDLED;
- if (data->password)
- g_mount_operation_set_password (data->op,
- data->password);
- if (data->username)
- g_mount_operation_set_username (data->op,
- data->username);
- if (data->domain)
- g_mount_operation_set_domain (data->op,
- data->domain);
+ if (password)
+ g_mount_operation_set_password (op, password);
+ if (username)
+ g_mount_operation_set_username (op, username);
+ if (domain)
+ g_mount_operation_set_domain (op, domain);
}
- g_mount_operation_reply (data->op, result);
-
- g_object_unref (data->op);
- g_free (data);
+ g_mount_operation_reply (op, result);
+ g_object_unref (op);
}
static gboolean
@@ -347,18 +451,13 @@ op_ask_password (GMountOperation *op,
GAskPasswordFlags flags,
GMountSource *mount_source)
{
- AskPasswordData *data;
-
- data = g_new0 (AskPasswordData, 1);
- data->callback = ask_password_reply_async;
- data->op = g_object_ref (op);
-
g_mount_source_ask_password_async (mount_source,
message,
default_user,
default_domain,
- flags,
- data);
+ flags,
+ op_ask_password_reply,
+ g_object_ref (op));
return TRUE;
}
diff --git a/common/gmountsource.h b/common/gmountsource.h
index f1075970..bad54918 100644
--- a/common/gmountsource.h
+++ b/common/gmountsource.h
@@ -65,6 +65,23 @@ gboolean g_mount_source_ask_password (GMountSource
char **password_out,
char **user_out,
char **domain_out);
+
+void g_mount_source_ask_password_async (GMountSource *mount_source,
+ const char *message,
+ const char *initial_user,
+ const char *initial_domain,
+ GAskPasswordFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean g_mount_source_ask_password_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out);
+
+
const char * g_mount_source_get_dbus_id (GMountSource *mount_source);
const char * g_mount_source_get_obj_path (GMountSource *mount_source);
diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c
index bca998c0..8e756fbb 100644
--- a/daemon/gvfsbackenddav.c
+++ b/daemon/gvfsbackenddav.c
@@ -64,9 +64,6 @@ struct _GVfsBackendDav
{
GVfsBackendHttp parent_instance;
- /* Only used during mount: */
- char *last_good_path;
- GMountSource *mount_source;
};
G_DEFINE_TYPE (GVfsBackendDav, g_vfs_backend_dav, G_VFS_TYPE_BACKEND_HTTP);
@@ -187,9 +184,12 @@ node_has_name (xmlNodePtr node, const char *name)
}
static xmlDocPtr
-multistatus_parse_xml (SoupMessage *msg, xmlNodePtr *root, GError **error)
+parse_xml (SoupMessage *msg,
+ xmlNodePtr *root,
+ const char *name,
+ GError **error)
{
- xmlDocPtr doc;
+ xmlDocPtr doc;
if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
{
@@ -220,7 +220,7 @@ multistatus_parse_xml (SoupMessage *msg, xmlNodePtr *root, GError **error)
return NULL;
}
- if (strcmp ((char *) (*root)->name, "multistatus"))
+ if (strcmp ((char *) (*root)->name, name))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Unexpected reply from server"));
@@ -230,6 +230,14 @@ multistatus_parse_xml (SoupMessage *msg, xmlNodePtr *root, GError **error)
return doc;
}
+
+static xmlDocPtr
+multistatus_parse_xml (SoupMessage *msg, xmlNodePtr *root, GError **error)
+{
+ return parse_xml (msg, root, "multistatus", error);
+}
+
+
static GFileType
parse_resourcetype (xmlNodePtr rt)
{
@@ -256,57 +264,80 @@ parse_resourcetype (xmlNodePtr rt)
return type;
}
+static const char *
+node_get_content (xmlNodePtr node)
+{
+ if (node == NULL)
+ return NULL;
+
+ switch (node->type)
+ {
+ case XML_ELEMENT_NODE:
+ return node_get_content (node->children);
+ break;
+ case XML_TEXT_NODE:
+ return (const char *) node->content;
+ break;
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
static GFileInfo *
mulitstatus_parse_prop_node (xmlDocPtr doc, xmlNodePtr prop)
{
GFileInfo *info;
xmlNodePtr node;
+ const char *text;
+ GTimeVal tv;
info = g_file_info_new ();
+
for (node = prop->children; node; node = node->next)
{
if (node->type != XML_ELEMENT_NODE ||
- node->name == NULL)
+ node->name == NULL)
{
continue;
}
- else if (!strcmp ((char *) node->name, "resourcetype"))
+
+ text = node_get_content (node);
+
+ if (node_has_name (node, "resourcetype"))
{
GFileType type = parse_resourcetype (node);
g_file_info_set_file_type (info, type);
}
- else if (!strcmp ((char *) node->name, "displayname"))
+ else if (node_has_name (node, "displayname"))
{
- xmlChar *text;
- text = xmlNodeGetContent (node);
- g_file_info_set_display_name (info, (char *) text);
- xmlFree (text);
+ g_file_info_set_display_name (info, text);
}
- else if (!strcmp ((char *) node->name, "getetag"))
+ else if (node_has_name (node, "getetag"))
{
-
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE,
+ text);
}
- else if (!strcmp ((char *) node->name, "creationdate"))
+ else if (node_has_name (node, "creationdate"))
{
-
+
}
- else if (!strcmp ((char *) node->name, "getcontenttype"))
+ else if (node_has_name (node, "getcontenttype"))
{
- xmlChar *text;
- text = xmlNodeGetContent (node);
- g_file_info_set_content_type (info, (char *) text);
- xmlFree (text);
+ g_file_info_set_content_type (info, text);
}
- else if (!strcmp ((char *) node->name, "getcontentlength"))
+ else if (node_has_name (node, "getcontentlength"))
{
- gint64 size;
- xmlChar *text;
- text = xmlNodeGetContent (node);
- size = g_ascii_strtoll ((char *) text, NULL, 10);
- xmlFree (text);
+ gint64 size;
+ size = g_ascii_strtoll (text, NULL, 10);
g_file_info_set_size (info, size);
}
+ else if (node_has_name (node, "getlastmodified"))
+ {
+ if (g_time_val_from_iso8601 (text, &tv))
+ g_file_info_set_modification_time (info, &tv);
+ }
}
return info;
}
@@ -333,11 +364,10 @@ multistatus_parse_response (xmlDocPtr doc,
}
else if (! strcmp ((char *) node->name, "href"))
{
- xmlChar *text;
+ const char *text;
- text = xmlNodeGetContent (node);
- name = uri_get_basename ((char *) text);
- xmlFree (text);
+ text = node_get_content (node);
+ name = uri_get_basename (text);
}
else if (! strcmp ((char *) node->name, "propstat"))
@@ -449,76 +479,157 @@ create_propfind_request (GFileAttributeMatcher *matcher, gulong *size)
return res;
}
+
/* ************************************************************************* */
/* */
+
+typedef struct _MountOpData {
+
+ SoupSession *session;
+ GMountSource *mount_source;
+
+ char *last_good_path;
+
+ /* general authentication */
+
+ SoupMessage *message;
+ SoupAuth *auth;
+
+ /* for server authentication */
+ char *username;
+ char *password;
+ char *last_realm;
+
+ /* for proxy authentication */
+ char *proxy_user;
+ char *proxy_password;
+
+} MountOpData;
+
+static void
+mount_op_data_free (gpointer _data)
+{
+ MountOpData *data;
+
+ data = (MountOpData *) _data;
+
+ g_free (data->last_good_path);
+
+ if (data->mount_source)
+ g_object_unref (data->mount_source);
+
+ if (data->message)
+ g_object_unref (data->message);
+
+ if (data->auth)
+ g_object_unref (data->auth);
+
+ g_free (data->username);
+ g_free (data->password);
+ g_free (data->last_realm);
+ g_free (data->proxy_user);
+ g_free (data->proxy_password);
+
+ g_free (data);
+}
+
+static void
+ask_password_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ MountOpData *data;
+ char *username;
+ char *password;
+ gboolean aborted;
+ gboolean res;
+
+ data = (MountOpData *) user_data;
+ username = password = NULL;
+
+ res = g_mount_source_ask_password_finish (data->mount_source,
+ result,
+ &aborted,
+ &password,
+ &username,
+ NULL);
+
+ if (res && !aborted)
+ soup_auth_authenticate (data->auth, username, password);
+
+ soup_session_unpause_message (data->session, data->message);
+
+ g_free (username);
+ g_free (password);
+
+ g_object_unref (data->message);
+ g_object_unref (data->auth);
+
+ data->message = NULL;
+ data->auth = NULL;
+}
+
static void
soup_authenticate (SoupSession *session,
SoupMessage *msg,
SoupAuth *auth,
gboolean retrying,
- gpointer data)
+ gpointer user_data)
{
- GVfsBackendDav *backend;
- GVfsJobMount *job;
- SoupURI *mount_base;
- gboolean res;
- gboolean aborted;
- const char *auth_realm;
+ MountOpData *data;
+ const char *username;
+ const char *password;
char *prompt;
- char *new_password;
- char *new_user;
-
- job = G_VFS_JOB_MOUNT (data);
- backend = G_VFS_BACKEND_DAV (job->backend);
- mount_base = G_VFS_BACKEND_HTTP (backend)->mount_base;
- auth_realm = soup_auth_get_realm (auth);
+ data = (MountOpData *) user_data;
- if (auth_realm == NULL)
- auth_realm = _("WebDAV share");
+ if (soup_auth_is_for_proxy (auth))
+ {
+ username = data->proxy_user;
+ password = retrying ? NULL : data->proxy_password;
+ }
+ else
+ {
+ username = data->username;
+ password = retrying ? NULL : data->password;
+ }
- prompt = g_strdup_printf (_("Enter password for %s"), auth_realm);
+ if (username && password)
+ {
+ soup_auth_authenticate (auth, username, password);
+ return;
+ }
- new_user = new_password = NULL;
-
- res = g_mount_source_ask_password (backend->mount_source,
- prompt,
- mount_base->user,
- NULL,
- G_ASK_PASSWORD_NEED_PASSWORD |
- G_ASK_PASSWORD_NEED_USERNAME,
- &aborted,
- &new_password,
- &new_user,
- NULL);
- if (res && !aborted)
+ if (soup_auth_is_for_proxy (auth))
{
- soup_auth_authenticate (auth, new_user, new_password);
+ prompt = g_strdup (_("Please enter proxy password"));
}
+ else
+ {
+ const char *auth_realm;
- g_free (new_user);
- g_free (new_password);
- g_free (prompt);
-}
+ auth_realm = soup_auth_get_realm (auth);
-static void discover_mount_root_ready (SoupSession *session,
- SoupMessage *msg,
- gpointer user_data);
-static void
-discover_mount_root (GVfsBackendDav *backend, GVfsJobMount *job)
-{
- GVfsBackendHttp *http_backend;
- SoupMessage *msg;
- SoupSession *session;
- SoupURI *mount_base;
+ if (auth_realm == NULL)
+ auth_realm = _("WebDAV share");
- http_backend = G_VFS_BACKEND_HTTP (backend);
- mount_base = http_backend->mount_base;
- session = http_backend->session;
+ prompt = g_strdup_printf (_("Enter password for %s"), auth_realm);
+ }
- msg = soup_message_new_from_uri (SOUP_METHOD_OPTIONS, mount_base);
- soup_message_headers_append (msg->request_headers, "User-Agent", "gvfs/" VERSION);
- soup_session_queue_message (session, msg, discover_mount_root_ready, job);
+ data->auth = g_object_ref (auth);
+ data->message = g_object_ref (msg);
+
+ soup_session_pause_message (data->session, msg);
+
+ g_mount_source_ask_password_async (data->mount_source,
+ prompt,
+ username,
+ NULL,
+ G_ASK_PASSWORD_NEED_PASSWORD |
+ G_ASK_PASSWORD_NEED_USERNAME,
+ ask_password_ready,
+ data);
+ g_free (prompt);
}
static void
@@ -528,6 +639,7 @@ discover_mount_root_ready (SoupSession *session,
{
GVfsBackendDav *backend;
GVfsJobMount *job;
+ MountOpData *data;
GMountSpec *mount_spec;
SoupURI *mount_base;
gboolean is_success;
@@ -536,6 +648,7 @@ discover_mount_root_ready (SoupSession *session,
job = G_VFS_JOB_MOUNT (user_data);
backend = G_VFS_BACKEND_DAV (job->backend);
mount_base = G_VFS_BACKEND_HTTP (backend)->mount_base;
+ data = (MountOpData *) G_VFS_JOB (job)->backend_data;
is_success = SOUP_STATUS_IS_SUCCESSFUL (msg->status_code);
is_dav = sm_has_header (msg, "DAV");
@@ -544,12 +657,16 @@ discover_mount_root_ready (SoupSession *session,
if (is_success && is_dav)
{
- backend->last_good_path = mount_base->path;
+
+ data->last_good_path = mount_base->path;
mount_base->path = path_get_parent_dir (mount_base->path);
if (mount_base->path)
{
- discover_mount_root (backend, job);
+ SoupMessage *msg;
+ msg = message_new_from_uri (SOUP_METHOD_OPTIONS, mount_base);
+ soup_session_queue_message (session, msg,
+ discover_mount_root_ready, job);
return;
}
}
@@ -558,7 +675,7 @@ discover_mount_root_ready (SoupSession *session,
* chdir up to (or couldn't chdir up at all) */
/* check if we at all have a good path */
- if (backend->last_good_path == NULL)
+ if (data->last_good_path == NULL)
{
if (!is_success)
g_vfs_job_failed (G_VFS_JOB (job),
@@ -572,7 +689,11 @@ discover_mount_root_ready (SoupSession *session,
return;
}
+ g_free (mount_base->path);
+ mount_base->path = data->last_good_path;
+ data->last_good_path = NULL;
mount_spec = g_mount_spec_new ("dav");
+
g_mount_spec_set (mount_spec, "host", mount_base->host);
if (mount_base->user)
@@ -583,43 +704,16 @@ discover_mount_root_ready (SoupSession *session,
else if (mount_base->scheme == SOUP_URI_SCHEME_HTTPS)
g_mount_spec_set (mount_spec, "ssl", "true");
- g_free (mount_base->path);
- mount_base->path = backend->last_good_path;
-
g_mount_spec_set_mount_prefix (mount_spec, mount_base->path);
- g_vfs_backend_set_mount_spec (G_VFS_BACKEND (backend), mount_spec);
g_vfs_backend_set_icon_name (G_VFS_BACKEND (backend), "folder-remote");
+ g_vfs_backend_set_mount_spec (G_VFS_BACKEND (backend), mount_spec);
g_mount_spec_unref (mount_spec);
+
g_print ("- discover_mount_root_ready success: %s \n", mount_base->path);
g_vfs_job_succeeded (G_VFS_JOB (job));
}
-
-
-static void
-mount (GVfsBackend *backend,
- GVfsJobMount *job,
- GMountSpec *mount_spec,
- GMountSource *mount_source,
- gboolean is_automount)
-{
- GVfsBackendDav *op_backend;
- SoupSession *session;
-
- g_print ("+ mount\n");
-
- op_backend = G_VFS_BACKEND_DAV (backend);
- session = G_VFS_BACKEND_HTTP (backend)->session;
-
- g_signal_connect (session, "authenticate",
- G_CALLBACK (soup_authenticate), job);
-
- op_backend->mount_source = mount_source;
- discover_mount_root (op_backend, job);
- g_print ("- mount\n");
-}
-
static gboolean
try_mount (GVfsBackend *backend,
GVfsJobMount *job,
@@ -628,6 +722,9 @@ try_mount (GVfsBackend *backend,
gboolean is_automount)
{
GVfsBackendDav *op_backend;
+ MountOpData *data;
+ SoupSession *session;
+ SoupMessage *msg;
SoupURI *uri;
const char *host;
const char *user;
@@ -635,11 +732,7 @@ try_mount (GVfsBackend *backend,
const char *ssl;
guint port_num;
- /* We have to override this method since the http backend
- * has its own try_mount and we don't want that to be used.
- * We also need to do the dav mounting stuff inside a
- * thread since the auth callback from soup is getting
- * called in the main thread otherwise and we would block */
+ g_print ("+ mount\n");
op_backend = G_VFS_BACKEND_DAV (backend);
@@ -672,9 +765,24 @@ try_mount (GVfsBackend *backend,
soup_uri_set_host (uri, host);
soup_uri_set_path (uri, mount_spec->mount_prefix);
+ session = G_VFS_BACKEND_HTTP (backend)->session;
G_VFS_BACKEND_HTTP (backend)->mount_base = uri;
- return FALSE;
+ msg = message_new_from_uri (SOUP_METHOD_OPTIONS, uri);
+ soup_session_queue_message (session, msg, discover_mount_root_ready, job);
+
+ data = g_new0 (MountOpData, 1);
+ data->session = g_object_ref (session);
+ data->mount_source = g_object_ref (mount_source);
+ data->username = g_strdup (user);
+
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (soup_authenticate), data);
+
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), data, mount_op_data_free);
+
+ g_print ("- mount\n");
+ return TRUE;
}
static void
@@ -784,8 +892,8 @@ try_query_info (GVfsBackend *backend,
return TRUE;
}
-/* *** enumerate *** */
+/* *** enumerate *** */
static void
@@ -888,7 +996,7 @@ try_enumerate (GVfsBackend *backend,
redirect_header = "T";
soup_message_headers_append (msg->request_headers,
- "Apply-To-Redirect-Ref", redirect_header);
+ "Apply-To-Redirect-Ref", redirect_header);
soup_message_set_request (msg, "application/xml",
SOUP_MEMORY_TAKE,
@@ -912,7 +1020,6 @@ g_vfs_backend_dav_class_init (GVfsBackendDavClass *klass)
gobject_class->finalize = g_vfs_backend_dav_finalize;
backend_class = G_VFS_BACKEND_CLASS (klass);
- backend_class->mount = mount;
backend_class->try_mount = try_mount;
backend_class->try_query_info = try_query_info;
backend_class->try_enumerate = try_enumerate;
diff --git a/programs/gvfs-mount.c b/programs/gvfs-mount.c
index 28812b6b..b6114b8a 100644
--- a/programs/gvfs-mount.c
+++ b/programs/gvfs-mount.c
@@ -29,6 +29,12 @@
#include <locale.h>
#include <gio/gio.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#define STDIN_FILENO 0
+
static int outstanding_mounts = 0;
static GMainLoop *main_loop;
@@ -48,8 +54,14 @@ static GOptionEntry entries[] =
};
static char *
-prompt_for (const char *prompt, const char *default_value)
+prompt_for (const char *prompt, const char *default_value, gboolean echo)
{
+#ifdef HAVE_TERMIOS_H
+ struct termios term_attr;
+ int old_flags;
+ int res;
+ gboolean restore_flags;
+#endif
char data[256];
int len;
@@ -59,7 +71,31 @@ prompt_for (const char *prompt, const char *default_value)
g_print ("%s: ", prompt);
data[0] = 0;
+
+#ifdef HAVE_TERMIOS_H
+ restore_flags = FALSE;
+ if (!echo && (res = tcgetattr (STDIN_FILENO, &term_attr)) == 0)
+ {
+ old_flags = term_attr.c_lflag;
+ term_attr.c_lflag &= ~ECHO;
+ restore_flags = TRUE;
+
+ if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &term_attr) != 0)
+ g_print ("Warning! Password will be echoed");
+ }
+
+#endif
+
fgets(data, sizeof (data), stdin);
+
+#ifdef HAVE_TERMIOS_H
+ if (restore_flags)
+ {
+ term_attr.c_lflag = old_flags;
+ tcsetattr (STDIN_FILENO, TCSAFLUSH, &term_attr);
+ }
+#endif
+
len = strlen (data);
if (len > 0 && data[len-1] == '\n')
data[len-1] = 0;
@@ -81,21 +117,21 @@ ask_password_cb (GMountOperation *op,
if (flags & G_ASK_PASSWORD_NEED_USERNAME)
{
- s = prompt_for ("User", default_user);
+ s = prompt_for ("User", default_user, TRUE);
g_mount_operation_set_username (op, s);
g_free (s);
}
if (flags & G_ASK_PASSWORD_NEED_DOMAIN)
{
- s = prompt_for ("Domain", default_domain);
+ s = prompt_for ("Domain", default_domain, TRUE);
g_mount_operation_set_domain (op, s);
g_free (s);
}
if (flags & G_ASK_PASSWORD_NEED_PASSWORD)
{
- s = prompt_for ("Password", NULL);
+ s = prompt_for ("Password", NULL, FALSE);
g_mount_operation_set_password (op, s);
g_free (s);
}