Bug #655252 - Need to escape the comp_uid part of a path

This commit is contained in:
Milan Crha
2011-09-26 11:02:47 +02:00
parent 7e1d3d6dbc
commit 8a309aef81
4 changed files with 116 additions and 72 deletions

View File

@ -43,6 +43,7 @@
#include <e-util/gconf-bridge.h>
#include <shell/e-shell.h>
#include <libedataserver/e-data-server-util.h>
#include <libecal/e-cal-client.h>
#include <libecal/e-cal-client-view.h>
@ -300,7 +301,7 @@ get_attachment_list (CompEditor *editor)
GSList *list = NULL;
const gchar *comp_uid = NULL;
const gchar *local_store;
gchar *path;
gchar *filename_prefix, *tmp;
gint ii;
struct {
@ -309,6 +310,9 @@ get_attachment_list (CompEditor *editor)
GtkWindow *parent;
} status;
e_cal_component_get_uid (editor->priv->comp, &comp_uid);
g_return_val_if_fail (comp_uid != NULL, NULL);
status.uris = NULL;
status.done = FALSE;
status.parent = g_object_ref (editor);
@ -316,17 +320,20 @@ get_attachment_list (CompEditor *editor)
view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
store = e_attachment_view_get_store (view);
tmp = g_strdup (comp_uid);
e_filename_make_safe (tmp);
filename_prefix = g_strconcat (tmp, "-", NULL);
g_free (tmp);
local_store = e_cal_client_get_local_attachment_store (editor->priv->cal_client);
e_cal_component_get_uid (editor->priv->comp, &comp_uid);
path = g_build_path ("/", local_store, comp_uid, NULL);
destination = g_file_new_for_path (path);
g_free (path);
destination = g_file_new_for_path (local_store);
e_attachment_store_save_async (
store, destination, (GAsyncReadyCallback)
attachment_save_finished, &status);
store, destination, filename_prefix,
(GAsyncReadyCallback) attachment_save_finished, &status);
g_object_unref (destination);
g_free (filename_prefix);
/* We can't return until we have results, so crank
* the main loop until the callback gets triggered. */

View File

