diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | common/gmountsource.c | 261 | ||||
-rw-r--r-- | common/gmountsource.h | 17 | ||||
-rw-r--r-- | daemon/gvfsbackenddav.c | 355 | ||||
-rw-r--r-- | programs/gvfs-mount.c | 44 |
5 files changed, 482 insertions, 209 deletions
@@ -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); } |