aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'widgets')
-rw-r--r--widgets/misc/ChangeLog14
-rw-r--r--widgets/misc/e-attachment-bar.c31
-rw-r--r--widgets/misc/e-attachment.c303
-rw-r--r--widgets/misc/e-attachment.h5
-rw-r--r--widgets/misc/e-image-chooser.c40
5 files changed, 235 insertions, 158 deletions
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog
index dd708047a7..608a0db842 100644
--- a/widgets/misc/ChangeLog
+++ b/widgets/misc/ChangeLog
@@ -1,3 +1,17 @@
+2008-04-17 Milan Crha <mcrha@redhat.com>
+
+ ** Part of fix for bug #526739
+
+ * e-attachment.h: (struct _EAttachment):
+ * e-attachment.c: (finalise), (init), (attachment_guess_mime_type),
+ (e_attachment_new), (struct DownloadInfo), (download_info_free),
+ (data_ready_cb), (download_to_local_path),
+ (e_attachment_new_remote_file):
+ Use gio instead of gnome-vfs to download remote files.
+ * e-image-chooser.c: (image_drag_data_received_cb):
+ Use new util function to read file.
+ * e-attachment-bar.c: (size_to_string): Stolen from gnome-vfs.
+
2008-04-14 Matthew Barnes <mbarnes@redhat.com>
* e-attachment-bar.c
diff --git a/widgets/misc/e-attachment-bar.c b/widgets/misc/e-attachment-bar.c
index ac25f628dd..0ef3ba21f7 100644
--- a/widgets/misc/e-attachment-bar.c
+++ b/widgets/misc/e-attachment-bar.c
@@ -33,7 +33,6 @@
#include <gconf/gconf.h>
#include <gconf/gconf-client.h>
#include <gdk/gdkkeysyms.h>
-#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <glib/gi18n.h>
#include <libgnome/libgnome.h>
@@ -95,15 +94,31 @@ static void update (EAttachmentBar *bar);
static char *
size_to_string (gulong size)
{
- char *size_string;
+ /* code copied from gnome-vfs */
+ #define KILOBYTE_FACTOR 1024.0
+ #define MEGABYTE_FACTOR (1024.0 * 1024.0)
+ #define GIGABYTE_FACTOR (1024.0 * 1024.0 * 1024.0)
- /* FIXME: The following should probably go into a separate module, as
- we might have to do the same thing in other places as well. Also,
- I am not sure this will be OK for all the languages. */
-
- size_string = gnome_vfs_format_file_size_for_display (size);
+ if (size < (gulong) KILOBYTE_FACTOR) {
+ return g_strdup_printf (ngettext ("%u byte", "%u bytes",(guint) size), (guint) size);
+ } else {
+ gdouble displayed_size;
+
+ if (size < (gulong) MEGABYTE_FACTOR) {
+ displayed_size = (gdouble) size / KILOBYTE_FACTOR;
+ return g_strdup_printf (_("%.1f KB"), displayed_size);
+ } else if (size < (gulong) GIGABYTE_FACTOR) {
+ displayed_size = (gdouble) size / MEGABYTE_FACTOR;
+ return g_strdup_printf (_("%.1f MB"), displayed_size);
+ } else {
+ displayed_size = (gdouble) size / GIGABYTE_FACTOR;
+ return g_strdup_printf (_("%.1f GB"), displayed_size);
+ }
+ }
- return size_string;
+ #undef KILOBYTE_FACTOR
+ #undef MEGABYTE_FACTOR
+ #undef GIGABYTE_FACTOR
}
/* Attachment handling functions. */
diff --git a/widgets/misc/e-attachment.c b/widgets/misc/e-attachment.c
index 1383335499..27729b396f 100644
--- a/widgets/misc/e-attachment.c
+++ b/widgets/misc/e-attachment.c
@@ -29,7 +29,7 @@
#include <glib.h>
#ifdef G_OS_WIN32
-/* Include <windows.h> early (as the gnome-vfs stuff below will
+/* Include <windows.h> early (as the gio stuff below will
* include it anyway, sigh) to workaround the DATADIR problem.
* <windows.h> (and the headers it includes) stomps all over the
* namespace like a baboon on crack, and especially the DATADIR enum
@@ -50,12 +50,13 @@
#include <gtk/gtknotebook.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtkdialog.h>
-#include <libgnomevfs/gnome-vfs-mime.h>
+#include <gio/gio.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <libebook/e-vcard.h>
+#include "e-util/e-util.h"
#include "e-util/e-error.h"
#include "e-util/e-mktemp.h"
#include "e-util/e-util-private.h"
@@ -97,8 +98,11 @@ finalise (GObject *object)
if (attachment->pixbuf_cache != NULL)
g_object_unref (attachment->pixbuf_cache);
} else {
- if (attachment->handle)
- gnome_vfs_async_cancel(attachment->handle);
+ if (attachment->cancellable) {
+ /* the operation is still running, so cancel it */
+ g_cancellable_cancel (attachment->cancellable);
+ attachment->cancellable = NULL;
+ }
g_free (attachment->description);
}
@@ -170,6 +174,7 @@ init (EAttachment *attachment)
attachment->sign = CAMEL_CIPHER_VALIDITY_SIGN_NONE;
attachment->encrypt = CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE;
attachment->store_uri = NULL;
+ attachment->cancellable = NULL;
}
GType
@@ -226,57 +231,31 @@ file_ext_is (const char *file_name, const char *ext)
static char *
attachment_guess_mime_type (const char *file_name)
{
- GnomeVFSFileInfo *info;
- GnomeVFSResult result;
- char *type = NULL;
-
- info = gnome_vfs_file_info_new ();
- result = gnome_vfs_get_file_info (file_name, info,
- GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
- GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
- GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
-
- if (result != GNOME_VFS_OK) {
- CamelURL *url;
- char *uri;
-
- url = camel_url_new ("file://", NULL);
- camel_url_set_path (url, file_name);
- uri = camel_url_to_string (url, 0);
- camel_url_free (url);
-
- result = gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
-
- g_free (uri);
- }
-
- if (result == GNOME_VFS_OK) {
- gchar *content = NULL;
+ char *type;
+ gchar *content = NULL;
- type = g_strdup (gnome_vfs_file_info_get_mime_type (info));
+ type = e_util_guess_mime_type (file_name);
- if (type && strcmp (type, "text/directory") == 0 &&
- file_ext_is (file_name, ".vcf") &&
- g_file_get_contents (file_name, &content, NULL, NULL) &&
- content) {
- EVCard *vc = e_vcard_new_from_string (content);
- if (vc) {
- g_free (type);
- g_object_unref (G_OBJECT (vc));
+ if (type && strcmp (type, "text/directory") == 0 &&
+ file_ext_is (file_name, ".vcf") &&
+ g_file_get_contents (file_name, &content, NULL, NULL) &&
+ content) {
+ EVCard *vc = e_vcard_new_from_string (content);
- type = g_strdup ("text/x-vcard");
- }
+ if (vc) {
+ g_free (type);
+ g_object_unref (G_OBJECT (vc));
+ type = g_strdup ("text/x-vcard");
}
- g_free (content);
}
- gnome_vfs_file_info_unref (info);
+ g_free (content);
if (type) {
- /* gnome_vfs can sometimes return invalid type, so check for it */
+ /* Check if returned mime_type is valid */
CamelContentType *ctype = camel_content_type_decode (type);
if (!ctype) {
@@ -376,7 +355,7 @@ e_attachment_new (const char *file_name, const char *disposition, CamelException
new->body = part;
new->size = statbuf.st_size;
new->guessed_type = TRUE;
- new->handle = NULL;
+ new->cancellable = NULL;
new->is_available_local = TRUE;
new->file_name = filename;
@@ -389,93 +368,173 @@ e_attachment_new (const char *file_name, const char *disposition, CamelException
}
-typedef struct DownloadInfo {
+typedef struct {
EAttachment *attachment;
char *file_name;
char *uri;
GtkWindow *parent; /* for error dialog */
+
+ guint64 file_size; /* zero indicates unknown size */
+ GInputStream *istream; /* read from here ... */
+ GOutputStream *ostream; /* ...and write into this. */
+ gboolean was_error;
+ GCancellable *cancellable;
+
+ void *buffer; /* read into this, not more than buffer_size bytes */
+ gsize buffer_size;
} DownloadInfo;
-static int
-async_progress_update_cb (GnomeVFSAsyncHandle *handle,
- GnomeVFSXferProgressInfo *info,
- DownloadInfo *download_info)
+static void
+download_info_free (DownloadInfo *download_info)
{
- switch (info->status) {
- case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
- if (info->file_size) {
- download_info->attachment->percentage = info->bytes_copied*100/info->file_size;
- g_signal_emit (download_info->attachment, signals[UPDATE], 0);
+ /* if there was an error, then free attachment too */
+ if (download_info->was_error)
+ g_object_unref (download_info->attachment);
+
+ if (download_info->ostream)
+ g_object_unref (download_info->ostream);
+
+ if (download_info->istream)
+ g_object_unref (download_info->istream);
+
+ if (download_info->cancellable)
+ g_object_unref (download_info->cancellable);
+
+ g_free (download_info->file_name);
+ g_free (download_info->uri);
+ g_free (download_info->buffer);
+ g_free (download_info);
+}
+
+static void
+data_ready_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ DownloadInfo *download_info = (DownloadInfo *)user_data;
+ GError *error = NULL;
+ gssize read;
+
+ g_return_if_fail (download_info != NULL);
+
+ if (g_cancellable_is_cancelled (download_info->cancellable)) {
+ /* finish the operation and close both streams */
+ g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, NULL);
+
+ g_output_stream_close (download_info->ostream, NULL, NULL);
+ g_input_stream_close (download_info->istream, NULL, NULL);
+
+ /* The only way how to get this canceled is in EAttachment's finalize method,
+ and because the download_info_free free's the attachment on error,
+ then do not consider cancellation as an error. */
+ download_info_free (download_info);
+ return;
+ }
+
+ read = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
+
+ if (!error)
+ g_output_stream_write_all (download_info->ostream, download_info->buffer, read, NULL, download_info->cancellable, &error);
+
+ if (error) {
+ download_info->was_error = error->domain != G_IO_ERROR || error->code != G_IO_ERROR_CANCELLED;
+ if (download_info->was_error)
+ e_error_run (download_info->parent, "mail-composer:no-attach", download_info->uri, error->message, NULL);
+
+ g_error_free (error);
+
+ download_info->attachment->cancellable = NULL;
+ download_info_free (download_info);
+ return;
+ }
+
+ if (read == 0) {
+ CamelException ex;
+
+ /* done with reading */
+ g_output_stream_close (download_info->ostream, NULL, NULL);
+ g_input_stream_close (download_info->istream, NULL, NULL);
+
+ download_info->attachment->cancellable = NULL;
+
+ camel_exception_init (&ex);
+ e_attachment_build_remote_file (download_info->file_name, download_info->attachment, "attachment", &ex);
+
+ if (camel_exception_is_set (&ex)) {
+ download_info->was_error = TRUE;
+ e_error_run (download_info->parent, "mail-composer:no-attach", download_info->uri, camel_exception_get_description (&ex), NULL);
+ camel_exception_clear (&ex);
+ }
+
+ download_info->attachment->percentage = -1;
+ download_info->attachment->is_available_local = TRUE;
+ g_signal_emit (download_info->attachment, signals[UPDATE], 0);
+
+ download_info_free (download_info);
+ return;
+ } else if (download_info->file_size) {
+ download_info->attachment->percentage = read * 100 / download_info->file_size;
+ download_info->file_size -= MIN (download_info->file_size, read);
+ g_signal_emit (download_info->attachment, signals[UPDATE], 0);
+ } else {
+ download_info->attachment->percentage = 0;
+ g_signal_emit (download_info->attachment, signals[UPDATE], 0);
+ }
+
+ /* read next chunk */
+ g_input_stream_read_async (download_info->istream, download_info->buffer, download_info->buffer_size, G_PRIORITY_DEFAULT, download_info->cancellable, data_ready_cb, download_info);
+}
+
+static gboolean
+download_to_local_path (DownloadInfo *download_info, CamelException *ex)
+{
+ GError *error = NULL;
+ GFile *src = g_file_new_for_uri (download_info->uri);
+ GFile *des = g_file_new_for_path (download_info->file_name);
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (src != NULL && des != NULL, FALSE);
+
+ download_info->ostream = G_OUTPUT_STREAM (g_file_replace (des, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error));
+
+ if (download_info->ostream && !error) {
+ GFileInfo *fi;
+
+ fi = g_file_query_info (src, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+ if (fi) {
+ download_info->file_size = g_file_info_get_attribute_uint64 (fi, G_FILE_ATTRIBUTE_STANDARD_SIZE);
+ g_object_unref (fi);
} else {
- download_info->attachment->percentage = 0;
- g_signal_emit (download_info->attachment, signals[UPDATE], 0);
+ download_info->file_size = 0;
}
- if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
- CamelException ex;
-
- if (!info->file_size) {
- if (info->vfs_status == GNOME_VFS_OK)
- info->vfs_status = GNOME_VFS_ERROR_EOF;
- goto error_msg;
- }
-
- download_info->attachment->handle = NULL;
- camel_exception_init (&ex);
- e_attachment_build_remote_file (download_info->file_name, download_info->attachment, "attachment", &ex);
- if (camel_exception_is_set (&ex)) {
- e_error_run (download_info->parent, "mail-composer:no-attach",
- download_info->uri, camel_exception_get_description (&ex), NULL);
- camel_exception_clear (&ex);
- goto error;
- }
- download_info->attachment->percentage = -1;
- download_info->attachment->is_available_local = TRUE;
- g_signal_emit (download_info->attachment, signals[UPDATE], 0);
- g_free (download_info->file_name);
- g_free (download_info->uri);
- g_free (download_info);
+ download_info->istream = G_INPUT_STREAM (g_file_read (src, NULL, &error));
+
+ if (download_info->istream && !error) {
+ download_info->cancellable = g_cancellable_new ();
+ download_info->attachment->cancellable = download_info->cancellable;
+ download_info->buffer_size = 10240; /* max 10KB chunk */
+ download_info->buffer = g_malloc (sizeof (char) * download_info->buffer_size);
+
+ g_input_stream_read_async (download_info->istream, download_info->buffer, download_info->buffer_size, G_PRIORITY_DEFAULT, download_info->cancellable, data_ready_cb, download_info);
+
+ res = TRUE;
}
- return TRUE;
- case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
- error_msg:
- e_error_run (download_info->parent, "mail-composer:no-attach",
- download_info->uri, gnome_vfs_result_to_string (info->vfs_status), NULL);
- error:
- g_object_unref (download_info->attachment);
- g_free (download_info->file_name);
- g_free (download_info->uri);
- g_free (download_info);
- return FALSE;
- default:
- break;
}
- return TRUE;
-}
+ if (error) {
+ /* propagate error */
+ if (ex)
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, error->message);
-static void
-download_to_local_path (GnomeVFSURI *source_uri, GnomeVFSURI *target_uri, DownloadInfo *download_info)
+ g_error_free (error);
+ download_info->was_error = TRUE;
+ download_info_free (download_info);
+ }
-{
- GList *source_uri_list;
- GList *target_uri_list;
-
- source_uri_list = g_list_append (NULL, source_uri);
- target_uri_list = g_list_append (NULL, target_uri);
-
- /* Callback info */
- gnome_vfs_async_xfer (&download_info->attachment->handle, /* handle_return */
- source_uri_list, /* source_uri_list */
- target_uri_list, /* target_uri_list */
- GNOME_VFS_XFER_DEFAULT, /* xfer_options */
- GNOME_VFS_XFER_ERROR_MODE_ABORT, /* error_mode */
- GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE, /* overwrite_mode */
- GNOME_VFS_PRIORITY_DEFAULT, /* priority */
- (GnomeVFSAsyncXferProgressCallback) async_progress_update_cb,
- download_info, /* update_callback_data */
- NULL, /* progress_sync_callback */
- NULL); /* sync_callback_data */
+ g_object_unref (src);
+ g_object_unref (des);
+
+ return res;
}
EAttachment *
@@ -497,19 +556,23 @@ e_attachment_new_remote_file (GtkWindow *error_dlg_parent, const char *uri, cons
new->body = NULL;
new->size = 0;
new->guessed_type = FALSE;
- new->handle = NULL;
+ new->cancellable = NULL;
new->is_available_local = FALSE;
new->percentage = 0;
new->file_name = g_build_filename (path, base, NULL);
g_free (base);
- download_info = g_new (DownloadInfo, 1);
+ download_info = g_new0 (DownloadInfo, 1);
download_info->attachment = new;
download_info->file_name = g_strdup (new->file_name);
download_info->uri = g_strdup (uri);
download_info->parent = error_dlg_parent;
- download_to_local_path (gnome_vfs_uri_new (uri), gnome_vfs_uri_new (new->file_name), download_info);
+ download_info->was_error = FALSE;
+
+ /* it frees all on the error, so do not free it twice */
+ if (!download_to_local_path (download_info, ex))
+ return NULL;
return new;
}
diff --git a/widgets/misc/e-attachment.h b/widgets/misc/e-attachment.h
index 3b03a0aa72..d2cf892c11 100644
--- a/widgets/misc/e-attachment.h
+++ b/widgets/misc/e-attachment.h
@@ -31,7 +31,7 @@
#include <camel/camel-mime-part.h>
#include <camel/camel-exception.h>
#include <camel/camel-cipher-context.h>
-#include <libgnomevfs/gnome-vfs.h>
+#include <gio/gio.h>
#ifdef __cplusplus
extern "C" {
@@ -59,7 +59,8 @@ struct _EAttachment {
GdkPixbuf *pixbuf_cache;
- GnomeVFSAsyncHandle *handle;
+ GCancellable *cancellable;
+
gboolean is_available_local;
int percentage;
char *file_name;
diff --git a/widgets/misc/e-image-chooser.c b/widgets/misc/e-image-chooser.c
index 5dae27527f..f3fb4070ba 100644
--- a/widgets/misc/e-image-chooser.c
+++ b/widgets/misc/e-image-chooser.c
@@ -29,12 +29,12 @@
#include <gtk/gtkbutton.h>
#include <gtk/gtkdnd.h>
-#include <libgnomevfs/gnome-vfs-ops.h>
#include <glib/gi18n.h>
#include "e-image-chooser.h"
#include "e-util/e-util-marshal.h"
#include "e-util/e-icon-factory.h"
+#include "e-util/e-util.h"
struct _EImageChooserPrivate {
@@ -409,46 +409,30 @@ image_drag_data_received_cb (GtkWidget *widget,
target_type = gdk_atom_name (selection_data->target);
if (!strcmp (target_type, URI_LIST_TYPE)) {
- GnomeVFSResult result;
- GnomeVFSHandle *handle;
+ GError *error = NULL;
char *uri;
char *nl = strstr ((char *)selection_data->data, "\r\n");
char *buf = NULL;
- /* Why can't we change the info parameter to a GnomeVFSFileInfo and use that? */
- GnomeVFSFileInfo file_info;
+ gsize read = 0;
if (nl)
uri = g_strndup ((char *)selection_data->data, nl - (char*)selection_data->data);
else
uri = g_strdup ((char *)selection_data->data);
- result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
- if (result == GNOME_VFS_OK) {
- result = gnome_vfs_get_file_info_from_handle (handle, &file_info, GNOME_VFS_FILE_INFO_DEFAULT);
- if (result == GNOME_VFS_OK) {
- GnomeVFSFileSize num_read;
-
- buf = g_malloc (file_info.size);
-
- if ((result = gnome_vfs_read (handle, buf, file_info.size, &num_read)) == GNOME_VFS_OK) {
- if (set_image_from_data (chooser, buf, num_read)) {
- handled = TRUE;
- } else {
- /* XXX we should pop up a warning dialog here */
- g_free (buf);
- }
- } else {
- g_free (buf);
- }
+ if (e_util_read_file (uri, TRUE, &buf, &read, &error) && read > 0 && buf) {
+ if (set_image_from_data (chooser, buf, read)) {
+ handled = TRUE;
}
-
- gnome_vfs_close (handle);
- }
- else {
- printf ("gnome_vfs_open failed (%s)\n", gnome_vfs_result_to_string (result));
}
+ g_free (buf);
g_free (uri);
+
+ if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
}
gtk_drag_finish (context, handled, FALSE, time);