]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/ev-poppler.cc
Add support for PDF attachments. Fixes bug #325143
[evince.git] / pdf / ev-poppler.cc
index 4fb1d9a2e50c957bad2db783a8fde10a85d42c59..a4be75ee9b7eb6323039b9e64fbe5fdec46e6c9f 100644 (file)
@@ -34,6 +34,7 @@
 #include "ev-document-security.h"
 #include "ev-document-thumbnails.h"
 #include "ev-selection.h"
+#include "ev-attachment.h"
 
 typedef struct {
        PdfDocument *document;
@@ -313,7 +314,122 @@ pdf_document_get_links (EvDocument *document,
 
        return g_list_reverse (retval);
 }
+
+static gboolean
+pdf_document_has_attachments (EvDocument *document)
+{
+       PdfDocument *pdf_document;
+
+       pdf_document = PDF_DOCUMENT (document);
+
+       return poppler_document_has_attachments (pdf_document->document);
+}
+
+struct SaveToBufferData {
+       gchar *buffer;
+       gsize len, max;
+};
+
+static gboolean
+attachment_save_to_buffer_callback (const gchar  *buf,
+                                   gsize         count,
+                                   gpointer      user_data,
+                                   GError      **error)
+{
+       struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
+       gchar *new_buffer;
+       gsize new_max;
+
+       if (sdata->len + count > sdata->max) {
+               new_max = MAX (sdata->max * 2, sdata->len + count);
+               new_buffer = (gchar *)g_realloc (sdata->buffer, new_max);
+
+               sdata->buffer = new_buffer;
+               sdata->max = new_max;
+       }
+       
+       memcpy (sdata->buffer + sdata->len, buf, count);
+       sdata->len += count;
+       
+       return TRUE;
+}
+
+static gboolean
+attachment_save_to_buffer (PopplerAttachment  *attachment,
+                          gchar             **buffer,
+                          gsize              *buffer_size,
+                          GError            **error)
+{
+       static const gint initial_max = 1024;
+       struct SaveToBufferData sdata;
+
+       *buffer = NULL;
+       *buffer_size = 0;
+
+       sdata.buffer = (gchar *) g_malloc (initial_max);
+       sdata.max = initial_max;
+       sdata.len = 0;
+
+       if (! poppler_attachment_save_to_callback (attachment,
+                                                  attachment_save_to_buffer_callback,
+                                                  &sdata,
+                                                  error)) {
+               g_free (sdata.buffer);
+               return FALSE;
+       }
+
+       *buffer = sdata.buffer;
+       *buffer_size = sdata.len;
+       
+       return TRUE;
+}
+
+static GList *
+pdf_document_get_attachments (EvDocument *document)
+{
+       PdfDocument *pdf_document;
+       GList *attachments;
+       GList *list;
+       GList *retval = NULL;
+
+       pdf_document = PDF_DOCUMENT (document);
+
+       if (!pdf_document_has_attachments (document))
+               return NULL;
+
+       attachments = poppler_document_get_attachments (pdf_document->document);
+       
+       for (list = attachments; list; list = list->next) {
+               PopplerAttachment *attachment;
+               EvAttachment *ev_attachment;
+               gchar *data = NULL;
+               gsize size;
+               GError *error = NULL;
+
+               attachment = (PopplerAttachment *) list->data;
+
+               if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
+                       ev_attachment = ev_attachment_new (attachment->name,
+                                                          attachment->description,
+                                                          attachment->mtime,
+                                                          attachment->ctime,
+                                                          size, data);
                        
+                       retval = g_list_prepend (retval, ev_attachment);
+               } else {
+                       if (error) {
+                               g_warning ("%s", error->message);
+                               g_error_free (error);
+
+                               g_free (data);
+                       }
+               }
+
+               g_object_unref (attachment);
+       }
+
+       return g_list_reverse (retval);
+}
 
 static GdkPixbuf *
 pdf_document_render_pixbuf (EvDocument   *document,
@@ -551,6 +667,8 @@ pdf_document_document_iface_init (EvDocumentIface *iface)
        iface->get_page_size = pdf_document_get_page_size;
        iface->get_page_label = pdf_document_get_page_label;
        iface->get_links = pdf_document_get_links;
+       iface->has_attachments = pdf_document_has_attachments;
+       iface->get_attachments = pdf_document_get_attachments;
        iface->render_pixbuf = pdf_document_render_pixbuf;
        iface->get_text = pdf_document_get_text;
        iface->can_get_text = pdf_document_can_get_text;