diff options
Diffstat (limited to 'libdocument')
-rw-r--r-- | libdocument/ev-document-factory.c | 119 | ||||
-rw-r--r-- | libdocument/ev-file-helpers.c | 97 | ||||
-rw-r--r-- | libdocument/ev-file-helpers.h | 18 |
3 files changed, 203 insertions, 31 deletions
diff --git a/libdocument/ev-document-factory.c b/libdocument/ev-document-factory.c index 348cb80..4adec66 100644 --- a/libdocument/ev-document-factory.c +++ b/libdocument/ev-document-factory.c @@ -51,16 +51,19 @@ #endif #include <string.h> +#include <glib/gstdio.h> #include <glib/gi18n.h> #include <libgnomevfs/gnome-vfs-mime-utils.h> #include <libgnomevfs/gnome-vfs-file-info.h> #include <libgnomevfs/gnome-vfs-ops.h> #include <gtk/gtkfilechooserdialog.h> +#include "ev-file-helpers.h" + typedef struct _EvDocumentType EvDocumentType; -struct _EvDocumentType -{ +struct _EvDocumentType { const char *mime_type; + EvCompressionType compression; EvBackend backend; GType (*document_type_factory_callback)(); }; @@ -68,41 +71,46 @@ struct _EvDocumentType const EvDocumentType document_types[] = { #ifdef ENABLE_PDF /* PDF: */ - {"application/pdf", EV_BACKEND_PDF, pdf_document_get_type}, + {"application/pdf", EV_COMPRESSION_NONE, EV_BACKEND_PDF, pdf_document_get_type}, + {"application/x-bzpdf", EV_COMPRESSION_BZIP2, EV_BACKEND_PDF, pdf_document_get_type}, + {"application/x-gzpdf", EV_COMPRESSION_GZIP, EV_BACKEND_PDF, pdf_document_get_type}, #endif #ifdef ENABLE_PS /* Postscript: */ - {"application/postscript", EV_BACKEND_PS, ps_document_get_type}, - {"application/x-gzpostscript", EV_BACKEND_PS, ps_document_get_type}, - {"image/x-eps", EV_BACKEND_PS, ps_document_get_type}, + {"application/postscript", EV_COMPRESSION_NONE, EV_BACKEND_PS, ps_document_get_type}, + {"application/x-bzpostscript", EV_COMPRESSION_BZIP2, EV_BACKEND_PS, ps_document_get_type}, + {"application/x-gzpostscript", EV_COMPRESSION_GZIP, EV_BACKEND_PS, ps_document_get_type}, + {"image/x-eps", EV_COMPRESSION_NONE, EV_BACKEND_PS, ps_document_get_type}, + {"image/x-bzeps", EV_COMPRESSION_BZIP2, EV_BACKEND_PS, ps_document_get_type}, + {"image/x-gzeps", EV_COMPRESSION_GZIP, EV_BACKEND_PS, ps_document_get_type}, #endif #ifdef ENABLE_TIFF /* Tiff: */ - {"image/tiff", EV_BACKEND_TIFF, tiff_document_get_type}, + {"image/tiff", EV_COMPRESSION_NONE, EV_BACKEND_TIFF, tiff_document_get_type}, #endif #ifdef ENABLE_DJVU /* djvu: */ - {"image/vnd.djvu", EV_BACKEND_DJVU, djvu_document_get_type}, + {"image/vnd.djvu", EV_COMPRESSION_NONE, EV_BACKEND_DJVU, djvu_document_get_type}, #endif #ifdef ENABLE_DVI /* dvi: */ - {"application/x-dvi", EV_BACKEND_DVI, dvi_document_get_type}, + {"application/x-dvi", EV_COMPRESSION_NONE, EV_BACKEND_DVI, dvi_document_get_type}, #endif #ifdef ENABLE_COMICS /* cbr/cbz: */ - {"application/x-cbr", EV_BACKEND_COMICS, comics_document_get_type}, - {"application/x-cbz", EV_BACKEND_COMICS, comics_document_get_type}, + {"application/x-cbr", EV_COMPRESSION_NONE, EV_BACKEND_COMICS, comics_document_get_type}, + {"application/x-cbz", EV_COMPRESSION_NONE, EV_BACKEND_COMICS, comics_document_get_type}, #endif #ifdef ENABLE_IMPRESS /* Impress slides: */ - {"application/vnd.sun.xml.impress", EV_BACKEND_IMPRESS, impress_document_get_type}, - {"application/vnd.oasis.opendocument.presentation", EV_BACKEND_IMPRESS, impress_document_get_type}, + {"application/vnd.sun.xml.impress", EV_COMPRESSION_NONE, EV_BACKEND_IMPRESS, impress_document_get_type}, + {"application/vnd.oasis.opendocument.presentation", EV_COMPRESSION_NONE, EV_BACKEND_IMPRESS, impress_document_get_type}, #endif }; @@ -160,19 +168,21 @@ mime_type_supported_by_gdk_pixbuf (const gchar *mime_type) } #endif -static EvDocument* -ev_document_factory_get_from_mime (const char *mime_type) +static EvDocument * +ev_document_factory_get_from_mime (const gchar *mime_type, + EvCompressionType *compression) { int i; GType type = G_TYPE_INVALID; EvDocument *document = NULL; - - g_return_val_if_fail (mime_type, G_TYPE_INVALID); + *compression = EV_COMPRESSION_NONE; + for (i = 0; i < G_N_ELEMENTS (document_types); i++) { if (strcmp (mime_type, document_types[i].mime_type) == 0) { g_assert (document_types[i].document_type_factory_callback != NULL); - type = document_types[i].document_type_factory_callback(); + type = document_types[i].document_type_factory_callback (); + *compression = document_types[i].compression; break; } } @@ -181,6 +191,7 @@ ev_document_factory_get_from_mime (const char *mime_type) type = pixbuf_document_get_type (); } #endif + if (type != G_TYPE_INVALID) { document = g_object_new (type, NULL); } @@ -248,13 +259,17 @@ ev_document_factory_get_all_mime_types (void) } static EvDocument * -get_document_from_uri (const char *uri, gboolean slow, GError **error) +get_document_from_uri (const char *uri, + gboolean slow, + EvCompressionType *compression, + GError **error) { EvDocument *document = NULL; - GnomeVFSFileInfo *info; GnomeVFSResult result; + *compression = EV_COMPRESSION_NONE; + info = gnome_vfs_file_info_new (); result = gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE | @@ -278,7 +293,7 @@ get_document_from_uri (const char *uri, gboolean slow, GError **error) return NULL; } - document = ev_document_factory_get_from_mime (info->mime_type); + document = ev_document_factory_get_from_mime (info->mime_type, compression); if (document == NULL) { g_set_error (error, @@ -287,23 +302,56 @@ get_document_from_uri (const char *uri, gboolean slow, GError **error) _("Unhandled MIME type: ā%sā"), info->mime_type); gnome_vfs_file_info_unref (info); return NULL; - } + } gnome_vfs_file_info_unref (info); return document; } +static void +free_uncompressed_uri (gchar *uri_unc) +{ + gchar *filename; + + if (!uri_unc) + return; + + filename = g_filename_from_uri (uri_unc, NULL, NULL); + if (!filename) + return; + + g_unlink (filename); + g_free (filename); + g_free (uri_unc); +} + EvDocument * ev_document_factory_get_document (const char *uri, GError **error) { EvDocument *document; int result; + EvCompressionType compression; + gchar *uri_unc = NULL; - document = get_document_from_uri (uri, FALSE, error); - + document = get_document_from_uri (uri, FALSE, &compression, error); if (*error == NULL) { - result = ev_document_load (document, uri, error); + uri_unc = ev_file_uncompress (uri, compression, error); + if (uri_unc) { + g_object_set_data_full (G_OBJECT (document), + "uri-uncompressed", + uri_unc, + (GDestroyNotify) free_uncompressed_uri); + } + + if (*error != NULL) { + /* Error uncompressing file */ + if (document) + g_object_unref (document); + return NULL; + } + + result = ev_document_load (document, uri_unc ? uri_unc : uri, error); if (result == FALSE || *error) { if (*error && @@ -324,13 +372,30 @@ ev_document_factory_get_document (const char *uri, GError **error) g_error_free (*error); *error = NULL; - document = get_document_from_uri (uri, TRUE, error); + uri_unc = NULL; + + document = get_document_from_uri (uri, TRUE, &compression, error); if (*error != NULL) { return NULL; } - result = ev_document_load (document, uri, error); + uri_unc = ev_file_uncompress (uri, compression, error); + if (uri_unc) { + g_object_set_data_full (G_OBJECT (document), + "uri-uncompressed", + uri_unc, + (GDestroyNotify) free_uncompressed_uri); + } + + if (*error != NULL) { + /* Error uncompressing file */ + if (document) + g_object_unref (document); + return NULL; + } + + result = ev_document_load (document, uri_unc ? uri_unc : uri, error); if (result == FALSE) { if (*error == NULL) { diff --git a/libdocument/ev-file-helpers.c b/libdocument/ev-file-helpers.c index b6a50b6..9bf2e46 100644 --- a/libdocument/ev-file-helpers.c +++ b/libdocument/ev-file-helpers.c @@ -167,3 +167,100 @@ ev_xfer_uri_simple (const char *from, return (result == GNOME_VFS_OK); } + +/* Compressed files support */ +#define BZIPCOMMAND "bzip2" +#define GZIPCOMMAND "gzip" +#define N_ARGS 5 +#define BUFFER_SIZE 1024 + +gchar * +ev_file_uncompress (const gchar *uri, + EvCompressionType type, + GError **error) +{ + gchar *argv[N_ARGS]; + gchar *uri_unc = NULL; + gchar *filename, *filename_unc; + gchar *cmd; + gint fd, pout; + + g_return_val_if_fail (uri != NULL, NULL); + + if (type == EV_COMPRESSION_NONE) + return NULL; + + cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND); + if (!cmd) + return NULL; + + + filename = g_filename_from_uri (uri, NULL, NULL); + if (!filename) { + g_free (cmd); + return NULL; + } + + filename_unc = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL); + fd = g_mkstemp (filename_unc); + if (fd < 0) { + g_free (cmd); + g_free (filename); + g_free (filename_unc); + return NULL; + } + + argv[0] = cmd; + argv[1] = "-cd"; + argv[2] = filename; + argv[3] = filename_unc; + argv[4] = NULL; + + if (g_spawn_async_with_pipes (NULL, argv, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, NULL, + NULL, &pout, NULL, error)) { + GIOChannel *in, *out; + gchar buf[BUFFER_SIZE]; + GIOStatus read_st, write_st; + gsize bytes_read, bytes_written; + + in = g_io_channel_unix_new (pout); + g_io_channel_set_encoding (in, NULL, NULL); + out = g_io_channel_unix_new (fd); + g_io_channel_set_encoding (out, NULL, NULL); + + do { + read_st = g_io_channel_read_chars (in, buf, + BUFFER_SIZE, + &bytes_read, + error); + if (read_st == G_IO_STATUS_NORMAL) { + write_st = g_io_channel_write_chars (out, buf, + bytes_read, + &bytes_written, + error); + if (write_st == G_IO_STATUS_ERROR) + break; + } else if (read_st == G_IO_STATUS_ERROR) { + break; + } + } while (bytes_read > 0); + + g_io_channel_unref (in); + g_io_channel_unref (out); + } + + close (fd); + + if (*error == NULL) { + uri_unc = g_filename_to_uri (filename_unc, + NULL, NULL); + } + + g_free (cmd); + g_free (filename); + g_free (filename_unc); + + return uri_unc; +} diff --git a/libdocument/ev-file-helpers.h b/libdocument/ev-file-helpers.h index 4e75a14..945573d 100644 --- a/libdocument/ev-file-helpers.h +++ b/libdocument/ev-file-helpers.h @@ -25,6 +25,12 @@ G_BEGIN_DECLS +typedef enum { + EV_COMPRESSION_NONE, + EV_COMPRESSION_BZIP2, + EV_COMPRESSION_GZIP +} EvCompressionType; + const gchar *ev_dot_dir (void); const gchar *ev_tmp_dir (void); @@ -33,11 +39,15 @@ void ev_file_helpers_init (void); void ev_file_helpers_shutdown (void); -gchar* ev_tmp_filename (const char *prefix); +gchar *ev_tmp_filename (const char *prefix); + +gboolean ev_xfer_uri_simple (const char *from, + const char *to, + GError **error); +gchar *ev_file_uncompress (const gchar *uri, + EvCompressionType type, + GError **error); -gboolean ev_xfer_uri_simple (const char *from, - const char *to, - GError **error); G_END_DECLS |