@ -37,6 +37,7 @@
#include <libecal/e-cal-client.h>
#include <libecal/e-cal-component.h>
#include <libedataserver/e-account.h>
#include <libedataserver/e-data-server-util.h>
#include <libedataserver/e-flag.h>
#include <libedataserverui/e-source-selector-dialog.h>
#include <libedataserverui/e-client-utils.h>
@ -400,8 +401,8 @@ set_attachments (ECalClient *client,
GSList *uri_list = NULL;
const gchar *comp_uid = NULL;
const gchar *local_store;
gchar *filename_prefix, *tmp;
gint ii, n_parts;
gchar *path;
struct _att_async_cb_data cb_data;
cb_data.flag = e_flag_new ();
@ -416,11 +417,15 @@ set_attachments (ECalClient *client,
return;
e_cal_component_get_uid (comp, &comp_uid);
local_store = e_cal_client_get_local_attachment_store (client);
path = g_build_path ("/", local_store, comp_uid, NULL);
g_return_if_fail (comp_uid != NULL);
destination = g_file_new_for_path (path);
g_free (path);
tmp = g_strdup (comp_uid);
e_filename_make_safe (tmp);
filename_prefix = g_strconcat (tmp, "-", NULL);
g_free (tmp);
local_store = e_cal_client_get_local_attachment_store (client);
destination = g_file_new_for_path (local_store);
/* Create EAttachments from the MIME parts and add them to the
* attachment store. */
@ -457,8 +462,10 @@ set_attachments (ECalClient *client,
e_flag_clear (cb_data.flag);
e_attachment_store_save_async (
store, destination, (GAsyncReadyCallback)
attachment_save_finished, &cb_data);
store, destination, filename_prefix,
(GAsyncReadyCallback) attachment_save_finished, &cb_data);
g_free (filename_prefix);
/* We can't return until we have results. */
e_flag_wait (cb_data.flag);

View File

@ -1068,6 +1068,7 @@ typedef struct _SaveContext SaveContext;
struct _SaveContext {
GSimpleAsyncResult *simple;
GFile *destination;
gchar *filename_prefix;
GFile *fresh_directory;
GFile *trash_directory;
GList *attachment_list;
@ -1079,6 +1080,7 @@ struct _SaveContext {
static SaveContext *
attachment_store_save_context_new (EAttachmentStore *store,
GFile *destination,
const gchar *filename_prefix,
GAsyncReadyCallback callback,
gpointer user_data)
{
@ -1101,6 +1103,7 @@ attachment_store_save_context_new (EAttachmentStore *store,
save_context = g_slice_new0 (SaveContext);
save_context->simple = simple;
save_context->destination = g_object_ref (destination);
save_context->filename_prefix = g_strdup (filename_prefix);
save_context->attachment_list = attachment_list;
save_context->uris = uris;
@ -1123,6 +1126,9 @@ attachment_store_save_context_free (SaveContext *save_context)
save_context->destination = NULL;
}
g_free (save_context->filename_prefix);
save_context->filename_prefix = NULL;
if (save_context->fresh_directory) {
g_object_unref (save_context->fresh_directory);
save_context->fresh_directory = NULL;
@ -1138,6 +1144,56 @@ attachment_store_save_context_free (SaveContext *save_context)
g_slice_free (SaveContext, save_context);
}
static void
attachment_store_move_file (SaveContext *save_context, GFile *source, GFile *destination, GError **error)
{
gchar *tmpl;
gchar *path;
g_return_if_fail (save_context != NULL);
g_return_if_fail (source != NULL);
g_return_if_fail (destination != NULL);
g_return_if_fail (error != NULL);
/* Attachments are all saved to a temporary directory.
* Now we need to move the existing destination directory
* out of the way (if it exists). Instead of testing for
* existence we'll just attempt the move and ignore any
* G_IO_ERROR_NOT_FOUND errors. */
/* First, however, we need another temporary directory to
* move the existing destination directory to. Note we're
* not actually creating the directory yet, just picking a
* name for it. The usual raciness with this approach
* applies here (read up on mktemp(3)), but worst case is
* we get a spurious G_IO_ERROR_WOULD_MERGE error and the
* user has to try saving attachments again. */
tmpl = g_strdup_printf (PACKAGE "-%s-XXXXXX", g_get_user_name ());
path = e_mktemp (tmpl);
g_free (tmpl);
save_context->trash_directory = g_file_new_for_path (path);
g_free (path);
/* XXX No asynchronous move operation in GIO? */
g_file_move (
destination,
save_context->trash_directory,
G_FILE_COPY_NONE, NULL, NULL, NULL, error);
if (*error != NULL && !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return;
g_clear_error (error);
/* Now we can move the file from the temporary directory
* to the user-specified destination. */
g_file_move (
source,
destination,
G_FILE_COPY_NONE, NULL, NULL, NULL, error);
}
static void
attachment_store_save_cb (EAttachment *attachment,
GAsyncResult *result,
@ -1146,8 +1202,6 @@ attachment_store_save_cb (EAttachment *attachment,
GSimpleAsyncResult *simple;
GFile *file;
gchar **uris;
gchar *template;
gchar *path;
GError *error = NULL;
file = e_attachment_save_finish (attachment, result, &error);
@ -1161,18 +1215,35 @@ attachment_store_save_cb (EAttachment *attachment,
/* Assemble the file's final URI from its basename. */
gchar *basename;
gchar *uri;
GFile *source = NULL, *destination = NULL;
basename = g_file_get_basename (file);
g_object_unref (file);
source = g_file_get_child (save_context->fresh_directory, basename);
if (save_context->filename_prefix && *save_context->filename_prefix) {
gchar *tmp = basename;
basename = g_strconcat (save_context->filename_prefix, basename, NULL);
g_free (tmp);
}
file = save_context->destination;
file = g_file_get_child (file, basename);
uri = g_file_get_uri (file);
g_object_unref (file);
destination = g_file_get_child (file, basename);
uri = g_file_get_uri (destination);
save_context->uris[save_context->index++] = uri;
/* move them file-by-file */
attachment_store_move_file (save_context, source, destination, &error);
} else if (error != NULL) {
if (!error)
save_context->uris[save_context->index++] = uri;
g_object_unref (source);
g_object_unref (destination);
}
if (error != NULL) {
/* If this is the first error, cancel the other jobs. */
if (save_context->error == NULL) {
g_propagate_error (&save_context->error, error);
@ -1189,8 +1260,7 @@ attachment_store_save_cb (EAttachment *attachment,
g_warning ("%s", error->message);
}
if (error != NULL)
g_error_free (error);
g_clear_error (&error);
/* If there's still jobs running, let them finish. */
if (save_context->attachment_list != NULL)
@ -1212,53 +1282,6 @@ attachment_store_save_cb (EAttachment *attachment,
return;
}
/* Attachments are all saved to a temporary directory.
* Now we need to move the existing destination directory
* out of the way (if it exists). Instead of testing for
* existence we'll just attempt the move and ignore any
* G_IO_ERROR_NOT_FOUND errors. */
/* First, however, we need another temporary directory to
* move the existing destination directory to. Note we're
* not actually creating the directory yet, just picking a
* name for it. The usual raciness with this approach
* applies here (read up on mktemp(3)), but worst case is
* we get a spurious G_IO_ERROR_WOULD_MERGE error and the
* user has to try saving attachments again. */
template = g_strdup_printf (PACKAGE "-%s-XXXXXX", g_get_user_name ());
path = e_mktemp (template);
g_free (template);
save_context->trash_directory = g_file_new_for_path (path);
g_free (path);
/* XXX No asynchronous move operation in GIO? */
g_file_move (
save_context->destination,
save_context->trash_directory,
G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
if (error != NULL && !g_error_matches (
error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
simple = save_context->simple;
g_simple_async_result_set_from_error (simple, error);
g_simple_async_result_complete (simple);
attachment_store_save_context_free (save_context);
g_error_free (error);
return;
}
g_clear_error (&error);
/* Now we can move the first temporary directory containing
* the newly saved files to the user-specified destination. */
g_file_move (
save_context->fresh_directory,
save_context->destination,
G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
if (error != NULL) {
simple = save_context->simple;
g_simple_async_result_set_from_error (simple, error);
@ -1269,6 +1292,9 @@ attachment_store_save_cb (EAttachment *attachment,
return;
}
/* clean-up left directory */
g_file_delete (save_context->fresh_directory, NULL, NULL);
/* And the URI list. */
uris = save_context->uris;
save_context->uris = NULL;
@ -1279,10 +1305,13 @@ attachment_store_save_cb (EAttachment *attachment,
attachment_store_save_context_free (save_context);
}
/*
* @filename_prefix: prefix to use for a file name; can be %NULL for none
**/
void
e_attachment_store_save_async (EAttachmentStore *store,
GFile *destination,
const gchar *filename_prefix,
GAsyncReadyCallback callback,
gpointer user_data)
{
@ -1296,7 +1325,7 @@ e_attachment_store_save_async (EAttachmentStore *store,
g_return_if_fail (G_IS_FILE (destination));
save_context = attachment_store_save_context_new (
store, destination, callback, user_data);
store, destination, filename_prefix, callback, user_data);
attachment_list = save_context->attachment_list;

View File

@ -128,6 +128,7 @@ gboolean e_attachment_store_load_finish (EAttachmentStore *store,
GError **error);
void e_attachment_store_save_async (EAttachmentStore *store,
GFile *destination,
const gchar *filename_prefix,
GAsyncReadyCallback callback,
gpointer user_data);
gchar ** e_attachment_store_save_finish (EAttachmentStore *store,