Bug #655252 - Need to escape the comp_uid part of a path
This commit is contained in:
@ -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. */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
Reference in New Issue
Block a user