[gvfs/wip/rishi/goa: 5/8] push: Implement overwrites and guard against broken filenames
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/wip/rishi/goa: 5/8] push: Implement overwrites and guard against broken filenames
- Date: Mon, 31 Aug 2015 19:02:45 +0000 (UTC)
commit d77d303f05f5838c9d42e7589cb1ff586a42dace
Author: Debarshi Ray <debarshir gnome org>
Date: Tue Aug 25 21:14:56 2015 +0200
push: Implement overwrites and guard against broken filenames
daemon/gvfsbackendgoogle.c | 178 ++++++++++++++++++++++++++++++++++---------
1 files changed, 140 insertions(+), 38 deletions(-)
---
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
index 29bf3c2..2604f6f 100644
--- a/daemon/gvfsbackendgoogle.c
+++ b/daemon/gvfsbackendgoogle.c
@@ -1594,16 +1594,19 @@ g_vfs_backend_google_push (GVfsBackend *_self,
GDataDocumentsDocument *document = NULL;
GDataDocumentsDocument *new_document = NULL;
GDataDocumentsFolder *parent = NULL;
+ GDataEntry *entry;
GDataUploadStream *ostream = NULL;
GError *error;
GFile *local_file = NULL;
GFileInputStream *istream = NULL;
GFileInfo *info = NULL;
+ gboolean is_display_name;
gboolean is_root;
+ gboolean needs_overwrite = FALSE;
const gchar *content_type;
const gchar *id;
- const gchar *real_parent_path;
const gchar *title;
+ gchar *basename = NULL;
gchar *parent_id = NULL;
gchar *parent_path = NULL;
gchar *path = NULL;
@@ -1615,8 +1618,24 @@ g_vfs_backend_google_push (GVfsBackend *_self,
*/
g_rec_mutex_lock (&self->mutex);
- unescaped_destination = unescape_basename_and_map_dirname (self, destination, NULL);
- g_debug ("+ push: %s -> %s (%s, 1)\n", local_path, destination, unescaped_destination);
+ unescaped_destination = unescape_basename_and_map_dirname (self, destination, &is_display_name);
+ g_debug ("+ push: %s -> %s (%s, %d)\n", local_path, destination, unescaped_destination, is_display_name);
+
+ if (unescaped_destination == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+ goto out;
+ }
+
+ if (flags & G_FILE_COPY_BACKUP)
+ {
+ /* Return G_IO_ERROR_NOT_SUPPORTED instead of
+ * G_IO_ERROR_CANT_CREATE_BACKUP to proceed with the GIO
+ * fallback copy.
+ */
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Operation not
supported");
+ goto out;
+ }
local_file = g_file_new_for_path (local_path);
@@ -1644,6 +1663,74 @@ g_vfs_backend_google_push (GVfsBackend *_self,
goto out;
}
+ basename = g_path_get_basename (unescaped_destination);
+
+ if (!is_display_name)
+ {
+ const gchar *destination_id = basename;
+
+ /* This is almost a pathological case. In reality, clients like
+ * file managers won't use an ID as the destination
+ * basename. They will use an escaped version of the source
+ * basename. That means this code path is unlikely to be hit
+ * when recursively pushing a folder.
+ *
+ * Therefore, in order to keep things simple, we unconditionally
+ * refresh the cache.
+ */
+ error = NULL;
+ rebuild_entries (self, cancellable, &error);
+ if (error != NULL)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ goto out;
+ }
+
+ entry = g_hash_table_lookup (self->entries, destination_id);
+ if (entry != NULL)
+ {
+ if (flags & G_FILE_COPY_OVERWRITE)
+ {
+ if (GDATA_IS_DOCUMENTS_FOLDER (entry))
+ {
+ /* At this point, the source can never be a
+ * directory. So we can ignore the issue of copying
+ * a directory over another
+ * (ie. G_IO_ERROR_WOULD_MERGE).
+ */
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("Can't copy file over directory"));
+ goto out;
+ }
+
+ needs_overwrite = TRUE;
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_EXISTS, _("Target file already
exists"));
+ goto out;
+ }
+ }
+ else
+ {
+ /* The basename looks like an ID but that ID doesn't
+ * exist. This is fishy. Probably caused by not using
+ * g_file_get_child_for_display_name to create the
+ * destination path.
+ */
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ _("Invalid filename %s"),
+ destination);
+ goto out;
+ }
+ }
+
+ g_debug (" will overwrite: %d\n", needs_overwrite);
+
error = NULL;
istream = g_file_read (local_file, cancellable, &error);
if (error != NULL)
@@ -1653,54 +1740,68 @@ g_vfs_backend_google_push (GVfsBackend *_self,
goto out;
}
- parent_path = g_path_get_dirname (unescaped_destination);
- real_parent_path = g_hash_table_lookup (self->lookaside, parent_path);
- if (real_parent_path != NULL)
+ content_type = g_file_info_get_content_type (info);
+
+ if (needs_overwrite)
{
- g_free (parent_path);
- parent_path = g_strdup (real_parent_path);
- }
+ document = g_object_ref (entry);
+ title = gdata_entry_get_title (entry);
- is_folder_or_root (parent_path, NULL, NULL, &is_root);
- if (!is_root)
+ error = NULL;
+ ostream = gdata_documents_service_update_document (self->service,
+ document,
+ title,
+ content_type,
+ cancellable,
+ &error);
+ }
+ else
{
- parent_id = g_path_get_basename (parent_path);
- parent = g_hash_table_lookup (self->entries, parent_id);
+ parent_path = g_path_get_dirname (unescaped_destination);
- if (parent == NULL)
+ is_folder_or_root (parent_path, NULL, NULL, &is_root);
+ if (!is_root)
{
- error = NULL;
- rebuild_entries (self, cancellable, &error);
- if (error != NULL)
- {
- g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
- g_error_free (error);
- goto out;
- }
-
+ parent_id = g_path_get_basename (parent_path);
parent = g_hash_table_lookup (self->entries, parent_id);
+
if (parent == NULL)
{
- g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
- goto out;
+ error = NULL;
+ rebuild_entries (self, cancellable, &error);
+ if (error != NULL)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+
+ parent = g_hash_table_lookup (self->entries, parent_id);
+ if (parent == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ goto out;
+ }
}
}
- }
- document = gdata_documents_document_new (NULL);
- title = g_file_info_get_display_name (info);
- gdata_entry_set_title (GDATA_ENTRY (document), title);
+ document = gdata_documents_document_new (NULL);
+ title = basename;
+ gdata_entry_set_title (GDATA_ENTRY (document), title);
- content_type = g_file_info_get_content_type (info);
+ error = NULL;
+ ostream = gdata_documents_service_upload_document (self->service,
+ document,
+ title,
+ content_type,
+ parent,
+ cancellable,
+ &error);
+ }
- error = NULL;
- ostream = gdata_documents_service_upload_document (self->service,
- document,
- title,
- content_type,
- parent,
- cancellable,
- &error);
if (error != NULL)
{
g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
@@ -1764,6 +1865,7 @@ g_vfs_backend_google_push (GVfsBackend *_self,
g_clear_object (&local_file);
g_clear_object (&new_document);
g_clear_object (&ostream);
+ g_free (basename);
g_free (parent_id);
g_free (parent_path);
g_free (path);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]