Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/libdocument
diff options
context:
space:
mode:
authorCarlos Garcia Campos <carlosgc@gnome.org>2007-02-03 19:02:28 (GMT)
committer Carlos Garcia Campos <carlosgc@src.gnome.org>2007-02-03 19:02:28 (GMT)
commitb346c5664d27a77e9068ea91eaf9a0c0d6210b0f (patch)
treefa3ee84f26b4edde138b23c363600cac764beac4 /libdocument
parent4430c8c45ee5b7a6331a6bbc63dbdd8478780371 (diff)
Support for PDF, PS and EPS compressed files. Fixes bug #307087.
2007-02-03 Carlos Garcia Campos <carlosgc@gnome.org> * configure.ac: * backend/ps/ps-document.c: (ps_document_init), (ps_document_dispose), (ps_interpreter_start), (document_load), (save_document), (save_page_list): * libdocument/ev-file-helpers.[ch]: (ev_file_uncompress): * libdocument/ev-document-factory.c: (ev_document_factory_get_from_mime), (get_document_from_uri), (free_uncompressed_uri), (ev_document_factory_get_document): * shell/ev-window.c: (ev_window_cmd_file_open_copy_at_dest): Support for PDF, PS and EPS compressed files. Fixes bug #307087. svn path=/trunk/; revision=2291
Diffstat (limited to 'libdocument')
-rw-r--r--libdocument/ev-document-factory.c119
-rw-r--r--libdocument/ev-file-helpers.c97
-rw-r--r--libdocument/ev-file-helpers.h18
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