Bug#1061380: bookworm-pu: package atril/1.26.0-2+deb12u2
Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: atril@packages.debian.org
Control: affects -1 + src:atril
Recently atril 1.26.0-2+deb12u1 has been accepted in bookworm for the
upcoming 12.5 point release. This upload brings a follow-up change (CVE
fix), also targetting the upcoming point release.
[ Reason ]
Fix CVE-2023-51698:
https://security-tracker.debian.org/tracker/CVE-2023-51698
[ Impact ]
CVE-2023-51698 stays unfixed and atril stays vulnerable to crafted .CBT
(Comic Book Tar) files
[ Tests ]
I manually checked that common file formats such as PDF and ePub can
still be opened. Unfortunately, I don't own any comic book tarball files
and could not find any such files on the internet for free download. As the
patches have been cherry-picked from upstream, I assume that they are
well tested with actual .CBT files.
[ Risks ]
Comic book consumers who read their comic books with atril might be
affected if the patchset is not sane.
[ Checklist ]
[x] *all* changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in (old)stable
[x] the issue is verified as fixed in unstable
[ Changes ]
+atril (1.26.0-2+deb12u2) bookworm; urgency=medium
+
+ * debian/patches:
+ + Add 0005-Use-a-blank-line-at-most.patch and 0006-comics-Use-libarchive-
+ to-unpack-documents.patch. Use libarchive instead of external command for
+ extracing documents (CVE-2023-51698, closes: #1060751).
+
+ -- Mike Gabriel <sunweaver@debian.org> Tue, 23 Jan 2024 10:08:40 +0100
+
+atril (1.26.0-2+deb12u1) bookworm; urgency=medium
+
+ * debian/patches:
+ + Add 1002-avoid-crash-on-certain-epub-files.patch. Avoid crashes when
+ opening certain epub files. (Closes: #972715).
+ + Add 0001-Accessibility-add-button-description.patch. Accessibility: add
+ 'Hide sidebar' button description. (Cherry-picked from v1.26.1).
+ + Add 0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch. Fix
+ index loading for certain epub documents. (Cherry-picked from v1.26.1).
+ + Add 0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch. epub:
+ add fallback for malformed epub files in check_mime_type. (Cherry-picked from
+ v1.26.1).
+
+ -- Mike Gabriel <sunweaver@debian.org> Sat, 06 Jan 2024 07:18:28 +0100
[ Other info ]
None.
diff -Nru atril-1.26.0/debian/changelog atril-1.26.0/debian/changelog
--- atril-1.26.0/debian/changelog 2022-10-27 11:00:10.000000000 +0200
+++ atril-1.26.0/debian/changelog 2024-01-23 10:08:40.000000000 +0100
@@ -1,3 +1,27 @@
+atril (1.26.0-2+deb12u2) bookworm; urgency=medium
+
+ * debian/patches:
+ + Add 0005-Use-a-blank-line-at-most.patch and 0006-comics-Use-libarchive-
+ to-unpack-documents.patch. Use libarchive instead of external command for
+ extracing documents (CVE-2023-51698, closes: #1060751).
+
+ -- Mike Gabriel <sunweaver@debian.org> Tue, 23 Jan 2024 10:08:40 +0100
+
+atril (1.26.0-2+deb12u1) bookworm; urgency=medium
+
+ * debian/patches:
+ + Add 1002-avoid-crash-on-certain-epub-files.patch. Avoid crashes when
+ opening certain epub files. (Closes: #972715).
+ + Add 0001-Accessibility-add-button-description.patch. Accessibility: add
+ 'Hide sidebar' button description. (Cherry-picked from v1.26.1).
+ + Add 0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch. Fix
+ index loading for certain epub documents. (Cherry-picked from v1.26.1).
+ + Add 0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch. epub:
+ add fallback for malformed epub files in check_mime_type. (Cherry-picked from
+ v1.26.1).
+
+ -- Mike Gabriel <sunweaver@debian.org> Sat, 06 Jan 2024 07:18:28 +0100
+
atril (1.26.0-2) unstable; urgency=medium
[ Mike Gabriel ]
diff -Nru atril-1.26.0/debian/patches/0001-Accessibility-add-button-description.patch atril-1.26.0/debian/patches/0001-Accessibility-add-button-description.patch
--- atril-1.26.0/debian/patches/0001-Accessibility-add-button-description.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/0001-Accessibility-add-button-description.patch 2024-01-23 10:05:56.000000000 +0100
@@ -0,0 +1,47 @@
+From 9a981607b36488ea5d2ce8646540b1545e35ecd5 Mon Sep 17 00:00:00 2001
+From: Valentin Villenave <vvillenave@hypra.fr>
+Date: Tue, 26 Oct 2021 19:29:01 +0200
+Subject: [PATCH 01/10] Accessibility: add button description
+
+Signed-off-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+---
+ po/POTFILES.in | 1 +
+ shell/ev-sidebar.c | 3 +++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index 02b9435..08ab5ec 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -67,6 +67,7 @@ shell/ev-password-view.c
+ shell/ev-properties-dialog.c
+ shell/ev-properties-fonts.c
+ shell/ev-properties-license.c
++shell/ev-sidebar.c
+ shell/ev-sidebar-annotations.c
+ shell/ev-sidebar-attachments.c
+ shell/ev-sidebar-bookmarks.c
+diff --git a/shell/ev-sidebar.c b/shell/ev-sidebar.c
+index b9173cd..0cdb6be 100644
+--- a/shell/ev-sidebar.c
++++ b/shell/ev-sidebar.c
+@@ -26,6 +26,8 @@
+
+ #include <string.h>
+
++#include <glib.h>
++#include <glib/gi18n.h>
+ #include <gtk/gtk.h>
+ #include <gdk/gdkkeysyms.h>
+
+@@ -362,6 +364,7 @@ ev_sidebar_init (EvSidebar *ev_sidebar)
+ g_signal_connect (close_button, "clicked",
+ G_CALLBACK (ev_sidebar_close_clicked_cb),
+ ev_sidebar);
++ gtk_widget_set_tooltip_text (close_button, _("Hide sidebar"));
+
+ image = gtk_image_new_from_icon_name ("window-close",
+ GTK_ICON_SIZE_MENU);
+--
+2.39.2
+
diff -Nru atril-1.26.0/debian/patches/0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch atril-1.26.0/debian/patches/0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch
--- atril-1.26.0/debian/patches/0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch 2024-01-23 10:05:56.000000000 +0100
@@ -0,0 +1,38 @@
+From 9f5d7343f79f6ff8295884df3229bc6696b4386c Mon Sep 17 00:00:00 2001
+From: Michael Webster <miketwebster@gmail.com>
+Date: Mon, 18 Jul 2022 10:43:47 -0400
+Subject: [PATCH 03/10] epub: Fix index loading for certain documents - look
+ for epub:type instead of epub:id.
+
+Add a null check as well.
+
+ref:
+https://help.apple.com/itc/booksassetguide/en.lproj/itc0f175a5b9.html#apdd3c4c6d1c0904
+https://idpf.org/epub/301/spec/epub-contentdocs-20140626.html#sec-xhtml-nav
+Signed-off-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+---
+ backend/epub/epub-document.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/backend/epub/epub-document.c b/backend/epub/epub-document.c
+index 52530f4..385d2fe 100644
+--- a/backend/epub/epub-document.c
++++ b/backend/epub/epub-document.c
+@@ -1201,7 +1201,13 @@ setup_index_from_navfile(gchar *tocpath)
+ GList *index = NULL;
+ open_xml_document(tocpath);
+ set_xml_root_node(NULL);
+- xmlNodePtr nav = xml_get_pointer_to_node((xmlChar*)"nav",(xmlChar*)"id",(xmlChar*)"toc");
++ xmlNodePtr nav = xml_get_pointer_to_node((xmlChar*)"nav",(xmlChar*)"type",(xmlChar*)"toc");
++
++ if (nav == NULL) {
++ xml_free_doc();
++ return NULL;
++ }
++
+ xmlretval=NULL;
+ xml_parse_children_of_node(nav,(xmlChar*)"ol", NULL,NULL);
+ gchar *navdirend = g_strrstr(tocpath,"/");
+--
+2.39.2
+
diff -Nru atril-1.26.0/debian/patches/0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch atril-1.26.0/debian/patches/0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch
--- atril-1.26.0/debian/patches/0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch 2024-01-23 10:05:56.000000000 +0100
@@ -0,0 +1,98 @@
+From c585b945d27e883908c437d12aa9c453db2143f4 Mon Sep 17 00:00:00 2001
+From: rbuj <robert.buj@gmail.com>
+Date: Sun, 7 Aug 2022 23:08:59 +0200
+Subject: [PATCH 04/10] epub: add fallback for malformed epub files in
+ check_mime_type
+
+Signed-off-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+---
+ backend/epub/epub-document.c | 66 +++++++++++++++++++++---------------
+ 1 file changed, 38 insertions(+), 28 deletions(-)
+
+diff --git a/backend/epub/epub-document.c b/backend/epub/epub-document.c
+index 385d2fe..451c884 100644
+--- a/backend/epub/epub-document.c
++++ b/backend/epub/epub-document.c
+@@ -625,41 +625,51 @@ xml_get_data_from_node(xmlNodePtr node,
+ static gboolean
+ check_mime_type(const gchar* uri,GError** error)
+ {
+- GError * err = NULL ;
+- const gchar* mimeFromFile = ev_file_get_mime_type(uri,FALSE,&err);
++ GError * err = NULL;
++ const gchar* mimeFromFile;
+
+- gchar* mimetypes[] = {"application/epub+zip","application/x-booki+zip"};
+- int typecount = 2;
+- if ( !mimeFromFile )
++ mimeFromFile = ev_file_get_mime_type(uri, FALSE, &err);
++ if (mimeFromFile)
+ {
+- if (err) {
+- g_propagate_error (error, err);
+- }
+- else {
+- g_set_error_literal (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("Unknown MIME Type"));
+- }
+- return FALSE;
+- }
+- else
+- {
+- int i=0;
+- for (i=0; i < typecount ;i++) {
+- if ( g_strcmp0(mimeFromFile, mimetypes[i]) == 0 ) {
++ const gchar* mimetypes[] = {"application/epub+zip", "application/x-booki+zip", NULL};
++ guint i;
++
++ for (i = 0; i < g_strv_length (mimetypes); i++) {
++ if (strcmp(mimeFromFile, mimetypes[i]) == 0)
+ return TRUE;
+- }
++ }
++
++ /* fallback for malformed epub files */
++ if (strcmp (mimeFromFile, "application/zip") == 0)
++ {
++ mimeFromFile = ev_file_get_mime_type (uri, TRUE, &err);
++ if (mimeFromFile)
++ {
++ for (i = 0; i < g_strv_length (mimetypes); i++) {
++ if (g_strcmp0(mimeFromFile, mimetypes[i]) == 0)
++ return TRUE;
++ }
++
++ /*We didn't find a match*/
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_INVALID,
++ _("Not an ePub document"));
++
++ return FALSE;
++ }
+ }
++ }
+
+- /*We didn't find a match*/
++ if (err)
++ g_propagate_error (error, err);
++ else
+ g_set_error_literal (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("Not an ePub document"));
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_INVALID,
++ _("Unknown MIME Type"));
+
+- return FALSE;
+- }
++ return FALSE;
+ }
+
+ static gboolean
+--
+2.39.2
+
diff -Nru atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch
--- atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch 2024-01-23 10:08:40.000000000 +0100
@@ -0,0 +1,1866 @@
+From 658fab1f008bff7e1ec147d95baa04bc44c2fbcd Mon Sep 17 00:00:00 2001
+From: rbuj <robert.buj@gmail.com>
+Date: Wed, 27 Oct 2021 17:30:36 +0200
+Subject: [PATCH 1/2] Use a blank line at most
+
+Signed-off-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+---
+ backend/comics/comics-document.c | 3 --
+ backend/djvu/djvu-document.c | 3 --
+ backend/djvu/djvu-links.c | 2 -
+ backend/djvu/djvu-text-page.c | 3 --
+ backend/djvu/djvu-text-page.h | 1 -
+ backend/dvi/dvi-document.c | 2 -
+ backend/dvi/fonts.c | 1 -
+ backend/dvi/mdvi-lib/afmparse.c | 18 --------
+ backend/dvi/mdvi-lib/bitmap.c | 2 -
+ backend/dvi/mdvi-lib/color.c | 1 -
+ backend/dvi/mdvi-lib/color.h | 1 -
+ backend/dvi/mdvi-lib/fontmap.c | 1 -
+ backend/dvi/mdvi-lib/hash.c | 1 -
+ backend/dvi/mdvi-lib/hash.h | 2 -
+ backend/dvi/mdvi-lib/mdvi.h | 2 -
+ backend/dvi/mdvi-lib/paper.h | 1 -
+ backend/dvi/mdvi-lib/special.c | 1 -
+ backend/dvi/mdvi-lib/tfmfile.c | 1 -
+ backend/epub/epub-document.c | 6 ---
+ backend/epub/minizip/ioapi.c | 6 ---
+ backend/epub/minizip/ioapi.h | 7 ---
+ backend/epub/minizip/unzip.c | 45 -------------------
+ backend/epub/minizip/unzip.h | 11 -----
+ backend/pdf/ev-poppler.h | 1 -
+ backend/pixbuf/pixbuf-document.c | 1 -
+ backend/tiff/tiff-document.c | 1 -
+ backend/tiff/tiff2ps.c | 2 -
+ backend/xps/xps-document.c | 2 -
+ .../toolbar-editor/egg-editable-toolbar.c | 2 -
+ .../toolbar-editor/egg-toolbar-editor.c | 1 -
+ .../toolbar-editor/egg-toolbar-editor.h | 2 -
+ .../toolbar-editor/egg-toolbars-model.c | 2 -
+ cut-n-paste/zoom-control/ephy-zoom.c | 1 -
+ libdocument/ev-document-attachments.c | 1 -
+ libdocument/ev-document-factory.c | 1 -
+ libdocument/ev-document-fonts.h | 1 -
+ libdocument/ev-document-misc.c | 1 -
+ libdocument/ev-document-security.h | 1 -
+ libdocument/ev-document-text.c | 1 -
+ libdocument/ev-document.c | 1 -
+ libdocument/ev-file-helpers.h | 1 -
+ libdocument/ev-form-field.h | 1 -
+ libdocument/ev-image.h | 1 -
+ libdocument/ev-render-context.h | 2 -
+ libdocument/ev-transition-effect.h | 2 -
+ libmisc/ev-page-action-widget.c | 3 --
+ libview/ev-page-accessible.c | 2 -
+ libview/ev-pixbuf-cache.c | 6 ---
+ libview/ev-pixbuf-cache.h | 2 -
+ libview/ev-timeline.c | 2 -
+ libview/ev-timeline.h | 2 -
+ libview/ev-transition-animation.c | 2 -
+ libview/ev-transition-animation.h | 2 -
+ libview/ev-view-presentation.c | 1 -
+ libview/ev-view.c | 2 -
+ libview/ev-web-view.c | 2 -
+ libview/ev-web-view.h | 1 -
+ previewer/ev-previewer-window.c | 1 -
+ shell/eggfindbar.c | 1 -
+ shell/eggfindbar.h | 1 -
+ shell/ev-application.c | 2 -
+ shell/ev-bookmarks.h | 2 -
+ shell/ev-daemon.c | 1 -
+ shell/ev-history.c | 1 -
+ shell/ev-loading-message.c | 1 -
+ shell/ev-media-player-keys.h | 1 -
+ shell/ev-navigation-action.c | 1 -
+ shell/ev-open-recent-action.c | 1 -
+ shell/ev-password-view.c | 2 -
+ shell/ev-sidebar-attachments.c | 1 -
+ shell/ev-sidebar-bookmarks.c | 1 -
+ shell/ev-sidebar-layers.c | 1 -
+ shell/ev-sidebar-links.c | 3 --
+ shell/ev-sidebar-links.h | 1 -
+ shell/ev-sidebar-page.c | 1 -
+ shell/ev-sidebar-page.h | 1 -
+ shell/ev-sidebar-thumbnails.c | 1 -
+ shell/ev-sidebar-thumbnails.h | 1 -
+ shell/ev-sidebar.c | 1 -
+ shell/ev-sidebar.h | 1 -
+ shell/ev-window.c | 9 ----
+ shell/ev-window.h | 2 -
+ shell/main.c | 4 --
+ 83 files changed, 220 deletions(-)
+
+--- a/backend/comics/comics-document.c
++++ b/backend/comics/comics-document.c
+@@ -126,7 +126,6 @@
+ static char** extract_argv (EvDocument *document,
+ gint page);
+
+-
+ EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,
+ {
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+@@ -186,7 +185,6 @@
+ return g_string_free (dest, FALSE);
+ }
+
+-
+ /* This function manages the command for decompressing a comic book */
+ static gboolean
+ comics_decompress_temp_dir (const gchar *command_decompress_tmp,
+@@ -627,7 +625,6 @@
+ return TRUE;
+ }
+
+-
+ static gboolean
+ comics_document_save (EvDocument *document,
+ const char *uri,
+--- a/backend/djvu/djvu-document.c
++++ b/backend/djvu/djvu-document.c
+@@ -66,7 +66,6 @@
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION, djvu_selection_iface_init);
+ });
+
+-
+ #define EV_DJVU_ERROR ev_djvu_error_quark ()
+
+ static GQuark
+@@ -256,7 +255,6 @@
+ return TRUE;
+ }
+
+-
+ static gboolean
+ djvu_document_save (EvDocument *document,
+ const char *uri,
+@@ -676,7 +674,6 @@
+ r->y2 = height - tmp * SCALE_FACTOR;
+ }
+
+-
+ return matches;
+ }
+
+--- a/backend/djvu/djvu-links.c
++++ b/backend/djvu/djvu-links.c
+@@ -181,7 +181,6 @@
+ if (!string_from_miniexp (miniexp_car (iter), &title)) goto unknown_entry;
+ if (!string_from_miniexp (miniexp_cadr (iter), &link_dest)) goto unknown_entry;
+
+-
+ if (!g_utf8_validate (title, -1, NULL)) {
+ utf8_title = str_to_utf8 (title);
+ title_markup = g_markup_escape_text (utf8_title, -1);
+@@ -342,7 +341,6 @@
+ return NULL;
+ }
+
+-
+ gboolean
+ djvu_links_has_document_links (EvDocumentLinks *document_links)
+ {
+--- a/backend/djvu/djvu-text-page.c
++++ b/backend/djvu/djvu-text-page.c
+@@ -23,7 +23,6 @@
+ #include <libdjvu/miniexp.h>
+ #include "djvu-text-page.h"
+
+-
+ /**
+ * djvu_text_page_selection_process:
+ * @page: #DjvuTextPage instance
+@@ -117,7 +116,6 @@
+ }
+ }
+
+-
+ static void
+ djvu_text_page_limits (DjvuTextPage *page,
+ miniexp_t p,
+@@ -404,7 +402,6 @@
+ g_free (search_text);
+ }
+
+-
+ /**
+ * djvu_text_page_prepare_search:
+ * @page: #DjvuTextPage instance
+--- a/backend/djvu/djvu-text-page.h
++++ b/backend/djvu/djvu-text-page.h
+@@ -25,7 +25,6 @@
+ #include <glib.h>
+ #include <libdjvu/miniexp.h>
+
+-
+ typedef struct _DjvuTextPage DjvuTextPage;
+ typedef struct _DjvuTextLink DjvuTextLink;
+
+--- a/backend/dvi/dvi-document.c
++++ b/backend/dvi/dvi-document.c
+@@ -110,7 +110,6 @@
+
+ mdvi_cairo_device_init (&dvi_document->context->device);
+
+-
+ dvi_document->base_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv
+ + 2 * unit2pix(dvi_document->params->dpi, MDVI_HMARGIN) / dvi_document->params->hshrink;
+
+@@ -123,7 +122,6 @@
+ return TRUE;
+ }
+
+-
+ static gboolean
+ dvi_document_save (EvDocument *document,
+ const char *uri,
+--- a/backend/dvi/fonts.c
++++ b/backend/dvi/fonts.c
+@@ -54,4 +54,3 @@
+ return;
+ }
+
+-
+--- a/backend/dvi/mdvi-lib/afmparse.c
++++ b/backend/dvi/mdvi-lib/afmparse.c
+@@ -81,13 +81,10 @@
+
+ #define MATCH(A,B) (strncmp((A),(B), MAX_NAME) == 0)
+
+-
+-
+ /*************************** GLOBALS ***********************/
+
+ static char *ident = NULL; /* storage buffer for keywords */
+
+-
+ /* "shorts" for fast case statement
+ * The values of each of these enumerated items correspond to an entry in the
+ * table of strings defined below. Therefore, if you add a new string as
+@@ -175,7 +172,6 @@
+
+ } /* token */
+
+-
+ /*************************** linetoken *************************/
+
+ /* "linetoken" will get read all tokens until the EOL character from
+@@ -203,7 +199,6 @@
+
+ } /* linetoken */
+
+-
+ /*************************** recognize *************************/
+
+ /* This function tries to match a string to a known list of
+@@ -234,7 +229,6 @@
+
+ } /* recognize */
+
+-
+ /************************* parseGlobals *****************************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -401,8 +395,6 @@
+
+ } /* parseGlobals */
+
+-
+-
+ #if 0 /* this function does not seem to be used anywhere */
+ /************************* initializeArray ************************/
+
+@@ -584,7 +576,6 @@
+
+ } /* parseCharWidths */
+
+-
+ /************************* parseCharMetrics ************************/
+
+ /* This function is called by parseFile if the caller of parseFile
+@@ -694,8 +685,6 @@
+
+ } /* parseCharMetrics */
+
+-
+-
+ /************************* parseTrackKernData ***********************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -797,7 +786,6 @@
+
+ } /* parseTrackKernData */
+
+-
+ /************************* parsePairKernData ************************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -918,7 +906,6 @@
+
+ } /* parsePairKernData */
+
+-
+ /************************* parseCompCharData **************************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -1043,12 +1030,8 @@
+
+ } /* parseCompCharData */
+
+-
+-
+-
+ /*************************** 'PUBLIC' FUNCTION ********************/
+
+-
+ /*************************** parseFile *****************************/
+
+ /* parseFile is the only 'public' procedure available. It is called
+@@ -1078,7 +1061,6 @@
+
+ register char *keyword; /* used to store a token */
+
+-
+ /* storage data for the global variable ident */
+ ident = (char *) calloc(MAX_NAME, sizeof(char));
+ if (ident == NULL) {error = storageProblem; return(error);}
+--- a/backend/dvi/mdvi-lib/bitmap.c
++++ b/backend/dvi/mdvi-lib/bitmap.c
+@@ -117,7 +117,6 @@
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+ };
+
+-
+ /*
+ * next we have three bitmap functions to convert bitmaps in LSB bit order
+ * with 8, 16 and 32 bits per unit, to our internal format. The differences
+@@ -192,7 +191,6 @@
+ return bm;
+ }
+
+-
+ BITMAP *bitmap_copy(BITMAP *bm)
+ {
+ BITMAP *nb = bitmap_alloc(bm->width, bm->height);
+--- a/backend/dvi/mdvi-lib/color.c
++++ b/backend/dvi/mdvi-lib/color.c
+@@ -79,7 +79,6 @@
+
+ #define GAMMA_DIFF 0.005
+
+-
+ /* create a color table */
+ Ulong *get_color_table(DviDevice *dev,
+ int nlevels, Ulong fg, Ulong bg, double gamma, int density)
+--- a/backend/dvi/mdvi-lib/color.h
++++ b/backend/dvi/mdvi-lib/color.h
+@@ -16,7 +16,6 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-
+ #ifndef _COLOR_H_
+ #define _COLOR_H_
+
+--- a/backend/dvi/mdvi-lib/fontmap.c
++++ b/backend/dvi/mdvi-lib/fontmap.c
+@@ -834,7 +834,6 @@
+ return 0;
+ }
+
+-
+ void mdvi_flush_encodings(void)
+ {
+ DviEncoding *enc;
+--- a/backend/dvi/mdvi-lib/hash.c
++++ b/backend/dvi/mdvi-lib/hash.c
+@@ -21,7 +21,6 @@
+
+ /* simple hash tables for MDVI */
+
+-
+ struct _DviHashBucket {
+ DviHashBucket *next;
+ DviHashKey key;
+--- a/backend/dvi/mdvi-lib/hash.h
++++ b/backend/dvi/mdvi-lib/hash.h
+@@ -3,7 +3,6 @@
+
+ /* Hash tables */
+
+-
+ typedef struct _DviHashBucket DviHashBucket;
+ typedef struct _DviHashTable DviHashTable;
+
+@@ -18,7 +17,6 @@
+ typedef int (*DviHashComp) __PROTO((DviHashKey key1, DviHashKey key2));
+ typedef void (*DviHashFree) __PROTO((DviHashKey key, void *data));
+
+-
+ struct _DviHashTable {
+ DviHashBucket **buckets;
+ int nbucks;
+--- a/backend/dvi/mdvi-lib/mdvi.h
++++ b/backend/dvi/mdvi-lib/mdvi.h
+@@ -414,7 +414,6 @@
+ int step; /* step */
+ };
+
+-
+ typedef void (*DviSpecialHandler)
+ __PROTO((DviContext *dvi, const char *prefix, const char *arg));
+
+@@ -600,7 +599,6 @@
+
+ extern int mdvi_encode_font __PROTO((DviParams *, DviFont *));
+
+-
+ /* font lookup functions */
+ extern int mdvi_register_font_type __PROTO((DviFontInfo *, int));
+ extern char **mdvi_list_font_class __PROTO((int));
+--- a/backend/dvi/mdvi-lib/paper.h
++++ b/backend/dvi/mdvi-lib/paper.h
+@@ -24,7 +24,6 @@
+ const char *height;
+ };
+
+-
+ extern int mdvi_get_paper_size __PROTO((const char *, DviPaper *));
+ extern DviPaperSpec* mdvi_get_paper_specs __PROTO((DviPaperClass));
+ extern void mdvi_free_paper_specs __PROTO((DviPaperSpec *));
+--- a/backend/dvi/mdvi-lib/special.c
++++ b/backend/dvi/mdvi-lib/special.c
+@@ -212,7 +212,6 @@
+ {
+ DviSpecial *sp, *list;
+
+-
+ for(list = (DviSpecial *)specials.head; (sp = list); ) {
+ list = sp->next;
+ if(sp->prefix) mdvi_free(sp->prefix);
+--- a/backend/dvi/mdvi-lib/tfmfile.c
++++ b/backend/dvi/mdvi-lib/tfmfile.c
+@@ -258,7 +258,6 @@
+ /* allocate characters */
+ info->chars = xnalloc(TFMChar, size);
+
+-
+ #ifdef WORD_LITTLE_ENDIAN
+ /* byte-swap the three arrays at once (they are consecutive in memory) */
+ swap_array((Uint32 *)widths, nw + nh + nd);
+--- a/backend/epub/epub-document.c
++++ b/backend/epub/epub-document.c
+@@ -224,7 +224,6 @@
+ return TRUE;
+ }
+
+-
+ typedef struct _LinksCBStruct {
+ GtkTreeModel *model;
+ GtkTreeIter *parent;
+@@ -413,7 +412,6 @@
+ return (g_remove (path_name));
+ }
+
+-
+ static gboolean
+ check_mime_type (const gchar* uri,
+ GError** error);
+@@ -1562,7 +1560,6 @@
+
+ gchar *csspath = g_strdup_printf("%s/atrilnightstyle.css",epub_document->documentdir);
+
+-
+ GFile *styles = g_file_new_for_path (csspath);
+ GOutputStream *outstream = (GOutputStream*)g_file_create(styles,G_FILE_CREATE_PRIVATE,NULL,NULL);
+ if ( g_output_stream_write((GOutputStream*)outstream,style,strlen(style),NULL,NULL) == -1 )
+@@ -1636,7 +1633,6 @@
+ g_list_foreach(index,(GFunc)page_set_function,contentList);
+ }
+
+-
+ static void
+ add_mathjax_script_node_to_file(gchar *filename, gchar *data)
+ {
+@@ -1784,7 +1780,6 @@
+ epub_document->docTitle = NULL;
+ }
+
+-
+ static void
+ epub_document_finalize (GObject *object)
+ {
+@@ -1826,7 +1821,6 @@
+ G_OBJECT_CLASS (epub_document_parent_class)->finalize (object);
+ }
+
+-
+ static void
+ epub_document_class_init (EpubDocumentClass *klass)
+ {
+--- a/backend/epub/minizip/ioapi.c
++++ b/backend/epub/minizip/ioapi.c
+@@ -25,7 +25,6 @@
+ #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+ #endif
+
+-
+ #include "ioapi.h"
+
+ voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
+@@ -82,8 +81,6 @@
+ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+ }
+
+-
+-
+ static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+ static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+ static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
+@@ -128,7 +125,6 @@
+ return file;
+ }
+
+-
+ static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
+ {
+ uLong ret;
+@@ -150,7 +146,6 @@
+ return ret;
+ }
+
+-
+ static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+ {
+ ZPOS64_T ret;
+@@ -206,7 +201,6 @@
+ return ret;
+ }
+
+-
+ static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
+ {
+ int ret;
+--- a/backend/epub/minizip/ioapi.h
++++ b/backend/epub/minizip/ioapi.h
+@@ -110,7 +110,6 @@
+ extern "C" {
+ #endif
+
+-
+ #define ZLIB_FILEFUNC_SEEK_CUR (1)
+ #define ZLIB_FILEFUNC_SEEK_END (2)
+ #define ZLIB_FILEFUNC_SEEK_SET (0)
+@@ -122,7 +121,6 @@
+ #define ZLIB_FILEFUNC_MODE_EXISTING (4)
+ #define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+-
+ #ifndef ZCALLBACK
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+ #define ZCALLBACK CALLBACK
+@@ -131,9 +129,6 @@
+ #endif
+ #endif
+
+-
+-
+-
+ typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+ typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+ typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+@@ -143,7 +138,6 @@
+ typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+ typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+
+-
+ /* here is the "old" 32 bits structure structure */
+ typedef struct zlib_filefunc_def_s
+ {
+@@ -185,7 +179,6 @@
+ seek_file_func zseek32_file;
+ } zlib_filefunc64_32_def;
+
+-
+ #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+ #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+ //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+--- a/backend/epub/minizip/unzip.c
++++ b/backend/epub/minizip/unzip.c
+@@ -12,7 +12,6 @@
+
+ For more info read MiniZip_info.txt
+
+-
+ ------------------------------------------------------------------------------------
+ Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+ compatibility with older software. The following is from the original crypt.c.
+@@ -48,7 +47,6 @@
+
+ Copyright (C) 2007-2008 Even Rouault
+
+-
+ Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
+ Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
+ should only read the compressed/uncompressed size from the Zip64 format if
+@@ -63,7 +61,6 @@
+
+ */
+
+-
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -86,20 +83,17 @@
+ # include <errno.h>
+ #endif
+
+-
+ #ifndef local
+ # define local static
+ #endif
+ /* compile with -Dlocal if your debugger can't find static symbols */
+
+-
+ #ifndef CASESENSITIVITYDEFAULT_NO
+ # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+ # define CASESENSITIVITYDEFAULT_NO
+ # endif
+ #endif
+
+-
+ #ifndef UNZ_BUFSIZE
+ #define UNZ_BUFSIZE (16384)
+ #endif
+@@ -118,14 +112,12 @@
+ #define SIZECENTRALDIRITEM (0x2e)
+ #define SIZEZIPLOCALHEADER (0x1e)
+
+-
+ /* unz_file_info_interntal contain internal info about a file in zipfile*/
+ typedef struct unz_file_info64_internal_s
+ {
+ ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
+ } unz_file_info64_internal;
+
+-
+ /* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+ typedef struct
+@@ -156,7 +148,6 @@
+ int raw;
+ } file_in_zip64_read_info_s;
+
+-
+ /* unz64_s contain internal information about the zipfile
+ */
+ typedef struct
+@@ -189,7 +180,6 @@
+ # endif
+ } unz64_s;
+
+-
+ #ifndef NOUNCRYPT
+ #include "crypt.h"
+ #endif
+@@ -200,7 +190,6 @@
+ IN assertion: the stream s has been successfully opened for reading.
+ */
+
+-
+ local int unz64local_getByte OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+@@ -224,7 +213,6 @@
+ }
+ }
+
+-
+ /* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+ */
+@@ -295,7 +283,6 @@
+ voidpf filestream,
+ ZPOS64_T *pX));
+
+-
+ local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX)
+@@ -364,7 +351,6 @@
+ }
+ }
+
+-
+ #ifdef CASESENSITIVITYDEFAULT_NO
+ #define CASESENSITIVITYDEFAULTVALUE 2
+ #else
+@@ -418,7 +404,6 @@
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+-
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+@@ -463,7 +448,6 @@
+ return uPosFound;
+ }
+
+-
+ /*
+ Locate the Central directory 64 of a zipfile (at the end, just before
+ the global comment)
+@@ -486,7 +470,6 @@
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+-
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+@@ -605,8 +588,6 @@
+ us.z_filefunc = *pzlib_filefunc64_32_def;
+ us.is64bitOpenFunction = is64bitOpenFunction;
+
+-
+-
+ us.filestream = ZOPEN64(us.z_filefunc,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+@@ -745,7 +726,6 @@
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+-
+ s=(unz64_s*)ALLOC(sizeof(unz64_s));
+ if( s != NULL)
+ {
+@@ -755,7 +735,6 @@
+ return (unzFile)s;
+ }
+
+-
+ extern unzFile ZEXPORT unzOpen2 (const char *path,
+ zlib_filefunc_def* pzlib_filefunc32_def)
+ {
+@@ -814,7 +793,6 @@
+ return UNZ_OK;
+ }
+
+-
+ /*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+@@ -897,7 +875,6 @@
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+-
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+@@ -1002,7 +979,6 @@
+ else
+ lSeek += file_info.size_file_extra;
+
+-
+ if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
+ {
+ uLong acc = 0;
+@@ -1096,7 +1072,6 @@
+ else
+ lSeek+=file_info.size_file_comment;
+
+-
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+@@ -1106,8 +1081,6 @@
+ return err;
+ }
+
+-
+-
+ /*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+@@ -1156,7 +1129,6 @@
+
+ pfile_info->tmu_date = file_info64.tmu_date,
+
+-
+ pfile_info->compressed_size = (uLong)file_info64.compressed_size;
+ pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
+
+@@ -1212,7 +1184,6 @@
+ return err;
+ }
+
+-
+ /*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+@@ -1234,7 +1205,6 @@
+ ZPOS64_T num_fileSaved;
+ ZPOS64_T pos_in_central_dirSaved;
+
+-
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+
+@@ -1278,7 +1248,6 @@
+ return err;
+ }
+
+-
+ /*
+ ///////////////////////////////////////////
+ // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+@@ -1391,7 +1360,6 @@
+ s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+-
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+@@ -1594,7 +1562,6 @@
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size ;
+
+-
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+@@ -1626,7 +1593,6 @@
+ }
+ # endif
+
+-
+ return UNZ_OK;
+ }
+
+@@ -1687,7 +1653,6 @@
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+-
+ if (pfile_in_zip_read_info->read_buffer == NULL)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len==0)
+@@ -1731,7 +1696,6 @@
+ uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+
+-
+ # ifndef NOUNCRYPT
+ if(s->encrypted)
+ {
+@@ -1743,7 +1707,6 @@
+ }
+ # endif
+
+-
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+@@ -1874,7 +1837,6 @@
+ return err;
+ }
+
+-
+ /*
+ Give the current position in uncompressed data
+ */
+@@ -1909,7 +1871,6 @@
+ return pfile_in_zip_read_info->total_out_64;
+ }
+
+-
+ /*
+ return 1 if the end of file was reached, 0 elsewhere
+ */
+@@ -1931,8 +1892,6 @@
+ return 0;
+ }
+
+-
+-
+ /*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+@@ -2007,7 +1966,6 @@
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+-
+ if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+ (!pfile_in_zip_read_info->raw))
+ {
+@@ -2015,7 +1973,6 @@
+ err=UNZ_CRCERROR;
+ }
+
+-
+ TRYFREE(pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
+@@ -2025,7 +1982,6 @@
+ BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
+ #endif
+
+-
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE(pfile_in_zip_read_info);
+
+@@ -2034,7 +1990,6 @@
+ return err;
+ }
+
+-
+ /*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+--- a/backend/epub/minizip/unzip.h
++++ b/backend/epub/minizip/unzip.h
+@@ -70,7 +70,6 @@
+ typedef voidp unzFile;
+ #endif
+
+-
+ #define UNZ_OK (0)
+ #define UNZ_END_OF_LIST_OF_FILE (-100)
+ #define UNZ_ERRNO (Z_ERRNO)
+@@ -162,7 +161,6 @@
+ (like 1 on Unix, 2 on Windows)
+ */
+
+-
+ extern unzFile ZEXPORT unzOpen OF((const char *path));
+ extern unzFile ZEXPORT unzOpen64 OF((const void *path));
+ /*
+@@ -180,7 +178,6 @@
+ does not describe the reality
+ */
+
+-
+ extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def));
+ /*
+@@ -212,7 +209,6 @@
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+-
+ extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+ char *szComment,
+ uLong uSizeBuf));
+@@ -222,7 +218,6 @@
+ return the number of byte copied or an error code <0
+ */
+
+-
+ /***************************************************************************/
+ /* Unzip package allow you browse the directory of the zipfile */
+
+@@ -251,7 +246,6 @@
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+ */
+
+-
+ /* ****************************************** */
+ /* Ryan supplied functions */
+ /* unz_file_info contain information about a file in the zipfile */
+@@ -315,14 +309,12 @@
+ (commentBufferSize is the size of the buffer)
+ */
+
+-
+ /** Addition for GDAL : START */
+
+ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
+
+ /** Addition for GDAL : END */
+
+-
+ /***************************************************************************/
+ /* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+@@ -369,7 +361,6 @@
+ but you CANNOT set method parameter as NULL
+ */
+
+-
+ extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+ /*
+ Close the file in zip opened with unzOpenCurrentFile
+@@ -428,8 +419,6 @@
+ extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
+ extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+-
+-
+ #ifdef __cplusplus
+ }
+ #endif
+--- a/backend/pdf/ev-poppler.h
++++ b/backend/pdf/ev-poppler.h
+@@ -34,7 +34,6 @@
+
+ G_MODULE_EXPORT GType register_atril_backend (GTypeModule *module);
+
+-
+ G_END_DECLS
+
+ #endif /* __PDF_DOCUMENT_H__ */
+--- a/backend/pixbuf/pixbuf-document.c
++++ b/backend/pixbuf/pixbuf-document.c
+@@ -201,7 +201,6 @@
+ iface->get_dimensions = pixbuf_document_thumbnails_get_dimensions;
+ }
+
+-
+ static void
+ pixbuf_document_init (PixbufDocument *pixbuf_document)
+ {
+--- a/backend/tiff/tiff-document.c
++++ b/backend/tiff/tiff-document.c
+@@ -361,7 +361,6 @@
+ if (width <= 0 || height <= 0)
+ return NULL;
+
+-
+ if (width >= INT_MAX / 4)
+ /* overflow */
+ return NULL;
+--- a/backend/tiff/tiff2ps.c
++++ b/backend/tiff/tiff2ps.c
+@@ -449,7 +449,6 @@
+ return splitpage;
+ }
+
+-
+ void
+ tiff2ps_process_page(TIFF2PSContext* ctx, TIFF* tif, double pw, double ph,
+ double lm, double bm, gboolean cnt)
+@@ -592,7 +591,6 @@
+ }
+ }
+
+-
+ static char DuplexPreamble[] = "\
+ %%BeginFeature: *Duplex True\n\
+ systemdict begin\n\
+--- a/backend/xps/xps-document.c
++++ b/backend/xps/xps-document.c
+@@ -176,7 +176,6 @@
+ EV_DOCUMENT_INFO_N_PAGES |
+ EV_DOCUMENT_INFO_PAPER_SIZE;
+
+-
+ if (gxps_document_get_n_pages (xps->doc) > 0) {
+ ev_document_get_page_size (document, 0,
+ &(info->paper_width),
+@@ -483,7 +482,6 @@
+ iface->find_link_page = xps_document_links_find_link_page;
+ }
+
+-
+ /* EvDocumentPrint */
+ static void
+ xps_document_print_print_page (EvDocumentPrint *document,
+--- a/cut-n-paste/toolbar-editor/egg-editable-toolbar.c
++++ b/cut-n-paste/toolbar-editor/egg-editable-toolbar.c
+@@ -541,7 +541,6 @@
+ }
+ }
+
+-
+ static void
+ configure_item_tooltip (GtkToolItem *item)
+ {
+@@ -557,7 +556,6 @@
+ }
+ }
+
+-
+ static void
+ connect_widget_signals (GtkWidget *proxy, EggEditableToolbar *etoolbar)
+ {
+--- a/cut-n-paste/toolbar-editor/egg-toolbar-editor.c
++++ b/cut-n-paste/toolbar-editor/egg-toolbar-editor.c
+@@ -36,7 +36,6 @@
+ {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0},
+ };
+
+-
+ static void egg_toolbar_editor_finalize (GObject *object);
+ static void update_editor_sheet (EggToolbarEditor *editor);
+
+--- a/cut-n-paste/toolbar-editor/egg-toolbar-editor.h
++++ b/cut-n-paste/toolbar-editor/egg-toolbar-editor.h
+@@ -34,7 +34,6 @@
+ #define EGG_IS_TOOLBAR_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TOOLBAR_EDITOR))
+ #define EGG_TOOLBAR_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TOOLBAR_EDITOR, EggToolbarEditorClass))
+
+-
+ typedef struct EggToolbarEditor EggToolbarEditor;
+ typedef struct EggToolbarEditorPrivate EggToolbarEditorPrivate;
+
+@@ -51,7 +50,6 @@
+ GtkBoxClass parent_class;
+ };
+
+-
+ GType egg_toolbar_editor_get_type (void);
+ GtkWidget *egg_toolbar_editor_new (GtkUIManager *manager,
+ EggToolbarsModel *model);
+--- a/cut-n-paste/toolbar-editor/egg-toolbars-model.c
++++ b/cut-n-paste/toolbar-editor/egg-toolbars-model.c
+@@ -213,7 +213,6 @@
+ EggToolbarsItem *idata2;
+ GNode *toolbar, *item;
+
+-
+ for(toolbar = g_node_first_child (model->priv->toolbars);
+ toolbar != NULL; toolbar = g_node_next_sibling (toolbar))
+ {
+@@ -330,7 +329,6 @@
+ 0, toolbar_position);
+ }
+
+-
+ char *
+ egg_toolbars_model_get_data (EggToolbarsModel *model,
+ GdkAtom type,
+--- a/cut-n-paste/zoom-control/ephy-zoom.c
++++ b/cut-n-paste/zoom-control/ephy-zoom.c
+@@ -54,7 +54,6 @@
+ return n_zoom_levels - 1;
+ }
+
+-
+ float
+ ephy_zoom_get_changed_zoom_level (float level, gint steps)
+ {
+--- a/libdocument/ev-document-attachments.c
++++ b/libdocument/ev-document-attachments.c
+@@ -52,4 +52,3 @@
+ return iface->get_attachments (document_attachments);
+ }
+
+-
+--- a/libdocument/ev-document-factory.c
++++ b/libdocument/ev-document-factory.c
+@@ -106,7 +106,6 @@
+ return EV_COMPRESSION_NONE;
+ }
+
+-
+ /*
+ * get_document_from_uri:
+ * @uri: the document URI
+--- a/libdocument/ev-document-fonts.h
++++ b/libdocument/ev-document-fonts.h
+@@ -37,7 +37,6 @@
+
+ G_BEGIN_DECLS
+
+-
+ #define EV_TYPE_DOCUMENT_FONTS (ev_document_fonts_get_type ())
+ #define EV_DOCUMENT_FONTS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT_FONTS, EvDocumentFonts))
+ #define EV_DOCUMENT_FONTS_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT_FONTS, EvDocumentFontsInterface))
+--- a/libdocument/ev-document-misc.c
++++ b/libdocument/ev-document-misc.c
+@@ -149,7 +149,6 @@
+ }
+ }
+
+-
+ void
+ ev_document_misc_paint_one_page (cairo_t *cr,
+ GtkWidget *widget,
+--- a/libdocument/ev-document-security.h
++++ b/libdocument/ev-document-security.h
+@@ -35,7 +35,6 @@
+
+ G_BEGIN_DECLS
+
+-
+ #define EV_TYPE_DOCUMENT_SECURITY (ev_document_security_get_type ())
+ #define EV_DOCUMENT_SECURITY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT_SECURITY, EvDocumentSecurity))
+ #define EV_DOCUMENT_SECURITY_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT_SECURITY, EvDocumentSecurityInterface))
+--- a/libdocument/ev-document-text.c
++++ b/libdocument/ev-document-text.c
+@@ -42,7 +42,6 @@
+ return iface->get_text (document_text, page);
+ }
+
+-
+ gboolean
+ ev_document_text_get_text_layout (EvDocumentText *document_text,
+ EvPage *page,
+--- a/libdocument/ev-document.c
++++ b/libdocument/ev-document.c
+@@ -388,7 +388,6 @@
+ return klass->get_page (document, index);
+ }
+
+-
+ #ifdef ENABLE_SYNCTEX
+ static gboolean
+ _ev_document_support_synctex (EvDocument *document)
+--- a/libdocument/ev-file-helpers.h
++++ b/libdocument/ev-file-helpers.h
+@@ -66,7 +66,6 @@
+ EvCompressionType type,
+ GError **error);
+
+-
+ G_END_DECLS
+
+ #endif /* EV_FILE_HELPERS_H */
+--- a/libdocument/ev-form-field.h
++++ b/libdocument/ev-form-field.h
+@@ -209,7 +209,6 @@
+ GType ev_form_field_signature_get_type (void) G_GNUC_CONST;
+ EvFormField *ev_form_field_signature_new (gint id);
+
+-
+ G_END_DECLS
+
+ #endif /* !EV_FORM_FIELD_H */
+--- a/libdocument/ev-image.h
++++ b/libdocument/ev-image.h
+@@ -62,7 +62,6 @@
+ GdkPixbuf *pixbuf);
+ const gchar *ev_image_get_tmp_uri (EvImage *image);
+
+-
+ G_END_DECLS
+
+ #endif /* __EV_IMAGE_H__ */
+--- a/libdocument/ev-render-context.h
++++ b/libdocument/ev-render-context.h
+@@ -52,7 +52,6 @@
+ gdouble scale;
+ };
+
+-
+ GType ev_render_context_get_type (void) G_GNUC_CONST;
+ EvRenderContext *ev_render_context_new (EvPage *page,
+ gint rotation,
+@@ -64,7 +63,6 @@
+ void ev_render_context_set_scale (EvRenderContext *rc,
+ gdouble scale);
+
+-
+ G_END_DECLS
+
+ #endif /* !EV_RENDER_CONTEXT */
+--- a/libdocument/ev-transition-effect.h
++++ b/libdocument/ev-transition-effect.h
+@@ -61,7 +61,6 @@
+ EV_TRANSITION_DIRECTION_OUTWARD
+ } EvTransitionEffectDirection;
+
+-
+ typedef struct EvTransitionEffect EvTransitionEffect;
+ typedef struct EvTransitionEffectClass EvTransitionEffectClass;
+
+@@ -75,7 +74,6 @@
+ GObjectClass parent_class;
+ };
+
+-
+ GType ev_transition_effect_get_type (void) G_GNUC_CONST;
+
+ EvTransitionEffect *ev_transition_effect_new (EvTransitionEffectType type,
+--- a/libmisc/ev-page-action-widget.c
++++ b/libmisc/ev-page-action-widget.c
+@@ -305,7 +305,6 @@
+ return TRUE;
+ }
+
+-
+ static void
+ display_completion_text (GtkCellLayout *cell_layout,
+ GtkCellRenderer *renderer,
+@@ -349,7 +348,6 @@
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+
+-
+ if (link) {
+ text = ev_link_get_title (link);
+ g_object_unref (link);
+@@ -445,7 +443,6 @@
+ return filter_model;
+ }
+
+-
+ void
+ ev_page_action_widget_update_links_model (EvPageActionWidget *proxy, GtkTreeModel *model)
+ {
+--- a/libview/ev-page-accessible.c
++++ b/libview/ev-page-accessible.c
+@@ -37,7 +37,6 @@
+ gboolean children_initialized;
+ };
+
+-
+ enum {
+ PROP_0,
+ PROP_VIEW_ACCESSIBLE,
+@@ -412,7 +411,6 @@
+ EvRectangle *next_word_end;
+ gint prev_offset, next_offset;
+
+-
+ if (!log_attrs[offset].is_white)
+ return FALSE;
+
+--- a/libview/ev-pixbuf-cache.c
++++ b/libview/ev-pixbuf-cache.c
+@@ -72,7 +72,6 @@
+ void (* job_finished) (EvPixbufCache *pixbuf_cache);
+ };
+
+-
+ enum
+ {
+ JOB_FINISHED,
+@@ -92,7 +91,6 @@
+ gint page,
+ gfloat scale);
+
+-
+ /* These are used for iterating through the prev and next arrays */
+ #define FIRST_VISIBLE_PREV(pixbuf_cache) \
+ (MAX (0, pixbuf_cache->preload_cache_size - pixbuf_cache->start_page))
+@@ -223,7 +221,6 @@
+ G_OBJECT_CLASS (ev_pixbuf_cache_parent_class)->dispose (object);
+ }
+
+-
+ EvPixbufCache *
+ ev_pixbuf_cache_new (GtkWidget *view,
+ EvDocumentModel *model,
+@@ -985,7 +982,6 @@
+ }
+ }
+
+-
+ void
+ ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache)
+ {
+@@ -1265,7 +1261,6 @@
+ }
+ }
+
+-
+ /* Returns what the pixbuf cache thinks is */
+
+ GList *
+@@ -1356,4 +1351,3 @@
+ EV_JOB_PRIORITY_URGENT);
+ }
+
+-
+--- a/libview/ev-pixbuf-cache.h
++++ b/libview/ev-pixbuf-cache.h
+@@ -39,8 +39,6 @@
+ #define EV_PIXBUF_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_PIXBUF_CACHE, EvPixbufCache))
+ #define EV_IS_PIXBUF_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_PIXBUF_CACHE))
+
+-
+-
+ /* The coordinates in the rect here are at scale == 1.0, so that we can ignore
+ * resizings. There is one per page, maximum.
+ */
+--- a/libview/ev-timeline.c
++++ b/libview/ev-timeline.c
+@@ -56,10 +56,8 @@
+
+ static guint signals [LAST_SIGNAL] = { 0, };
+
+-
+ G_DEFINE_TYPE_WITH_PRIVATE (EvTimeline, ev_timeline, G_TYPE_OBJECT)
+
+-
+ static void
+ ev_timeline_init (EvTimeline *timeline)
+ {
+--- a/libview/ev-timeline.h
++++ b/libview/ev-timeline.h
+@@ -59,7 +59,6 @@
+ gdouble progress);
+ };
+
+-
+ GType ev_timeline_get_type (void) G_GNUC_CONST;
+
+ EvTimeline *ev_timeline_new (guint duration);
+@@ -84,7 +83,6 @@
+
+ gdouble ev_timeline_get_progress (EvTimeline *timeline);
+
+-
+ G_END_DECLS
+
+ #endif /* __EV_TIMELINE_H__ */
+--- a/libview/ev-transition-animation.c
++++ b/libview/ev-transition-animation.c
+@@ -41,10 +41,8 @@
+ PROP_DEST_SURFACE
+ };
+
+-
+ G_DEFINE_TYPE_WITH_PRIVATE (EvTransitionAnimation, ev_transition_animation, EV_TYPE_TIMELINE)
+
+-
+ static void
+ ev_transition_animation_init (EvTransitionAnimation *animation)
+ {
+--- a/libview/ev-transition-animation.h
++++ b/libview/ev-transition-animation.h
+@@ -50,7 +50,6 @@
+ EvTimelineClass parent_class;
+ };
+
+-
+ GType ev_transition_animation_get_type (void) G_GNUC_CONST;
+
+ EvTransitionAnimation * ev_transition_animation_new (EvTransitionEffect *effect);
+@@ -67,7 +66,6 @@
+ GdkRectangle page_area);
+ gboolean ev_transition_animation_ready (EvTransitionAnimation *animation);
+
+-
+ G_END_DECLS
+
+ #endif /* __EV_TRANSITION_ANIMATION_H__ */
+--- a/libview/ev-view-presentation.c
++++ b/libview/ev-view-presentation.c
+@@ -1385,7 +1385,6 @@
+ return TRUE;
+ }
+
+-
+ static void
+ add_change_page_binding_keypad (GtkBindingSet *binding_set,
+ guint keyval,
+--- a/libview/ev-view.c
++++ b/libview/ev-view.c
+@@ -5621,7 +5621,6 @@
+
+ /*** Drawing ***/
+
+-
+ static void
+ draw_rubberband (EvView *view,
+ cairo_t *cr,
+@@ -5652,7 +5651,6 @@
+ cairo_restore (cr);
+ }
+
+-
+ static void
+ highlight_find_results (EvView *view, cairo_t *cr, int page)
+ {
+--- a/libview/ev-web-view.c
++++ b/libview/ev-web-view.c
+@@ -31,7 +31,6 @@
+ #include "ev-document-model.h"
+ #include "ev-jobs.h"
+
+-
+ typedef enum {
+ EV_WEB_VIEW_FIND_NEXT,
+ EV_WEB_VIEW_FIND_PREV
+@@ -322,7 +321,6 @@
+ web_view_update_range_and_current_page (webview);
+ }
+
+-
+ gboolean
+ ev_web_view_next_page (EvWebView *webview)
+ {
+--- a/libview/ev-web-view.h
++++ b/libview/ev-web-view.h
+@@ -35,7 +35,6 @@
+ #include <glib-object.h>
+ G_BEGIN_DECLS
+
+-
+ typedef struct _EvWebView EvWebView;
+ typedef struct _EvWebViewClass EvWebViewClass;
+
+--- a/previewer/ev-previewer-window.c
++++ b/previewer/ev-previewer-window.c
+@@ -621,7 +621,6 @@
+ return object;
+ }
+
+-
+ static void
+ ev_previewer_window_class_init (EvPreviewerWindowClass *klass)
+ {
+--- a/shell/eggfindbar.c
++++ b/shell/eggfindbar.c
+@@ -573,7 +573,6 @@
+ g_object_thaw_notify (G_OBJECT (find_bar));
+ }
+
+-
+ /**
+ * egg_find_bar_get_search_string:
+ *
+--- a/shell/eggfindbar.h
++++ b/shell/eggfindbar.h
+@@ -77,4 +77,3 @@
+
+ #endif /* __EGG_FIND_BAR_H__ */
+
+-
+--- a/shell/ev-application.c
++++ b/shell/ev-application.c
+@@ -21,7 +21,6 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-
+ #include <config.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -311,7 +310,6 @@
+ return empty_window;
+ }
+
+-
+ #ifdef ENABLE_DBUS
+ typedef struct {
+ gchar *uri;
+--- a/shell/ev-bookmarks.h
++++ b/shell/ev-bookmarks.h
+@@ -50,8 +50,6 @@
+ void ev_bookmarks_update (EvBookmarks *bookmarks,
+ EvBookmark *bookmark);
+
+-
+-
+ G_END_DECLS
+
+ #endif /* EV_BOOKMARKS_H */
+--- a/shell/ev-daemon.c
++++ b/shell/ev-daemon.c
+@@ -43,7 +43,6 @@
+
+ #define LOG g_debug
+
+-
+ #define EV_TYPE_DAEMON_APPLICATION (ev_daemon_application_get_type ())
+ #define EV_DAEMON_APPLICATION(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplication))
+
+--- a/shell/ev-history.c
++++ b/shell/ev-history.c
+@@ -24,7 +24,6 @@
+
+ #include "ev-history.h"
+
+-
+ enum
+ {
+ HISTORY_CHANGED,
+--- a/shell/ev-loading-message.c
++++ b/shell/ev-loading-message.c
+@@ -174,4 +174,3 @@
+ return message;
+ }
+
+-
+--- a/shell/ev-media-player-keys.h
++++ b/shell/ev-media-player-keys.h
+@@ -37,7 +37,6 @@
+ typedef struct _EvMediaPlayerKeys EvMediaPlayerKeys;
+ typedef struct _EvMediaPlayerKeysClass EvMediaPlayerKeysClass;
+
+-
+ GType ev_media_player_keys_get_type (void) G_GNUC_CONST;
+
+ EvMediaPlayerKeys *ev_media_player_keys_new (void);
+--- a/shell/ev-navigation-action.c
++++ b/shell/ev-navigation-action.c
+@@ -26,7 +26,6 @@
+ #include "ev-navigation-action.h"
+ #include "ev-navigation-action-widget.h"
+
+-
+ enum
+ {
+ WIDGET_ACTIVATE_LINK,
+--- a/shell/ev-open-recent-action.c
++++ b/shell/ev-open-recent-action.c
+@@ -24,7 +24,6 @@
+
+ #include "ev-open-recent-action.h"
+
+-
+ enum {
+ ITEM_ACTIVATED,
+ N_SIGNALS
+--- a/shell/ev-password-view.c
++++ b/shell/ev-password-view.c
+@@ -18,7 +18,6 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+@@ -47,7 +46,6 @@
+
+ static guint password_view_signals [LAST_SIGNAL] = { 0 };
+
+-
+ G_DEFINE_TYPE_WITH_PRIVATE (EvPasswordView, ev_password_view, GTK_TYPE_VIEWPORT)
+
+ static void
+--- a/shell/ev-sidebar-attachments.c
++++ b/shell/ev-sidebar-attachments.c
+@@ -631,7 +631,6 @@
+ g_object_unref (job);
+ }
+
+-
+ static void
+ ev_sidebar_attachments_document_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+--- a/shell/ev-sidebar-bookmarks.c
++++ b/shell/ev-sidebar-bookmarks.c
+@@ -122,7 +122,6 @@
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+-
+ selection = gtk_tree_view_get_selection (tree_view);
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ GtkTreePath *path;
+--- a/shell/ev-sidebar-layers.c
++++ b/shell/ev-sidebar-layers.c
+@@ -239,7 +239,6 @@
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (tree_view),
+ GTK_SELECTION_NONE);
+
+-
+ column = gtk_tree_view_column_new ();
+
+ renderer = gtk_cell_renderer_toggle_new ();
+--- a/shell/ev-sidebar-links.c
++++ b/shell/ev-sidebar-links.c
+@@ -379,7 +379,6 @@
+ return FALSE;
+ }
+
+-
+ static void
+ ev_sidebar_links_construct (EvSidebarLinks *ev_sidebar_links)
+ {
+@@ -425,7 +424,6 @@
+ "markup", EV_DOCUMENT_LINKS_COLUMN_MARKUP,
+ NULL);
+
+-
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_end (GTK_TREE_VIEW_COLUMN (column), renderer, FALSE);
+ gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
+@@ -566,7 +564,6 @@
+ }
+ }
+
+-
+ static gint
+ page_link_tree_sort (gconstpointer a, gconstpointer b, void *data)
+ {
+--- a/shell/ev-sidebar-links.h
++++ b/shell/ev-sidebar-links.h
+@@ -63,4 +63,3 @@
+
+ #endif /* __EV_SIDEBAR_LINKS_H__ */
+
+-
+--- a/shell/ev-sidebar-page.c
++++ b/shell/ev-sidebar-page.c
+@@ -74,7 +74,6 @@
+ return iface->get_label (sidebar_page);
+ }
+
+-
+ static void
+ ev_sidebar_page_default_init (EvSidebarPageInterface *iface)
+ {
+--- a/shell/ev-sidebar-page.h
++++ b/shell/ev-sidebar-page.h
+@@ -58,7 +58,6 @@
+ EvDocumentModel *model);
+ const gchar* ev_sidebar_page_get_label (EvSidebarPage *page);
+
+-
+ G_END_DECLS
+
+ #endif /* EV_SIDEBAR_PAGE */
+--- a/shell/ev-sidebar-thumbnails.c
++++ b/shell/ev-sidebar-thumbnails.c
+@@ -245,7 +245,6 @@
+ return cache;
+ }
+
+-
+ static void
+ ev_sidebar_thumbnails_dispose (GObject *object)
+ {
+--- a/shell/ev-sidebar-thumbnails.h
++++ b/shell/ev-sidebar-thumbnails.h
+@@ -56,4 +56,3 @@
+
+ #endif /* __EV_SIDEBAR_THUMBNAILS_H__ */
+
+-
+--- a/shell/ev-sidebar.c
++++ b/shell/ev-sidebar.c
+@@ -446,7 +446,6 @@
+ gtk_list_store_move_before(GTK_LIST_STORE(ev_sidebar->priv->page_model),
+ &iter, NULL);
+
+-
+ /* Set the first item added as active */
+ gtk_tree_model_get_iter_first (ev_sidebar->priv->page_model, &iter);
+ gtk_tree_model_get (ev_sidebar->priv->page_model,
+--- a/shell/ev-sidebar.h
++++ b/shell/ev-sidebar.h
+@@ -64,4 +64,3 @@
+
+ #endif /* __EV_SIDEBAR_H__ */
+
+-
+--- a/shell/ev-window.c
++++ b/shell/ev-window.c
+@@ -418,7 +418,6 @@
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+ }
+
+-
+ static void
+ ev_window_setup_action_sensitivity (EvWindow *ev_window)
+ {
+@@ -1555,7 +1554,6 @@
+ ev_document_model_set_scale (model, g_settings_get_double (settings, "zoom"));
+ }
+
+-
+ static void
+ ev_window_clear_thumbnail_job (EvWindow *ev_window)
+ {
+@@ -3636,7 +3634,6 @@
+ GtkWidget *dialog;
+ GError *error = NULL;
+
+-
+ ev_print_operation_get_error (op, &error);
+
+ /* The message area is already used by
+@@ -3891,7 +3888,6 @@
+ return FALSE;
+ }
+
+-
+ text = g_markup_printf_escaped (_("Save a copy of document “%s” before closing?"),
+ gtk_window_get_title (GTK_WINDOW (ev_window)));
+
+@@ -4414,7 +4410,6 @@
+ _("Running in presentation mode"));
+ }
+
+-
+ static void
+ ev_window_uninhibit_screensaver (EvWindow *window)
+ {
+@@ -4727,7 +4722,6 @@
+ ev_window_update_actions (window);
+ }
+
+-
+ static void
+ ev_window_cmd_edit_rotate_left (GtkAction *action, EvWindow *ev_window)
+ {
+@@ -5977,7 +5971,6 @@
+ * the new expanded window size.
+ */
+
+-
+ if (ev_window->priv->chrome & EV_CHROME_SIDEBAR)
+ {
+ GtkAllocation alloc;
+@@ -6491,7 +6484,6 @@
+ { "EditSaveSettings", NULL, N_("Save Current Settings as _Default"), "<control>T", NULL,
+ G_CALLBACK (ev_window_cmd_edit_save_settings) },
+
+-
+ /* View menu */
+ { "ViewZoomIn", "zoom-in", N_("Zoom _In"), "<control>plus",
+ N_("Enlarge the document"),
+@@ -7746,7 +7738,6 @@
+ ev_atril_window_emit_document_loaded (window->priv->skeleton, window->priv->uri);
+ }
+
+-
+ #ifdef ENABLE_SYNCTEX
+ static gboolean
+ handle_sync_view_cb (EvAtrilWindow *object,
+--- a/shell/ev-window.h
++++ b/shell/ev-window.h
+@@ -58,7 +58,6 @@
+ #define EV_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_WINDOW))
+ #define EV_WINDOW_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_WINDOW, EvWindowClass))
+
+-
+ struct _EvWindow {
+ GtkApplicationWindow base_instance;
+ EvWindowPrivate *priv;
+@@ -87,7 +86,6 @@
+ int last_page);
+ const gchar * ev_window_get_dbus_object_path (EvWindow *ev_window);
+
+-
+ G_END_DECLS
+
+ #endif /* !EV_WINDOW_H */
+--- a/shell/main.c
++++ b/shell/main.c
+@@ -36,7 +36,6 @@
+ #include "eggsmclient.h"
+ #include "eggdesktopfile.h"
+
+-
+ static gchar *ev_page_label;
+ static gchar *ev_find_string;
+ static gint ev_page_index = 0;
+@@ -48,7 +47,6 @@
+ static gchar *print_settings;
+ static const char **file_arguments = NULL;
+
+-
+ static gboolean
+ option_version_cb (const gchar *option_name,
+ const gchar *value,
+@@ -206,8 +204,6 @@
+ continue;
+ }
+
+-
+-
+ ev_application_open_uri_at_dest (EV_APP, uri, screen, dest,
+ mode, ev_find_string,
+ GDK_CURRENT_TIME);
diff -Nru atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch
--- atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch 2024-01-23 10:06:08.000000000 +0100
@@ -0,0 +1,1814 @@
+From aa8e9dad472cbadc96719a8f521768aeeb0913f0 Mon Sep 17 00:00:00 2001
+From: lukefromdc <lukefromdc@hushmail.com>
+Date: Mon, 25 Dec 2023 15:11:04 -0500
+Subject: [PATCH 2/2] comics: Use libarchive to unpack documents
+
+This commit eliminates the use of external commands for opening
+comic documents, and uses libarchive instead.
+
+Signed-off-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+---
+ backend/comics/Makefile.am | 5 +-
+ backend/comics/comics-document.c | 1143 +++++++++++-------------------
+ backend/comics/comics-document.h | 7 +-
+ backend/comics/ev-archive.c | 323 +++++++++
+ backend/comics/ev-archive.h | 56 ++
+ configure.ac | 3 +
+ libdocument/ev-document.h | 1 +
+ 7 files changed, 799 insertions(+), 739 deletions(-)
+ create mode 100644 backend/comics/ev-archive.c
+ create mode 100644 backend/comics/ev-archive.h
+
+diff --git a/backend/comics/Makefile.am b/backend/comics/Makefile.am
+index b27f9b85..77f3dedb 100644
+--- a/backend/comics/Makefile.am
++++ b/backend/comics/Makefile.am
+@@ -12,12 +12,15 @@ backend_LTLIBRARIES = libcomicsdocument.la
+
+ libcomicsdocument_la_SOURCES = \
+ comics-document.c \
+- comics-document.h
++ comics-document.h \
++ ev-archive.c \
++ ev-archive.h
+
+ libcomicsdocument_la_LDFLAGS = $(BACKEND_LIBTOOL_FLAGS)
+ libcomicsdocument_la_LIBADD = \
+ $(top_builddir)/libdocument/libatrildocument.la \
+ $(BACKEND_LIBS) \
++ $(COMICS_LIBS) \
+ $(LIB_LIBS)
+
+ backend_in_files = comicsdocument.atril-backend.desktop.in
+diff --git a/backend/comics/comics-document.c b/backend/comics/comics-document.c
+index ed02a35c..1da1eee2 100644
+--- a/backend/comics/comics-document.c
++++ b/backend/comics/comics-document.c
+@@ -30,24 +30,17 @@
+ #include <glib/gstdio.h>
+ #include <gio/gio.h>
+
+-#include <sys/wait.h>
+-
+ #include "comics-document.h"
+ #include "ev-document-misc.h"
+ #include "ev-document-thumbnails.h"
+ #include "ev-file-helpers.h"
++#include "ev-archive.h"
++#include <archive.h>
++#include <archive_entry.h>
+
+ #define EV_EOL "\n"
+
+-typedef enum
+-{
+- RARLABS,
+- GNAUNRAR,
+- UNZIP,
+- P7ZIP,
+- TAR,
+- UNARCHIVER
+-} ComicBookDecompressType;
++#define BLOCK_SIZE 10240
+
+ typedef struct _ComicsDocumentClass ComicsDocumentClass;
+
+@@ -58,398 +51,269 @@ struct _ComicsDocumentClass
+
+ struct _ComicsDocument
+ {
+- EvDocument parent_instance;
+-
+- gchar *archive, *dir;
+- GPtrArray *page_names;
+- gchar *selected_command, *alternative_command;
+- gchar *extract_command, *list_command, *decompress_tmp;
+- gboolean regex_arg;
+- gint offset;
+- ComicBookDecompressType command_usage;
++ EvDocument parent_instance;
++ EvArchive *archive;
++ gchar *archive_path;
++ gchar *archive_uri;
++ GPtrArray *page_names; /* elem: char * */
++ GHashTable *page_positions; /* key: char *, value: uint + 1 */
++
+ };
+
+-#define OFFSET_7Z 53
+-#define OFFSET_ZIP 2
+-#define NO_OFFSET 0
+-
+-/* For perfomance reasons of 7z* we've choosen to decompress on the temporary
+- * directory instead of decompressing on the stdout */
+-
+-/**
+- * @extract: command line arguments to pass to extract a file from the archive
+- * to stdout.
+- * @list: command line arguments to list the archive contents
+- * @decompress_tmp: command line arguments to pass to extract the archive
+- * into a directory.
+- * @regex_arg: whether the command can accept regex expressions
+- * @offset: the position offset of the filename on each line in the output of
+- * running the @list command
+- */
+-typedef struct {
+- char *extract;
+- char *list;
+- char *decompress_tmp;
+- gboolean regex_arg;
+- gint offset;
+-} ComicBookDecompressCommand;
++static void
++comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
++EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,
++ {
++ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
++ comics_document_document_thumbnails_iface_init);
++ } );
++
++#define FORMAT_UNKNOWN 0
++#define FORMAT_SUPPORTED 1
++#define FORMAT_UNSUPPORTED 2
++
++/* Returns a GHashTable of:
++ * <key>: file extensions
++ * <value>: degree of support in gdk-pixbuf */
++static GHashTable *
++get_image_extensions(void)
++{
++ GHashTable *extensions;
++ GSList *formats = gdk_pixbuf_get_formats ();
++ GSList *l;
++ guint i;
++ const char *known_image_formats[] = {
++ "png",
++ "jpg",
++ "jpeg",
++ "webp"
++ };
++
++ extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
++ g_free, NULL);
++ for (l = formats; l != NULL; l = l->next) {
++ int i;
++ gchar **ext = gdk_pixbuf_format_get_extensions (l->data);
++
++ for (i = 0; ext[i] != NULL; i++) {
++ g_hash_table_insert (extensions,
++ g_strdup (ext[i]),
++ GINT_TO_POINTER (FORMAT_SUPPORTED));
++ }
+
+-static const ComicBookDecompressCommand command_usage_def[] = {
+- /* RARLABS unrar */
+- {"%s p -c- -ierr --", "%s vb -c- -- %s", NULL , FALSE, NO_OFFSET},
++ g_strfreev (ext);
++ }
++ g_slist_free (formats);
+
+- /* GNA! unrar */
+- {NULL , "%s t %s" , "%s -xf %s %s" , FALSE, NO_OFFSET},
++ /* Add known image formats that aren't supported by gdk-pixbuf */
++ for (i = 0; i < G_N_ELEMENTS (known_image_formats); i++) {
++ if (!g_hash_table_lookup (extensions, known_image_formats[i])) {
++ g_hash_table_insert (extensions,
++ g_strdup (known_image_formats[i]),
++ GINT_TO_POINTER (FORMAT_UNSUPPORTED));
++ }
++ }
+
+- /* unzip */
+- {"%s -p -C --" , "%s %s" , NULL , TRUE , OFFSET_ZIP},
++ return extensions;
++}
+
+- /* 7zip */
+- {NULL , "%s l -- %s" , "%s x -y %s -o%s", FALSE, OFFSET_7Z},
++static int
++has_supported_extension (const char *name,
++ GHashTable *supported_extensions)
++{
++ gboolean ret = FALSE;
++ gchar *suffix;
++ suffix = g_strrstr (name, ".");
++ if (!suffix)
++ return ret;
+
+- /* tar */
+- {"%s -xOf" , "%s -tf %s" , NULL , FALSE, NO_OFFSET},
++ suffix = g_ascii_strdown (suffix + 1, -1);
++ ret = GPOINTER_TO_INT (g_hash_table_lookup (supported_extensions, suffix));
++ g_free (suffix);
+
+- /* UNARCHIVER */
+- {"unar -o -" , "%s %s" , NULL , FALSE, NO_OFFSET}
+-};
++ return ret;
++}
+
+-static void comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
++#define APPLE_DOUBLE_PREFIX "._"
++static gboolean
++is_apple_double (const char *name)
++{
++char *basename;
++ gboolean ret = FALSE;
+
+-static GSList* get_supported_image_extensions (void);
+-static void get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
+- gpointer data);
+-static void render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
+- gint width,
+- gint height,
+- gpointer data);
+-static char** extract_argv (EvDocument *document,
+- gint page);
++ basename = g_path_get_basename (name);
++ if (basename == NULL) {
++ g_debug ("Filename '%s' doesn't have a basename?", name);
++ return ret;
++ }
++ ret = g_str_has_prefix (basename, APPLE_DOUBLE_PREFIX);
++ g_free (basename);
+
+-EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,
+- {
+- EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+- comics_document_document_thumbnails_iface_init);
+- } );
+-
+-/**
+- * comics_regex_quote:
+- * @unquoted_string: a literal string
+- *
+- * Quotes a string so unzip will not interpret the regex expressions of
+- * @unquoted_string. Basically, this functions uses [] to disable regex
+- * expressions. The return value must be freed with * g_free()
+- *
+- * Return value: quoted and disabled-regex string
+- **/
+-static gchar *
+-comics_regex_quote (const gchar *unquoted_string)
++ return ret;
++}
++
++static gboolean
++archive_reopen_if_needed (ComicsDocument *comics_document,
++ const char *page_wanted,
++ GError **error)
+ {
+- const gchar *p;
+- GString *dest;
+-
+- dest = g_string_new ("'");
+-
+- p = unquoted_string;
+-
+- while (*p) {
+- switch (*p) {
+- /* * matches a sequence of 0 or more characters */
+- case ('*'):
+- /* ? matches exactly 1 charactere */
+- case ('?'):
+- /* [...] matches any single character found inside
+- * the brackets. Disabling the first bracket is enough.
+- */
+- case ('['):
+- g_string_append (dest, "[");
+- g_string_append_c (dest, *p);
+- g_string_append (dest, "]");
+- break;
+- /* Because \ escapes regex expressions that we are
+- * disabling for unzip, we need to disable \ too */
+- case ('\\'):
+- g_string_append (dest, "[\\\\]");
+- break;
+- /* Escape single quote inside the string */
+- case ('\''):
+- g_string_append (dest, "'\\''");
+- break;
+- default:
+- g_string_append_c (dest, *p);
+- break;
++ const char *current_page;
++ guint current_page_idx, page_wanted_idx;
++
++ if (ev_archive_at_entry (comics_document->archive)) {
++ current_page = ev_archive_get_entry_pathname (comics_document->archive);
++ if (current_page) {
++ current_page_idx = GPOINTER_TO_UINT (g_hash_table_lookup (comics_document->page_positions, current_page));
++ page_wanted_idx = GPOINTER_TO_UINT (g_hash_table_lookup (comics_document->page_positions, page_wanted));
++
++ if (current_page_idx != 0 &&
++ page_wanted_idx != 0 &&
++ page_wanted_idx > current_page_idx)
++ return TRUE;
+ }
+- ++p;
++
++ ev_archive_reset (comics_document->archive);
+ }
+- g_string_append_c (dest, '\'');
+- return g_string_free (dest, FALSE);
++return ev_archive_open_filename (comics_document->archive, comics_document->archive_path, error);
+ }
+
+-/* This function manages the command for decompressing a comic book */
+-static gboolean
+-comics_decompress_temp_dir (const gchar *command_decompress_tmp,
+- const gchar *command,
+- GError **error)
++static GPtrArray *
++comics_document_list (ComicsDocument *comics_document,
++ GError **error)
+ {
+- gboolean success;
+- gchar *std_out, *basename;
+- GError *err = NULL;
+- gint retval;
+-
+- success = g_spawn_command_line_sync (command_decompress_tmp, &std_out,
+- NULL, &retval, &err);
+- basename = g_path_get_basename (command);
+- if (!success) {
+- g_set_error (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("Error launching the command “%s” in order to "
+- "decompress the comic book: %s"),
+- basename,
+- err->message);
+- g_error_free (err);
+- } else if (WIFEXITED (retval)) {
+- if (WEXITSTATUS (retval) == EXIT_SUCCESS) {
+- g_free (std_out);
+- g_free (basename);
+- return TRUE;
+- } else {
+- g_set_error (error,
++GPtrArray *array = NULL;
++ gboolean has_encrypted_files, has_unsupported_images, has_archive_errors;
++ GHashTable *supported_extensions = NULL;
++
++ if (!ev_archive_open_filename (comics_document->archive, comics_document->archive_path, error)) {
++ if (*error != NULL) {
++ g_warning ("Fatal error handling archive (%s): %s", G_STRFUNC, (*error)->message);
++ g_clear_error (error);
++ }
++
++ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+- _("The command “%s” failed at "
+- "decompressing the comic book."),
+- basename);
+- g_free (std_out);
++ _("File is corrupted"));
++ goto out;
++ }
++
++ supported_extensions = get_image_extensions ();
++
++ has_encrypted_files = FALSE;
++ has_unsupported_images = FALSE;
++ has_archive_errors = FALSE;
++ array = g_ptr_array_sized_new (64);
++
++ while (1) {
++ const char *name;
++ int supported;
++
++ if (!ev_archive_read_next_header (comics_document->archive, error)) {
++ if (*error != NULL) {
++ g_debug ("Fatal error handling archive (%s): %s", G_STRFUNC, (*error)->message);
++ g_clear_error (error);
++ has_archive_errors = TRUE;
++ goto out;
++ }
++ break;
+ }
+- } else {
+- g_set_error (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("The command “%s” did not end normally."),
+- basename);
+- g_free (std_out);
++
++ name = ev_archive_get_entry_pathname (comics_document->archive);
++ /* Ignore https://en.wikipedia.org/wiki/AppleSingle_and_AppleDouble_formats */
++ if (is_apple_double (name)) {
++ g_debug ("Not adding AppleDouble file '%s' to the list of files in the comics", name);
++ continue;
++ }
++
++ supported = has_supported_extension (name, supported_extensions);
++ if (supported == FORMAT_UNKNOWN) {
++ g_debug ("Not adding unsupported file '%s' to the list of files in the comics", name);
++ continue;
++ } else if (supported == FORMAT_UNSUPPORTED) {
++ g_debug ("Not adding unsupported image '%s' to the list of files in the comics", name);
++ has_unsupported_images = TRUE;
++ continue;
++ }
++
++ if (ev_archive_get_entry_is_encrypted (comics_document->archive)) {
++ g_debug ("Not adding encrypted file '%s' to the list of files in the comics", name);
++ has_encrypted_files = TRUE;
++ continue;
++ }
++
++ g_debug ("Adding '%s' to the list of files in the comics", name);
++ g_ptr_array_add (array, g_strdup (name));
+ }
+- g_free (basename);
+- return FALSE;
++out:
++ if (array->len == 0) {
++ g_ptr_array_free (array, TRUE);
++ array = NULL;
++
++ if (has_encrypted_files) {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_ENCRYPTED,
++ _("Archive is encrypted"));
++ } else if (has_unsupported_images) {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_UNSUPPORTED_CONTENT,
++ _("No supported images in archive"));
++ } else if (has_archive_errors) {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_INVALID,
++ _("File is corrupted"));
++ } else {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_INVALID,
++ _("No files in archive"));
++ }
++ }
++
++ if (supported_extensions)
++ g_hash_table_destroy (supported_extensions);
++ ev_archive_reset (comics_document->archive);
++ return array;
+ }
+
+-/* This function shows how to use the choosen command for decompressing a
+- * comic book file. It modifies fields of the ComicsDocument struct with
+- * this information */
+-static gboolean
+-comics_generate_command_lines (ComicsDocument *comics_document,
+- GError **error)
++static GHashTable *
++save_positions (GPtrArray *page_names)
+ {
+- gchar *quoted_file, *quoted_file_aux;
+- gchar *quoted_command;
+- ComicBookDecompressType type;
+-
+- type = comics_document->command_usage;
+- comics_document->regex_arg = command_usage_def[type].regex_arg;
+- quoted_command = g_shell_quote (comics_document->selected_command);
+- if (comics_document->regex_arg) {
+- quoted_file = comics_regex_quote (comics_document->archive);
+- quoted_file_aux = g_shell_quote (comics_document->archive);
+- comics_document->list_command =
+- g_strdup_printf (command_usage_def[type].list,
+- comics_document->alternative_command,
+- quoted_file_aux);
+- g_free (quoted_file_aux);
+- } else {
+- quoted_file = g_shell_quote (comics_document->archive);
+- comics_document->list_command =
+- g_strdup_printf (command_usage_def[type].list,
+- quoted_command, quoted_file);
+- }
+- comics_document->extract_command =
+- g_strdup_printf (command_usage_def[type].extract,
+- quoted_command);
+- comics_document->offset = command_usage_def[type].offset;
+- if (command_usage_def[type].decompress_tmp) {
+- comics_document->dir = ev_mkdtemp ("atril-comics-XXXXXX", error);
+- if (comics_document->dir == NULL)
+- return FALSE;
+-
+- /* unrar-free can't create directories, but ev_mkdtemp already created the dir */
+-
+- comics_document->decompress_tmp =
+- g_strdup_printf (command_usage_def[type].decompress_tmp,
+- quoted_command, quoted_file,
+- comics_document->dir);
+- g_free (quoted_file);
+- g_free (quoted_command);
+-
+- if (!comics_decompress_temp_dir (comics_document->decompress_tmp,
+- comics_document->selected_command, error))
+- return FALSE;
+- else
+- return TRUE;
+- } else {
+- g_free (quoted_file);
+- g_free (quoted_command);
+- return TRUE;
+- }
++ guint i;
++ GHashTable *ht;
+
++ ht = g_hash_table_new (g_str_hash, g_str_equal);
++ for (i = 0; i < page_names->len; i++)
++ g_hash_table_insert (ht, page_names->pdata[i], GUINT_TO_POINTER(i + 1));
++ return ht;
+ }
+
+-/* This function chooses an external command for decompressing a comic
+- * book based on its mime tipe. */
++/*This function chooses the archive decompression support
++ * book based on its mime type. */
+ static gboolean
+-comics_check_decompress_command (gchar *mime_type,
++comics_check_decompress_support (gchar *mime_type,
+ ComicsDocument *comics_document,
+ GError **error)
+ {
+- gboolean success;
+- gchar *std_out, *std_err;
+- gint retval;
+- GError *err = NULL;
+-
+- /* FIXME, use proper cbr/cbz mime types once they're
+- * included in shared-mime-info */
+-
+ if (g_content_type_is_a (mime_type, "application/x-cbr") ||
+ g_content_type_is_a (mime_type, "application/x-rar")) {
+- /* The RARLAB provides a no-charge proprietary (freeware)
+- * decompress-only client for Linux called unrar. Another
+- * option is a GPLv2-licensed command-line tool developed by
+- * the Gna! project. Confusingly enough, the free software RAR
+- * decoder is also named unrar. For this reason we need to add
+- * some lines for disambiguation. Sorry for the added the
+- * complexity but it's life :)
+- * Finally, some distributions, like Debian, rename this free
+- * option as unrar-free.
+- * */
+- comics_document->selected_command =
+- g_find_program_in_path ("unrar");
+- if (comics_document->selected_command) {
+- /* We only use std_err to avoid printing useless error
+- * messages on the terminal */
+- success =
+- g_spawn_command_line_sync (
+- comics_document->selected_command,
+- &std_out, &std_err,
+- &retval, &err);
+- if (!success) {
+- g_propagate_error (error, err);
+- g_error_free (err);
+- return FALSE;
+- /* I don't check retval status because RARLAB unrar
+- * doesn't have a way to return 0 without involving an
+- * operation with a file*/
+- } else if (WIFEXITED (retval)) {
+- if (g_strrstr (std_out,"freeware") != NULL)
+- /* The RARLAB freeware client */
+- comics_document->command_usage = RARLABS;
+- else
+- /* The Gna! free software client */
+- comics_document->command_usage = GNAUNRAR;
+-
+- g_free (std_out);
+- g_free (std_err);
+- return TRUE;
+- }
+- }
+- /* The Gna! free software client with Debian naming convention */
+- comics_document->selected_command =
+- g_find_program_in_path ("unrar-free");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = GNAUNRAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_RAR))
+ return TRUE;
+- }
+-
+ } else if (g_content_type_is_a (mime_type, "application/x-cbz") ||
+ g_content_type_is_a (mime_type, "application/zip")) {
+- /* InfoZIP's unzip program */
+- comics_document->selected_command =
+- g_find_program_in_path ("unzip");
+- comics_document->alternative_command =
+- g_find_program_in_path ("zipnote");
+- if (comics_document->selected_command &&
+- comics_document->alternative_command) {
+- comics_document->command_usage = UNZIP;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_ZIP))
+ return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+-
+ } else if (g_content_type_is_a (mime_type, "application/x-cb7") ||
+ g_content_type_is_a (mime_type, "application/x-7z-compressed")) {
+- /* 7zr, 7za and 7z are the commands from the p7zip project able
+- * to decompress .7z files */
+- comics_document->selected_command =
+- g_find_program_in_path ("7zr");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = P7ZIP;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_7Z))
+ return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("7za");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = P7ZIP;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("7z");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = P7ZIP;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+ } else if (g_content_type_is_a (mime_type, "application/x-cbt") ||
+ g_content_type_is_a (mime_type, "application/x-tar")) {
+- /* tar utility (Tape ARchive) */
+- comics_document->selected_command =
+- g_find_program_in_path ("tar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_TAR))
+ return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+ } else {
+ g_set_error (error,
+ EV_DOCUMENT_ERROR,
+@@ -461,8 +325,9 @@ comics_check_decompress_command (gchar *mime_type,
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+- _("Can't find an appropriate command to "
+- "decompress this type of comic book"));
++ _("libarchive lacks support for this comic book’s "
++ "compression, please contact your distributor"));
++
+ return FALSE;
+ }
+
+@@ -470,43 +335,15 @@ static int
+ sort_page_names (gconstpointer a,
+ gconstpointer b)
+ {
+- const char *name_1, *name_2;
+- gchar *key_1, *key_2;
+- gboolean sort_last_1, sort_last_2;
+- int compare;
+-
+- name_1 = * (const char **) a;
+- name_2 = * (const char **) b;
+-
+- #define SORT_LAST_CHAR1 '.'
+- #define SORT_LAST_CHAR2 '#'
+-
+- sort_last_1 = name_1[0] == SORT_LAST_CHAR1 || name_1[0] == SORT_LAST_CHAR2;
+- sort_last_2 = name_2[0] == SORT_LAST_CHAR1 || name_2[0] == SORT_LAST_CHAR2;
+-
+- #undef SORT_LAST_CHAR1
+- #undef SORT_LAST_CHAR2
+-
+- if (sort_last_1 && !sort_last_2)
+- {
+- compare = +1;
+- }
+- else if (!sort_last_1 && sort_last_2)
+- {
+- compare = -1;
+- }
+- else
+- {
+- key_1 = g_utf8_collate_key_for_filename (name_1, -1);
+- key_2 = g_utf8_collate_key_for_filename (name_2, -1);
+-
+- compare = strcmp (key_1, key_2);
+-
+- g_free (key_1);
+- g_free (key_2);
+- }
+-
+- return compare;
++ gchar *temp1, *temp2;
++ gint ret;
++ temp1 = g_utf8_collate_key_for_filename (* (const char **) a, -1);
++ temp2 = g_utf8_collate_key_for_filename (* (const char **) b, -1);
++ ret = strcmp (temp1, temp2);
++
++ g_free (temp1);
++ g_free (temp2);
++ return ret;
+ }
+
+ static gboolean
+@@ -515,50 +352,13 @@ comics_document_load (EvDocument *document,
+ GError **error)
+ {
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+- GSList *supported_extensions;
+- gchar *std_out;
+ gchar *mime_type;
+- gchar **cb_files, *cb_file;
+- gboolean success;
+- int i, retval;
+- GError *err = NULL;
+-
+- comics_document->archive = g_filename_from_uri (uri, NULL, error);
+- if (!comics_document->archive)
+- return FALSE;
+-
+- mime_type = ev_file_get_mime_type (uri, FALSE, &err);
+- if (!mime_type) {
+- if (err) {
+- g_propagate_error (error, err);
+- } else {
+- g_set_error_literal (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("Unknown MIME Type"));
+- }
+-
+- return FALSE;
+- }
+-
+- if (!comics_check_decompress_command (mime_type, comics_document,
+- error)) {
+- g_free (mime_type);
+- return FALSE;
+- } else if (!comics_generate_command_lines (comics_document, error)) {
+- g_free (mime_type);
+- return FALSE;
+- }
++ GFile *file;
++ file = g_file_new_for_uri (uri);
++ comics_document->archive_path = g_file_get_path (file);
++ g_object_unref (file);
+
+- g_free (mime_type);
+-
+- /* Get list of files in archive */
+- success = g_spawn_command_line_sync (comics_document->list_command,
+- &std_out, NULL, &retval, error);
+-
+- if (!success) {
+- return FALSE;
+- } else if (!WIFEXITED(retval) || WEXITSTATUS(retval) != EXIT_SUCCESS) {
++ if (!comics_document->archive_path) {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+@@ -566,58 +366,26 @@ comics_document_load (EvDocument *document,
+ return FALSE;
+ }
+
+- /* FIXME: is this safe against filenames containing \n in the archive ? */
+- cb_files = g_strsplit (std_out, EV_EOL, 0);
++ comics_document->archive_uri = g_strdup (uri);
++ mime_type = ev_file_get_mime_type (uri, FALSE, error);
+
+- g_free (std_out);
++ if (mime_type == NULL)
++ return FALSE;
+
+- if (!cb_files) {
+- g_set_error_literal (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("No files in archive"));
++ if (!comics_check_decompress_support (mime_type, comics_document, error)) {
++ g_free (mime_type);
+ return FALSE;
+ }
+
+- comics_document->page_names = g_ptr_array_sized_new (64);
+-
+- supported_extensions = get_supported_image_extensions ();
+- for (i = 0; cb_files[i] != NULL; i++) {
+- if (comics_document->offset != NO_OFFSET) {
+- if (g_utf8_strlen (cb_files[i],-1) >
+- comics_document->offset) {
+- cb_file =
+- g_utf8_offset_to_pointer (cb_files[i],
+- comics_document->offset);
+- } else {
+- continue;
+- }
+- } else {
+- cb_file = cb_files[i];
+- }
+- gchar *suffix = g_strrstr (cb_file, ".");
+- if (!suffix)
+- continue;
+- suffix = g_ascii_strdown (suffix + 1, -1);
+- if (g_slist_find_custom (supported_extensions, suffix,
+- (GCompareFunc) strcmp) != NULL) {
+- g_ptr_array_add (comics_document->page_names,
+- g_strstrip (g_strdup (cb_file)));
+- }
+- g_free (suffix);
+- }
+- g_strfreev (cb_files);
+- g_slist_foreach (supported_extensions, (GFunc) g_free, NULL);
+- g_slist_free (supported_extensions);
++ g_free (mime_type);
+
+- if (comics_document->page_names->len == 0) {
+- g_set_error (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("No images found in archive %s"),
+- uri);
++ /* Get list of files in archive */
++ comics_document->page_names = comics_document_list (comics_document, error);
++ if (!comics_document->page_names)
+ return FALSE;
+- }
++
++ /* Keep an index */
++ comics_document->page_positions = save_positions (comics_document->page_names);
+
+ /* Now sort the pages */
+ g_ptr_array_sort (comics_document->page_names, sort_page_names);
+@@ -632,7 +400,7 @@ comics_document_save (EvDocument *document,
+ {
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+
+- return ev_xfer_uri_simple (comics_document->archive, uri, error);
++ return ev_xfer_uri_simple (comics_document->archive_uri, uri, error);
+ }
+
+ static int
+@@ -646,6 +414,23 @@ comics_document_get_n_pages (EvDocument *document)
+ return comics_document->page_names->len;
+ }
+
++typedef struct {
++ gboolean got_info;
++ int height;
++ int width;
++} PixbufInfo;
++
++static void
++get_page_size_prepared_cb (GdkPixbufLoader *loader,
++ int width,
++ int height,
++ PixbufInfo *info)
++{
++ info->got_info = TRUE;
++ info->height = height;
++ info->width = width;
++}
++
+ static void
+ comics_document_get_page_size (EvDocument *document,
+ EvPage *page,
+@@ -653,74 +438,89 @@ comics_document_get_page_size (EvDocument *document,
+ double *height)
+ {
+ GdkPixbufLoader *loader;
+- char **argv;
+- guchar buf[1024];
+- gboolean success, got_size = FALSE;
+- gint outpipe = -1;
+- GPid child_pid;
+- gssize bytes;
+- GdkPixbuf *pixbuf;
+- gchar *filename;
++
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+
+- if (!comics_document->decompress_tmp) {
+- argv = extract_argv (document, page->index);
+- success = g_spawn_async_with_pipes (NULL, argv, NULL,
+- G_SPAWN_SEARCH_PATH |
+- G_SPAWN_STDERR_TO_DEV_NULL,
+- NULL, NULL,
+- &child_pid,
+- NULL, &outpipe, NULL, NULL);
+- g_strfreev (argv);
+- g_return_if_fail (success == TRUE);
+-
+- loader = gdk_pixbuf_loader_new ();
+- g_signal_connect (loader, "area-prepared",
+- G_CALLBACK (get_page_size_area_prepared_cb),
+- &got_size);
+-
+- while (outpipe >= 0) {
+- bytes = read (outpipe, buf, 1024);
+-
+- if (bytes > 0)
+- gdk_pixbuf_loader_write (loader, buf, bytes, NULL);
+- if (bytes <= 0 || got_size) {
+- close (outpipe);
+- outpipe = -1;
+- gdk_pixbuf_loader_close (loader, NULL);
++ const char *page_path;
++ PixbufInfo info;
++ GError *error = NULL;
++
++ page_path = g_ptr_array_index (comics_document->page_names, page->index);
++
++ if (!archive_reopen_if_needed (comics_document, page_path, &error)) {
++ g_warning ("Fatal error opening archive: %s", error->message);
++ g_error_free (error);
++ return;
++ }
++
++ loader = gdk_pixbuf_loader_new ();
++ info.got_info = FALSE;
++ g_signal_connect (loader, "size-prepared",
++ G_CALLBACK (get_page_size_prepared_cb),
++ &info);
++
++ while (1) {
++ const char *name;
++ GError *error = NULL;
++
++ if (!ev_archive_read_next_header (comics_document->archive, &error)) {
++ if (error != NULL) {
++ g_warning ("Fatal error handling archive (%s): %s", G_STRFUNC, error->message);
++ g_error_free (error);
+ }
++ break;
+ }
+- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+- if (pixbuf) {
+- if (width)
+- *width = gdk_pixbuf_get_width (pixbuf);
+- if (height)
+- *height = gdk_pixbuf_get_height (pixbuf);
+- }
+- g_spawn_close_pid (child_pid);
+- g_object_unref (loader);
+- } else {
+- filename = g_build_filename (comics_document->dir,
+- (char *) comics_document->page_names->pdata[page->index],
+- NULL);
+- pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+- if (pixbuf) {
+- if (width)
+- *width = gdk_pixbuf_get_width (pixbuf);
+- if (height)
+- *height = gdk_pixbuf_get_height (pixbuf);
+- g_object_unref (pixbuf);
++
++ name = ev_archive_get_entry_pathname (comics_document->archive);
++ if (g_strcmp0 (name, page_path) == 0) {
++ char buf[BLOCK_SIZE];
++ gssize read;
++ gint64 left;
++
++ left = ev_archive_get_entry_size (comics_document->archive);
++ read = ev_archive_read_data (comics_document->archive, buf,
++ MIN(BLOCK_SIZE, left), &error);
++ while (read > 0 && !info.got_info) {
++ if (!gdk_pixbuf_loader_write (loader, (guchar *) buf, read, &error)) {
++ read = -1;
++ break;
++ }
++ left -= read;
++ read = ev_archive_read_data (comics_document->archive, buf,
++ MIN(BLOCK_SIZE, left), &error);
++ }
++ if (read < 0) {
++ g_warning ("Fatal error reading '%s' in archive: %s", name, error->message);
++ g_error_free (error);
++ }
++ break;
+ }
+- g_free (filename);
++ }
++
++ gdk_pixbuf_loader_close (loader, NULL);
++ g_object_unref (loader);
++
++ if (info.got_info) {
++ if (width)
++ *width = info.width;
++ if (height)
++ *height = info.height;
+ }
+ }
+
+ static void
+-get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
+- gpointer data)
++render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
++ gint width,
++ gint height,
++ EvRenderContext *rc)
+ {
+- gboolean *got_size = data;
+- *got_size = TRUE;
++ // int scaled_width, scaled_height;
++ double scale = rc->scale;
++ int w = (width * scale + 0.5);
++ int h = (height * scale + 0.5);
++
++ // ev_render_context_compute_scaled_size (rc, width, height, &scaled_width, &scaled_height);
++ gdk_pixbuf_loader_set_size (loader, w, h);
+ }
+
+ static GdkPixbuf *
+@@ -728,69 +528,68 @@ comics_document_render_pixbuf (EvDocument *document,
+ EvRenderContext *rc)
+ {
+ GdkPixbufLoader *loader;
+- GdkPixbuf *rotated_pixbuf, *tmp_pixbuf;
+- char **argv;
+- guchar buf[4096];
+- gboolean success;
+- gint outpipe = -1;
+- GPid child_pid;
+- gssize bytes;
+- gint width, height;
+- gchar *filename;
++ GdkPixbuf *tmp_pixbuf;
++ GdkPixbuf *rotated_pixbuf = NULL;
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
++ const char *page_path;
++ GError *error = NULL;
++
++ page_path = g_ptr_array_index (comics_document->page_names, rc->page->index);
++
++ if (!archive_reopen_if_needed (comics_document, page_path, &error)) {
++ g_warning ("Fatal error opening archive: %s", error->message);
++ g_error_free (error);
++ return NULL;
++ }
+
+- if (!comics_document->decompress_tmp) {
+- argv = extract_argv (document, rc->page->index);
+- success = g_spawn_async_with_pipes (NULL, argv, NULL,
+- G_SPAWN_SEARCH_PATH |
+- G_SPAWN_STDERR_TO_DEV_NULL,
+- NULL, NULL,
+- &child_pid,
+- NULL, &outpipe, NULL, NULL);
+- g_strfreev (argv);
+- g_return_val_if_fail (success == TRUE, NULL);
+-
+- loader = gdk_pixbuf_loader_new ();
+- g_signal_connect (loader, "size-prepared",
+- G_CALLBACK (render_pixbuf_size_prepared_cb),
+- &rc->scale);
+-
+- while (outpipe >= 0) {
+- bytes = read (outpipe, buf, 4096);
+-
+- if (bytes > 0) {
+- gdk_pixbuf_loader_write (loader, buf, bytes,
+- NULL);
++ loader = gdk_pixbuf_loader_new ();
++ g_signal_connect (loader, "size-prepared",
++ G_CALLBACK (render_pixbuf_size_prepared_cb),
++ rc);
++
++ while (1) {
++ const char *name;
++
++ if (!ev_archive_read_next_header (comics_document->archive, &error)) {
++ if (error != NULL) {
++ g_warning ("Fatal error handling archive (%s): %s", G_STRFUNC, error->message);
++ g_error_free (error);
++ }
++ break;
++ }
++
++ name = ev_archive_get_entry_pathname (comics_document->archive);
++ if (g_strcmp0 (name, page_path) == 0) {
++ size_t size = ev_archive_get_entry_size (comics_document->archive);
++ char *buf;
++ ssize_t read;
++
++ buf = g_malloc (size);
++ read = ev_archive_read_data (comics_document->archive, buf, size, &error);
++ if (read <= 0) {
++ if (read < 0) {
++ g_warning ("Fatal error reading '%s' in archive: %s", name, error->message);
++ g_error_free (error);
++ } else {
++ g_warning ("Read an empty file from the archive");
++ }
+ } else {
+- close (outpipe);
+- gdk_pixbuf_loader_close (loader, NULL);
+- outpipe = -1;
++ gdk_pixbuf_loader_write (loader, (guchar *) buf, size, NULL);
+ }
++ g_free (buf);
++ gdk_pixbuf_loader_close (loader, NULL);
++ break;
+ }
+- tmp_pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+- rotated_pixbuf =
+- gdk_pixbuf_rotate_simple (tmp_pixbuf,
+- 360 - rc->rotation);
+- g_spawn_close_pid (child_pid);
+- g_object_unref (loader);
+- } else {
+- filename =
+- g_build_filename (comics_document->dir,
+- (char *) comics_document->page_names->pdata[rc->page->index],
+- NULL);
+-
+- gdk_pixbuf_get_file_info (filename, &width, &height);
+-
+- tmp_pixbuf =
+- gdk_pixbuf_new_from_file_at_size (
+- filename, width * (rc->scale) + 0.5,
+- height * (rc->scale) + 0.5, NULL);
+- rotated_pixbuf =
+- gdk_pixbuf_rotate_simple (tmp_pixbuf,
+- 360 - rc->rotation);
+- g_free (filename);
+- g_object_unref (tmp_pixbuf);
+ }
++ tmp_pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
++ if (tmp_pixbuf) {
++ if ((rc->rotation % 360) == 0)
++ rotated_pixbuf = g_object_ref (tmp_pixbuf);
++ else
++ rotated_pixbuf = gdk_pixbuf_rotate_simple (tmp_pixbuf,
++ 360 - rc->rotation);
++ }
++ g_object_unref (loader);
+ return rotated_pixbuf;
+ }
+
+@@ -802,79 +601,26 @@ comics_document_render (EvDocument *document,
+ cairo_surface_t *surface;
+
+ pixbuf = comics_document_render_pixbuf (document, rc);
++ if (!pixbuf)
++ return NULL;
+ surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+- g_object_unref (pixbuf);
+-
++ g_clear_object (&pixbuf);
+ return surface;
+ }
+
+-static void
+-render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
+- gint width,
+- gint height,
+- gpointer data)
+-{
+- double *scale = data;
+- int w = (width * (*scale) + 0.5);
+- int h = (height * (*scale) + 0.5);
+-
+- gdk_pixbuf_loader_set_size (loader, w, h);
+-}
+-
+-/**
+- * comics_remove_dir: Removes a directory recursively.
+- * Returns:
+- * 0 if it was successfully deleted,
+- * -1 if an error occurred
+- */
+-static int
+-comics_remove_dir (gchar *path_name)
+-{
+- GDir *content_dir;
+- const gchar *filename;
+- gchar *filename_with_path;
+-
+- if (g_file_test (path_name, G_FILE_TEST_IS_DIR)) {
+- content_dir = g_dir_open (path_name, 0, NULL);
+- filename = g_dir_read_name (content_dir);
+- while (filename) {
+- filename_with_path =
+- g_build_filename (path_name,
+- filename, NULL);
+- comics_remove_dir (filename_with_path);
+- g_free (filename_with_path);
+- filename = g_dir_read_name (content_dir);
+- }
+- g_dir_close (content_dir);
+- }
+- /* Note from g_remove() documentation: on Windows, it is in general not
+- * possible to remove a file that is open to some process, or mapped
+- * into memory.*/
+- return (g_remove (path_name));
+-}
+-
+ static void
+ comics_document_finalize (GObject *object)
+ {
+ ComicsDocument *comics_document = COMICS_DOCUMENT (object);
+
+- if (comics_document->decompress_tmp) {
+- if (comics_remove_dir (comics_document->dir) == -1)
+- g_warning (_("There was an error deleting “%s”."),
+- comics_document->dir);
+- g_free (comics_document->dir);
+- }
+-
+ if (comics_document->page_names) {
+ g_ptr_array_foreach (comics_document->page_names, (GFunc) g_free, NULL);
+ g_ptr_array_free (comics_document->page_names, TRUE);
+ }
+-
+- g_free (comics_document->archive);
+- g_free (comics_document->selected_command);
+- g_free (comics_document->alternative_command);
+- g_free (comics_document->extract_command);
+- g_free (comics_document->list_command);
++ g_clear_pointer (&comics_document->page_positions, g_hash_table_destroy);
++ g_clear_object (&comics_document->archive);
++ g_free (comics_document->archive_path);
++ g_free (comics_document->archive_uri);
+
+ G_OBJECT_CLASS (comics_document_parent_class)->finalize (object);
+ }
+@@ -897,33 +643,7 @@ comics_document_class_init (ComicsDocumentClass *klass)
+ static void
+ comics_document_init (ComicsDocument *comics_document)
+ {
+- comics_document->archive = NULL;
+- comics_document->page_names = NULL;
+- comics_document->extract_command = NULL;
+-}
+-
+-/* Returns a list of file extensions supported by gdk-pixbuf */
+-static GSList*
+-get_supported_image_extensions(void)
+-{
+- GSList *extensions = NULL;
+- GSList *formats = gdk_pixbuf_get_formats ();
+- GSList *l;
+-
+- for (l = formats; l != NULL; l = l->next) {
+- int i;
+- gchar **ext = gdk_pixbuf_format_get_extensions (l->data);
+-
+- for (i = 0; ext[i] != NULL; i++) {
+- extensions = g_slist_append (extensions,
+- g_strdup (ext[i]));
+- }
+-
+- g_strfreev (ext);
+- }
+-
+- g_slist_free (formats);
+- return extensions;
++ comics_document->archive = ev_archive_new ();
+ }
+
+ static GdkPixbuf *
+@@ -971,48 +691,3 @@ comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *i
+ iface->get_thumbnail = comics_document_thumbnails_get_thumbnail;
+ iface->get_dimensions = comics_document_thumbnails_get_dimensions;
+ }
+-
+-static char**
+-extract_argv (EvDocument *document, gint page)
+-{
+- ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+- char **argv;
+- char *command_line, *quoted_archive, *quoted_filename;
+- GError *err = NULL;
+-
+- if (g_strrstr (comics_document->page_names->pdata[page], "--checkpoint-action="))
+- {
+- g_warning ("File unsupported\n");
+- gtk_main_quit ();
+- }
+-
+- if (page >= comics_document->page_names->len)
+- return NULL;
+-
+- if (comics_document->regex_arg) {
+- quoted_archive = g_shell_quote (comics_document->archive);
+- quoted_filename =
+- comics_regex_quote (comics_document->page_names->pdata[page]);
+- } else {
+- quoted_archive = g_shell_quote (comics_document->archive);
+- quoted_filename = g_shell_quote (comics_document->page_names->pdata[page]);
+- }
+-
+- command_line = g_strdup_printf ("%s %s %s",
+- comics_document->extract_command,
+- quoted_archive,
+- quoted_filename);
+- g_free (quoted_archive);
+- g_free (quoted_filename);
+-
+- g_shell_parse_argv (command_line, NULL, &argv, &err);
+- g_free (command_line);
+-
+- if (err) {
+- g_warning (_("Error %s"), err->message);
+- g_error_free (err);
+- return NULL;
+- }
+-
+- return argv;
+-}
+diff --git a/backend/comics/comics-document.h b/backend/comics/comics-document.h
+index f6a4b440..4417a69f 100644
+--- a/backend/comics/comics-document.h
++++ b/backend/comics/comics-document.h
+@@ -16,9 +16,9 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-#ifndef __COMICS_DOCUMENT_H__
+-#define __COMICS_DOCUMENT_H__
++#pragma once
+
++#include "ev-macros.h"
+ #include "ev-document.h"
+
+ G_BEGIN_DECLS
+@@ -30,9 +30,8 @@ G_BEGIN_DECLS
+ typedef struct _ComicsDocument ComicsDocument;
+
+ GType comics_document_get_type (void) G_GNUC_CONST;
++GType register_atril_backend (GTypeModule *module);
+
+-G_MODULE_EXPORT GType register_atril_backend (GTypeModule *module);
+
+ G_END_DECLS
+
+-#endif /* __COMICS_DOCUMENT_H__ */
+diff --git a/backend/comics/ev-archive.c b/backend/comics/ev-archive.c
+new file mode 100644
+index 00000000..568e1621
+--- /dev/null
++++ b/backend/comics/ev-archive.c
+@@ -0,0 +1,323 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
++/*
++ * Copyright (C) 2017, Bastien Nocera <hadess@hadess.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#include "config.h"
++#include "ev-archive.h"
++
++#include <archive.h>
++#include <archive_entry.h>
++#include <gio/gio.h>
++
++#define BUFFER_SIZE (64 * 1024)
++
++struct _EvArchive {
++ GObject parent_instance;
++ EvArchiveType type;
++
++ /* libarchive */
++ struct archive *libar;
++ struct archive_entry *libar_entry;
++};
++
++G_DEFINE_TYPE(EvArchive, ev_archive, G_TYPE_OBJECT);
++
++static void
++ev_archive_finalize (GObject *object)
++{
++ EvArchive *archive = EV_ARCHIVE (object);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_clear_pointer (&archive->libar, archive_free);
++ break;
++ default:
++ break;
++ }
++
++ G_OBJECT_CLASS (ev_archive_parent_class)->finalize (object);
++}
++
++static void
++ev_archive_class_init (EvArchiveClass *klass)
++{
++ GObjectClass *object_class = (GObjectClass *) klass;
++
++ object_class->finalize = ev_archive_finalize;
++}
++
++EvArchive *
++ev_archive_new (void)
++{
++ return g_object_new (EV_TYPE_ARCHIVE, NULL);
++}
++
++static void
++libarchive_set_archive_type (EvArchive *archive,
++ EvArchiveType archive_type)
++{
++ archive->type = archive_type;
++ archive->libar = archive_read_new ();
++
++ if (archive_type == EV_ARCHIVE_TYPE_ZIP)
++ archive_read_support_format_zip (archive->libar);
++ else if (archive_type == EV_ARCHIVE_TYPE_7Z)
++ archive_read_support_format_7zip (archive->libar);
++ else if (archive_type == EV_ARCHIVE_TYPE_TAR)
++ archive_read_support_format_tar (archive->libar);
++ else if (archive_type == EV_ARCHIVE_TYPE_RAR) {
++ archive_read_support_format_rar (archive->libar);
++ archive_read_support_format_rar5 (archive->libar);
++ } else
++ g_assert_not_reached ();
++}
++
++EvArchiveType
++ev_archive_get_archive_type (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), EV_ARCHIVE_TYPE_NONE);
++
++ return archive->type;
++}
++
++gboolean
++ev_archive_set_archive_type (EvArchive *archive,
++ EvArchiveType archive_type)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type == EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ switch (archive_type) {
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ libarchive_set_archive_type (archive, archive_type);
++ break;
++ default:
++ g_assert_not_reached ();
++ }
++
++ return TRUE;
++}
++
++gboolean
++ev_archive_open_filename (EvArchive *archive,
++ const char *path,
++ GError **error)
++{
++ int r;
++
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++ g_return_val_if_fail (path != NULL, FALSE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ r = archive_read_open_filename (archive->libar, path, BUFFER_SIZE);
++ if (r != ARCHIVE_OK) {
++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ "Error opening archive: %s", archive_error_string (archive->libar));
++ return FALSE;
++ }
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
++static gboolean
++libarchive_read_next_header (EvArchive *archive,
++ GError **error)
++{
++ while (1) {
++ int r;
++
++ r = archive_read_next_header (archive->libar, &archive->libar_entry);
++ if (r != ARCHIVE_OK) {
++ if (r != ARCHIVE_EOF)
++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ "Error reading archive: %s", archive_error_string (archive->libar));
++ return FALSE;
++ }
++
++ if (archive_entry_filetype (archive->libar_entry) != AE_IFREG) {
++ g_debug ("Skipping '%s' as it's not a regular file",
++ archive_entry_pathname (archive->libar_entry));
++ continue;
++ }
++
++ g_debug ("At header for file '%s'", archive_entry_pathname (archive->libar_entry));
++
++ break;
++ }
++
++ return TRUE;
++}
++
++gboolean
++ev_archive_read_next_header (EvArchive *archive,
++ GError **error)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ return libarchive_read_next_header (archive, error);
++ }
++
++ return FALSE;
++}
++
++gboolean
++ev_archive_at_entry (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ return (archive->libar_entry != NULL);
++}
++
++const char *
++ev_archive_get_entry_pathname (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), NULL);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, NULL);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, NULL);
++ return archive_entry_pathname (archive->libar_entry);
++ }
++
++ return NULL;
++}
++
++gint64
++ev_archive_get_entry_size (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), -1);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, -1);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, -1);
++ return archive_entry_size (archive->libar_entry);
++ }
++
++ return -1;
++}
++
++gboolean
++ev_archive_get_entry_is_encrypted (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, -1);
++ return archive_entry_is_encrypted (archive->libar_entry);
++ }
++
++ return FALSE;
++}
++
++gssize
++ev_archive_read_data (EvArchive *archive,
++ void *buf,
++ gsize count,
++ GError **error)
++{
++ gssize r = -1;
++
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), -1);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, -1);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, -1);
++ r = archive_read_data (archive->libar, buf, count);
++ if (r < 0) {
++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ "Failed to decompress data: %s", archive_error_string (archive->libar));
++ }
++ break;
++ }
++
++ return r;
++}
++
++void
++ev_archive_reset (EvArchive *archive)
++{
++ g_return_if_fail (EV_IS_ARCHIVE (archive));
++ g_return_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_clear_pointer (&archive->libar, archive_free);
++ libarchive_set_archive_type (archive, archive->type);
++ archive->libar_entry = NULL;
++ break;
++ default:
++ g_assert_not_reached ();
++ }
++}
++
++static void
++ev_archive_init (EvArchive *archive)
++{
++}
+diff --git a/backend/comics/ev-archive.h b/backend/comics/ev-archive.h
+new file mode 100644
+index 00000000..b4e1399c
+--- /dev/null
++++ b/backend/comics/ev-archive.h
+@@ -0,0 +1,56 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
++/*
++ * Copyright (C) 2017, Bastien Nocera <hadess@hadess.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#pragma once
++
++#include <glib-object.h>
++
++G_BEGIN_DECLS
++
++#define EV_TYPE_ARCHIVE ev_archive_get_type ()
++G_DECLARE_FINAL_TYPE (EvArchive, ev_archive, EV, ARCHIVE, GObject)
++
++typedef enum {
++ EV_ARCHIVE_TYPE_NONE = 0,
++ EV_ARCHIVE_TYPE_RAR,
++ EV_ARCHIVE_TYPE_ZIP,
++ EV_ARCHIVE_TYPE_7Z,
++ EV_ARCHIVE_TYPE_TAR
++} EvArchiveType;
++
++EvArchive *ev_archive_new (void);
++gboolean ev_archive_set_archive_type (EvArchive *archive,
++ EvArchiveType archive_type);
++EvArchiveType ev_archive_get_archive_type (EvArchive *archive);
++gboolean ev_archive_open_filename (EvArchive *archive,
++ const char *path,
++ GError **error);
++gboolean ev_archive_read_next_header (EvArchive *archive,
++ GError **error);
++gboolean ev_archive_at_entry (EvArchive *archive);
++const char *ev_archive_get_entry_pathname (EvArchive *archive);
++gint64 ev_archive_get_entry_size (EvArchive *archive);
++gboolean ev_archive_get_entry_is_encrypted (EvArchive *archive);
++gssize ev_archive_read_data (EvArchive *archive,
++ void *buf,
++ gsize count,
++ GError **error);
++void ev_archive_reset (EvArchive *archive);
++
++G_END_DECLS
+diff --git a/configure.ac b/configure.ac
+index e25de054..d5830716 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -580,8 +580,11 @@ AC_ARG_ENABLE(comics,
+ [enable_comics=$enableval],
+ [enable_comics=yes])
+
++COMICS_DEPS="libarchive"
+ if test "x$enable_comics" = "xyes"; then
+ AC_DEFINE([ENABLE_COMICS], [1], [Enable support for comics.])
++ PKG_CHECK_MODULES([COMICS], [$COMICS_DEPS])
++ AC_SUBST(COMICS_LIBS)
+ fi
+ AM_CONDITIONAL(ENABLE_COMICS, test x$enable_comics = xyes)
+
+diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h
+index 67f53abb..8f54e6b5 100644
+--- a/libdocument/ev-document.h
++++ b/libdocument/ev-document.h
+@@ -59,6 +59,7 @@ typedef struct _EvDocumentPrivate EvDocumentPrivate;
+ typedef enum
+ {
+ EV_DOCUMENT_ERROR_INVALID,
++ EV_DOCUMENT_ERROR_UNSUPPORTED_CONTENT,
+ EV_DOCUMENT_ERROR_ENCRYPTED
+ } EvDocumentError;
+
+--
+2.39.2
+
diff -Nru atril-1.26.0/debian/patches/1002-avoid-crash-on-certain-epub-files.patch atril-1.26.0/debian/patches/1002-avoid-crash-on-certain-epub-files.patch
--- atril-1.26.0/debian/patches/1002-avoid-crash-on-certain-epub-files.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/1002-avoid-crash-on-certain-epub-files.patch 2024-01-23 10:05:56.000000000 +0100
@@ -0,0 +1,27 @@
+Description: Avoid crash on certain epub files
+
+Author: Bernhard Übelacker <bernhardu@mailbox.org>
+Bug-Debian: https://bugs.debian.org/972715
+Forwarded: no
+Last-Update: 2020-11-01
+
+--- a/backend/epub/epub-document.c
++++ b/backend/epub/epub-document.c
+@@ -1279,7 +1279,7 @@
+ xml_parse_children_of_node(navLabel,(xmlChar*)"text",NULL,NULL);
+ linknode *newnode = g_new0(linknode,1);
+ newnode->linktext = NULL;
+- while (newnode->linktext == NULL) {
++ while (xmlretval && newnode->linktext == NULL) {
+ newnode->linktext = (gchar*)xml_get_data_from_node(xmlretval,XML_KEYWORD,NULL);
+ xmlretval = xmlretval->next;
+ }
+@@ -1597,7 +1597,7 @@
+ contentListNode *pagedata;
+
+ guint flag=0;
+- while (!flag) {
++ while (listiter && !flag) {
+ pagedata = listiter->data;
+ if (link_present_on_page(Link->pagelink, pagedata->value)) {
+ flag=1;
diff -Nru atril-1.26.0/debian/patches/series atril-1.26.0/debian/patches/series
--- atril-1.26.0/debian/patches/series 2022-10-27 10:40:29.000000000 +0200
+++ atril-1.26.0/debian/patches/series 2024-01-23 10:06:53.000000000 +0100
@@ -1 +1,7 @@
1001-webkit2gtk4.1.patch
+1002-avoid-crash-on-certain-epub-files.patch
+0001-Accessibility-add-button-description.patch
+0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch
+0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch
+0005-Use-a-blank-line-at-most.patch
+0006-comics-Use-libarchive-to-unpack-documents.patch
diff -Nru atril-1.26.0/debian/changelog atril-1.26.0/debian/changelog
--- atril-1.26.0/debian/changelog 2024-01-06 07:18:28.000000000 +0100
+++ atril-1.26.0/debian/changelog 2024-01-23 10:08:40.000000000 +0100
@@ -1,3 +1,12 @@
+atril (1.26.0-2+deb12u2) bookworm; urgency=medium
+
+ * debian/patches:
+ + Add 0005-Use-a-blank-line-at-most.patch and 0006-comics-Use-libarchive-
+ to-unpack-documents.patch. Use libarchive instead of external command for
+ extracing documents (CVE-2023-51698, closes: #1060751).
+
+ -- Mike Gabriel <sunweaver@debian.org> Tue, 23 Jan 2024 10:08:40 +0100
+
atril (1.26.0-2+deb12u1) bookworm; urgency=medium
* debian/patches:
diff -Nru atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch
--- atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/0005-Use-a-blank-line-at-most.patch 2024-01-23 10:08:40.000000000 +0100
@@ -0,0 +1,1866 @@
+From 658fab1f008bff7e1ec147d95baa04bc44c2fbcd Mon Sep 17 00:00:00 2001
+From: rbuj <robert.buj@gmail.com>
+Date: Wed, 27 Oct 2021 17:30:36 +0200
+Subject: [PATCH 1/2] Use a blank line at most
+
+Signed-off-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+---
+ backend/comics/comics-document.c | 3 --
+ backend/djvu/djvu-document.c | 3 --
+ backend/djvu/djvu-links.c | 2 -
+ backend/djvu/djvu-text-page.c | 3 --
+ backend/djvu/djvu-text-page.h | 1 -
+ backend/dvi/dvi-document.c | 2 -
+ backend/dvi/fonts.c | 1 -
+ backend/dvi/mdvi-lib/afmparse.c | 18 --------
+ backend/dvi/mdvi-lib/bitmap.c | 2 -
+ backend/dvi/mdvi-lib/color.c | 1 -
+ backend/dvi/mdvi-lib/color.h | 1 -
+ backend/dvi/mdvi-lib/fontmap.c | 1 -
+ backend/dvi/mdvi-lib/hash.c | 1 -
+ backend/dvi/mdvi-lib/hash.h | 2 -
+ backend/dvi/mdvi-lib/mdvi.h | 2 -
+ backend/dvi/mdvi-lib/paper.h | 1 -
+ backend/dvi/mdvi-lib/special.c | 1 -
+ backend/dvi/mdvi-lib/tfmfile.c | 1 -
+ backend/epub/epub-document.c | 6 ---
+ backend/epub/minizip/ioapi.c | 6 ---
+ backend/epub/minizip/ioapi.h | 7 ---
+ backend/epub/minizip/unzip.c | 45 -------------------
+ backend/epub/minizip/unzip.h | 11 -----
+ backend/pdf/ev-poppler.h | 1 -
+ backend/pixbuf/pixbuf-document.c | 1 -
+ backend/tiff/tiff-document.c | 1 -
+ backend/tiff/tiff2ps.c | 2 -
+ backend/xps/xps-document.c | 2 -
+ .../toolbar-editor/egg-editable-toolbar.c | 2 -
+ .../toolbar-editor/egg-toolbar-editor.c | 1 -
+ .../toolbar-editor/egg-toolbar-editor.h | 2 -
+ .../toolbar-editor/egg-toolbars-model.c | 2 -
+ cut-n-paste/zoom-control/ephy-zoom.c | 1 -
+ libdocument/ev-document-attachments.c | 1 -
+ libdocument/ev-document-factory.c | 1 -
+ libdocument/ev-document-fonts.h | 1 -
+ libdocument/ev-document-misc.c | 1 -
+ libdocument/ev-document-security.h | 1 -
+ libdocument/ev-document-text.c | 1 -
+ libdocument/ev-document.c | 1 -
+ libdocument/ev-file-helpers.h | 1 -
+ libdocument/ev-form-field.h | 1 -
+ libdocument/ev-image.h | 1 -
+ libdocument/ev-render-context.h | 2 -
+ libdocument/ev-transition-effect.h | 2 -
+ libmisc/ev-page-action-widget.c | 3 --
+ libview/ev-page-accessible.c | 2 -
+ libview/ev-pixbuf-cache.c | 6 ---
+ libview/ev-pixbuf-cache.h | 2 -
+ libview/ev-timeline.c | 2 -
+ libview/ev-timeline.h | 2 -
+ libview/ev-transition-animation.c | 2 -
+ libview/ev-transition-animation.h | 2 -
+ libview/ev-view-presentation.c | 1 -
+ libview/ev-view.c | 2 -
+ libview/ev-web-view.c | 2 -
+ libview/ev-web-view.h | 1 -
+ previewer/ev-previewer-window.c | 1 -
+ shell/eggfindbar.c | 1 -
+ shell/eggfindbar.h | 1 -
+ shell/ev-application.c | 2 -
+ shell/ev-bookmarks.h | 2 -
+ shell/ev-daemon.c | 1 -
+ shell/ev-history.c | 1 -
+ shell/ev-loading-message.c | 1 -
+ shell/ev-media-player-keys.h | 1 -
+ shell/ev-navigation-action.c | 1 -
+ shell/ev-open-recent-action.c | 1 -
+ shell/ev-password-view.c | 2 -
+ shell/ev-sidebar-attachments.c | 1 -
+ shell/ev-sidebar-bookmarks.c | 1 -
+ shell/ev-sidebar-layers.c | 1 -
+ shell/ev-sidebar-links.c | 3 --
+ shell/ev-sidebar-links.h | 1 -
+ shell/ev-sidebar-page.c | 1 -
+ shell/ev-sidebar-page.h | 1 -
+ shell/ev-sidebar-thumbnails.c | 1 -
+ shell/ev-sidebar-thumbnails.h | 1 -
+ shell/ev-sidebar.c | 1 -
+ shell/ev-sidebar.h | 1 -
+ shell/ev-window.c | 9 ----
+ shell/ev-window.h | 2 -
+ shell/main.c | 4 --
+ 83 files changed, 220 deletions(-)
+
+--- a/backend/comics/comics-document.c
++++ b/backend/comics/comics-document.c
+@@ -126,7 +126,6 @@
+ static char** extract_argv (EvDocument *document,
+ gint page);
+
+-
+ EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,
+ {
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+@@ -186,7 +185,6 @@
+ return g_string_free (dest, FALSE);
+ }
+
+-
+ /* This function manages the command for decompressing a comic book */
+ static gboolean
+ comics_decompress_temp_dir (const gchar *command_decompress_tmp,
+@@ -627,7 +625,6 @@
+ return TRUE;
+ }
+
+-
+ static gboolean
+ comics_document_save (EvDocument *document,
+ const char *uri,
+--- a/backend/djvu/djvu-document.c
++++ b/backend/djvu/djvu-document.c
+@@ -66,7 +66,6 @@
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION, djvu_selection_iface_init);
+ });
+
+-
+ #define EV_DJVU_ERROR ev_djvu_error_quark ()
+
+ static GQuark
+@@ -256,7 +255,6 @@
+ return TRUE;
+ }
+
+-
+ static gboolean
+ djvu_document_save (EvDocument *document,
+ const char *uri,
+@@ -676,7 +674,6 @@
+ r->y2 = height - tmp * SCALE_FACTOR;
+ }
+
+-
+ return matches;
+ }
+
+--- a/backend/djvu/djvu-links.c
++++ b/backend/djvu/djvu-links.c
+@@ -181,7 +181,6 @@
+ if (!string_from_miniexp (miniexp_car (iter), &title)) goto unknown_entry;
+ if (!string_from_miniexp (miniexp_cadr (iter), &link_dest)) goto unknown_entry;
+
+-
+ if (!g_utf8_validate (title, -1, NULL)) {
+ utf8_title = str_to_utf8 (title);
+ title_markup = g_markup_escape_text (utf8_title, -1);
+@@ -342,7 +341,6 @@
+ return NULL;
+ }
+
+-
+ gboolean
+ djvu_links_has_document_links (EvDocumentLinks *document_links)
+ {
+--- a/backend/djvu/djvu-text-page.c
++++ b/backend/djvu/djvu-text-page.c
+@@ -23,7 +23,6 @@
+ #include <libdjvu/miniexp.h>
+ #include "djvu-text-page.h"
+
+-
+ /**
+ * djvu_text_page_selection_process:
+ * @page: #DjvuTextPage instance
+@@ -117,7 +116,6 @@
+ }
+ }
+
+-
+ static void
+ djvu_text_page_limits (DjvuTextPage *page,
+ miniexp_t p,
+@@ -404,7 +402,6 @@
+ g_free (search_text);
+ }
+
+-
+ /**
+ * djvu_text_page_prepare_search:
+ * @page: #DjvuTextPage instance
+--- a/backend/djvu/djvu-text-page.h
++++ b/backend/djvu/djvu-text-page.h
+@@ -25,7 +25,6 @@
+ #include <glib.h>
+ #include <libdjvu/miniexp.h>
+
+-
+ typedef struct _DjvuTextPage DjvuTextPage;
+ typedef struct _DjvuTextLink DjvuTextLink;
+
+--- a/backend/dvi/dvi-document.c
++++ b/backend/dvi/dvi-document.c
+@@ -110,7 +110,6 @@
+
+ mdvi_cairo_device_init (&dvi_document->context->device);
+
+-
+ dvi_document->base_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv
+ + 2 * unit2pix(dvi_document->params->dpi, MDVI_HMARGIN) / dvi_document->params->hshrink;
+
+@@ -123,7 +122,6 @@
+ return TRUE;
+ }
+
+-
+ static gboolean
+ dvi_document_save (EvDocument *document,
+ const char *uri,
+--- a/backend/dvi/fonts.c
++++ b/backend/dvi/fonts.c
+@@ -54,4 +54,3 @@
+ return;
+ }
+
+-
+--- a/backend/dvi/mdvi-lib/afmparse.c
++++ b/backend/dvi/mdvi-lib/afmparse.c
+@@ -81,13 +81,10 @@
+
+ #define MATCH(A,B) (strncmp((A),(B), MAX_NAME) == 0)
+
+-
+-
+ /*************************** GLOBALS ***********************/
+
+ static char *ident = NULL; /* storage buffer for keywords */
+
+-
+ /* "shorts" for fast case statement
+ * The values of each of these enumerated items correspond to an entry in the
+ * table of strings defined below. Therefore, if you add a new string as
+@@ -175,7 +172,6 @@
+
+ } /* token */
+
+-
+ /*************************** linetoken *************************/
+
+ /* "linetoken" will get read all tokens until the EOL character from
+@@ -203,7 +199,6 @@
+
+ } /* linetoken */
+
+-
+ /*************************** recognize *************************/
+
+ /* This function tries to match a string to a known list of
+@@ -234,7 +229,6 @@
+
+ } /* recognize */
+
+-
+ /************************* parseGlobals *****************************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -401,8 +395,6 @@
+
+ } /* parseGlobals */
+
+-
+-
+ #if 0 /* this function does not seem to be used anywhere */
+ /************************* initializeArray ************************/
+
+@@ -584,7 +576,6 @@
+
+ } /* parseCharWidths */
+
+-
+ /************************* parseCharMetrics ************************/
+
+ /* This function is called by parseFile if the caller of parseFile
+@@ -694,8 +685,6 @@
+
+ } /* parseCharMetrics */
+
+-
+-
+ /************************* parseTrackKernData ***********************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -797,7 +786,6 @@
+
+ } /* parseTrackKernData */
+
+-
+ /************************* parsePairKernData ************************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -918,7 +906,6 @@
+
+ } /* parsePairKernData */
+
+-
+ /************************* parseCompCharData **************************/
+
+ /* This function is called by "parseFile". It will parse the AFM File
+@@ -1043,12 +1030,8 @@
+
+ } /* parseCompCharData */
+
+-
+-
+-
+ /*************************** 'PUBLIC' FUNCTION ********************/
+
+-
+ /*************************** parseFile *****************************/
+
+ /* parseFile is the only 'public' procedure available. It is called
+@@ -1078,7 +1061,6 @@
+
+ register char *keyword; /* used to store a token */
+
+-
+ /* storage data for the global variable ident */
+ ident = (char *) calloc(MAX_NAME, sizeof(char));
+ if (ident == NULL) {error = storageProblem; return(error);}
+--- a/backend/dvi/mdvi-lib/bitmap.c
++++ b/backend/dvi/mdvi-lib/bitmap.c
+@@ -117,7 +117,6 @@
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+ };
+
+-
+ /*
+ * next we have three bitmap functions to convert bitmaps in LSB bit order
+ * with 8, 16 and 32 bits per unit, to our internal format. The differences
+@@ -192,7 +191,6 @@
+ return bm;
+ }
+
+-
+ BITMAP *bitmap_copy(BITMAP *bm)
+ {
+ BITMAP *nb = bitmap_alloc(bm->width, bm->height);
+--- a/backend/dvi/mdvi-lib/color.c
++++ b/backend/dvi/mdvi-lib/color.c
+@@ -79,7 +79,6 @@
+
+ #define GAMMA_DIFF 0.005
+
+-
+ /* create a color table */
+ Ulong *get_color_table(DviDevice *dev,
+ int nlevels, Ulong fg, Ulong bg, double gamma, int density)
+--- a/backend/dvi/mdvi-lib/color.h
++++ b/backend/dvi/mdvi-lib/color.h
+@@ -16,7 +16,6 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-
+ #ifndef _COLOR_H_
+ #define _COLOR_H_
+
+--- a/backend/dvi/mdvi-lib/fontmap.c
++++ b/backend/dvi/mdvi-lib/fontmap.c
+@@ -834,7 +834,6 @@
+ return 0;
+ }
+
+-
+ void mdvi_flush_encodings(void)
+ {
+ DviEncoding *enc;
+--- a/backend/dvi/mdvi-lib/hash.c
++++ b/backend/dvi/mdvi-lib/hash.c
+@@ -21,7 +21,6 @@
+
+ /* simple hash tables for MDVI */
+
+-
+ struct _DviHashBucket {
+ DviHashBucket *next;
+ DviHashKey key;
+--- a/backend/dvi/mdvi-lib/hash.h
++++ b/backend/dvi/mdvi-lib/hash.h
+@@ -3,7 +3,6 @@
+
+ /* Hash tables */
+
+-
+ typedef struct _DviHashBucket DviHashBucket;
+ typedef struct _DviHashTable DviHashTable;
+
+@@ -18,7 +17,6 @@
+ typedef int (*DviHashComp) __PROTO((DviHashKey key1, DviHashKey key2));
+ typedef void (*DviHashFree) __PROTO((DviHashKey key, void *data));
+
+-
+ struct _DviHashTable {
+ DviHashBucket **buckets;
+ int nbucks;
+--- a/backend/dvi/mdvi-lib/mdvi.h
++++ b/backend/dvi/mdvi-lib/mdvi.h
+@@ -414,7 +414,6 @@
+ int step; /* step */
+ };
+
+-
+ typedef void (*DviSpecialHandler)
+ __PROTO((DviContext *dvi, const char *prefix, const char *arg));
+
+@@ -600,7 +599,6 @@
+
+ extern int mdvi_encode_font __PROTO((DviParams *, DviFont *));
+
+-
+ /* font lookup functions */
+ extern int mdvi_register_font_type __PROTO((DviFontInfo *, int));
+ extern char **mdvi_list_font_class __PROTO((int));
+--- a/backend/dvi/mdvi-lib/paper.h
++++ b/backend/dvi/mdvi-lib/paper.h
+@@ -24,7 +24,6 @@
+ const char *height;
+ };
+
+-
+ extern int mdvi_get_paper_size __PROTO((const char *, DviPaper *));
+ extern DviPaperSpec* mdvi_get_paper_specs __PROTO((DviPaperClass));
+ extern void mdvi_free_paper_specs __PROTO((DviPaperSpec *));
+--- a/backend/dvi/mdvi-lib/special.c
++++ b/backend/dvi/mdvi-lib/special.c
+@@ -212,7 +212,6 @@
+ {
+ DviSpecial *sp, *list;
+
+-
+ for(list = (DviSpecial *)specials.head; (sp = list); ) {
+ list = sp->next;
+ if(sp->prefix) mdvi_free(sp->prefix);
+--- a/backend/dvi/mdvi-lib/tfmfile.c
++++ b/backend/dvi/mdvi-lib/tfmfile.c
+@@ -258,7 +258,6 @@
+ /* allocate characters */
+ info->chars = xnalloc(TFMChar, size);
+
+-
+ #ifdef WORD_LITTLE_ENDIAN
+ /* byte-swap the three arrays at once (they are consecutive in memory) */
+ swap_array((Uint32 *)widths, nw + nh + nd);
+--- a/backend/epub/epub-document.c
++++ b/backend/epub/epub-document.c
+@@ -224,7 +224,6 @@
+ return TRUE;
+ }
+
+-
+ typedef struct _LinksCBStruct {
+ GtkTreeModel *model;
+ GtkTreeIter *parent;
+@@ -413,7 +412,6 @@
+ return (g_remove (path_name));
+ }
+
+-
+ static gboolean
+ check_mime_type (const gchar* uri,
+ GError** error);
+@@ -1562,7 +1560,6 @@
+
+ gchar *csspath = g_strdup_printf("%s/atrilnightstyle.css",epub_document->documentdir);
+
+-
+ GFile *styles = g_file_new_for_path (csspath);
+ GOutputStream *outstream = (GOutputStream*)g_file_create(styles,G_FILE_CREATE_PRIVATE,NULL,NULL);
+ if ( g_output_stream_write((GOutputStream*)outstream,style,strlen(style),NULL,NULL) == -1 )
+@@ -1636,7 +1633,6 @@
+ g_list_foreach(index,(GFunc)page_set_function,contentList);
+ }
+
+-
+ static void
+ add_mathjax_script_node_to_file(gchar *filename, gchar *data)
+ {
+@@ -1784,7 +1780,6 @@
+ epub_document->docTitle = NULL;
+ }
+
+-
+ static void
+ epub_document_finalize (GObject *object)
+ {
+@@ -1826,7 +1821,6 @@
+ G_OBJECT_CLASS (epub_document_parent_class)->finalize (object);
+ }
+
+-
+ static void
+ epub_document_class_init (EpubDocumentClass *klass)
+ {
+--- a/backend/epub/minizip/ioapi.c
++++ b/backend/epub/minizip/ioapi.c
+@@ -25,7 +25,6 @@
+ #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+ #endif
+
+-
+ #include "ioapi.h"
+
+ voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
+@@ -82,8 +81,6 @@
+ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+ }
+
+-
+-
+ static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+ static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+ static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
+@@ -128,7 +125,6 @@
+ return file;
+ }
+
+-
+ static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
+ {
+ uLong ret;
+@@ -150,7 +146,6 @@
+ return ret;
+ }
+
+-
+ static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+ {
+ ZPOS64_T ret;
+@@ -206,7 +201,6 @@
+ return ret;
+ }
+
+-
+ static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
+ {
+ int ret;
+--- a/backend/epub/minizip/ioapi.h
++++ b/backend/epub/minizip/ioapi.h
+@@ -110,7 +110,6 @@
+ extern "C" {
+ #endif
+
+-
+ #define ZLIB_FILEFUNC_SEEK_CUR (1)
+ #define ZLIB_FILEFUNC_SEEK_END (2)
+ #define ZLIB_FILEFUNC_SEEK_SET (0)
+@@ -122,7 +121,6 @@
+ #define ZLIB_FILEFUNC_MODE_EXISTING (4)
+ #define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+-
+ #ifndef ZCALLBACK
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+ #define ZCALLBACK CALLBACK
+@@ -131,9 +129,6 @@
+ #endif
+ #endif
+
+-
+-
+-
+ typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+ typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+ typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+@@ -143,7 +138,6 @@
+ typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+ typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+
+-
+ /* here is the "old" 32 bits structure structure */
+ typedef struct zlib_filefunc_def_s
+ {
+@@ -185,7 +179,6 @@
+ seek_file_func zseek32_file;
+ } zlib_filefunc64_32_def;
+
+-
+ #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+ #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+ //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+--- a/backend/epub/minizip/unzip.c
++++ b/backend/epub/minizip/unzip.c
+@@ -12,7 +12,6 @@
+
+ For more info read MiniZip_info.txt
+
+-
+ ------------------------------------------------------------------------------------
+ Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+ compatibility with older software. The following is from the original crypt.c.
+@@ -48,7 +47,6 @@
+
+ Copyright (C) 2007-2008 Even Rouault
+
+-
+ Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
+ Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
+ should only read the compressed/uncompressed size from the Zip64 format if
+@@ -63,7 +61,6 @@
+
+ */
+
+-
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -86,20 +83,17 @@
+ # include <errno.h>
+ #endif
+
+-
+ #ifndef local
+ # define local static
+ #endif
+ /* compile with -Dlocal if your debugger can't find static symbols */
+
+-
+ #ifndef CASESENSITIVITYDEFAULT_NO
+ # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+ # define CASESENSITIVITYDEFAULT_NO
+ # endif
+ #endif
+
+-
+ #ifndef UNZ_BUFSIZE
+ #define UNZ_BUFSIZE (16384)
+ #endif
+@@ -118,14 +112,12 @@
+ #define SIZECENTRALDIRITEM (0x2e)
+ #define SIZEZIPLOCALHEADER (0x1e)
+
+-
+ /* unz_file_info_interntal contain internal info about a file in zipfile*/
+ typedef struct unz_file_info64_internal_s
+ {
+ ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
+ } unz_file_info64_internal;
+
+-
+ /* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+ typedef struct
+@@ -156,7 +148,6 @@
+ int raw;
+ } file_in_zip64_read_info_s;
+
+-
+ /* unz64_s contain internal information about the zipfile
+ */
+ typedef struct
+@@ -189,7 +180,6 @@
+ # endif
+ } unz64_s;
+
+-
+ #ifndef NOUNCRYPT
+ #include "crypt.h"
+ #endif
+@@ -200,7 +190,6 @@
+ IN assertion: the stream s has been successfully opened for reading.
+ */
+
+-
+ local int unz64local_getByte OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+@@ -224,7 +213,6 @@
+ }
+ }
+
+-
+ /* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+ */
+@@ -295,7 +283,6 @@
+ voidpf filestream,
+ ZPOS64_T *pX));
+
+-
+ local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX)
+@@ -364,7 +351,6 @@
+ }
+ }
+
+-
+ #ifdef CASESENSITIVITYDEFAULT_NO
+ #define CASESENSITIVITYDEFAULTVALUE 2
+ #else
+@@ -418,7 +404,6 @@
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+-
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+@@ -463,7 +448,6 @@
+ return uPosFound;
+ }
+
+-
+ /*
+ Locate the Central directory 64 of a zipfile (at the end, just before
+ the global comment)
+@@ -486,7 +470,6 @@
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+-
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+@@ -605,8 +588,6 @@
+ us.z_filefunc = *pzlib_filefunc64_32_def;
+ us.is64bitOpenFunction = is64bitOpenFunction;
+
+-
+-
+ us.filestream = ZOPEN64(us.z_filefunc,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+@@ -745,7 +726,6 @@
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+-
+ s=(unz64_s*)ALLOC(sizeof(unz64_s));
+ if( s != NULL)
+ {
+@@ -755,7 +735,6 @@
+ return (unzFile)s;
+ }
+
+-
+ extern unzFile ZEXPORT unzOpen2 (const char *path,
+ zlib_filefunc_def* pzlib_filefunc32_def)
+ {
+@@ -814,7 +793,6 @@
+ return UNZ_OK;
+ }
+
+-
+ /*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+@@ -897,7 +875,6 @@
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+-
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+@@ -1002,7 +979,6 @@
+ else
+ lSeek += file_info.size_file_extra;
+
+-
+ if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
+ {
+ uLong acc = 0;
+@@ -1096,7 +1072,6 @@
+ else
+ lSeek+=file_info.size_file_comment;
+
+-
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+@@ -1106,8 +1081,6 @@
+ return err;
+ }
+
+-
+-
+ /*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+@@ -1156,7 +1129,6 @@
+
+ pfile_info->tmu_date = file_info64.tmu_date,
+
+-
+ pfile_info->compressed_size = (uLong)file_info64.compressed_size;
+ pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
+
+@@ -1212,7 +1184,6 @@
+ return err;
+ }
+
+-
+ /*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+@@ -1234,7 +1205,6 @@
+ ZPOS64_T num_fileSaved;
+ ZPOS64_T pos_in_central_dirSaved;
+
+-
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+
+@@ -1278,7 +1248,6 @@
+ return err;
+ }
+
+-
+ /*
+ ///////////////////////////////////////////
+ // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+@@ -1391,7 +1360,6 @@
+ s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+-
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+@@ -1594,7 +1562,6 @@
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size ;
+
+-
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+@@ -1626,7 +1593,6 @@
+ }
+ # endif
+
+-
+ return UNZ_OK;
+ }
+
+@@ -1687,7 +1653,6 @@
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+-
+ if (pfile_in_zip_read_info->read_buffer == NULL)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len==0)
+@@ -1731,7 +1696,6 @@
+ uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+
+-
+ # ifndef NOUNCRYPT
+ if(s->encrypted)
+ {
+@@ -1743,7 +1707,6 @@
+ }
+ # endif
+
+-
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+@@ -1874,7 +1837,6 @@
+ return err;
+ }
+
+-
+ /*
+ Give the current position in uncompressed data
+ */
+@@ -1909,7 +1871,6 @@
+ return pfile_in_zip_read_info->total_out_64;
+ }
+
+-
+ /*
+ return 1 if the end of file was reached, 0 elsewhere
+ */
+@@ -1931,8 +1892,6 @@
+ return 0;
+ }
+
+-
+-
+ /*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+@@ -2007,7 +1966,6 @@
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+-
+ if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+ (!pfile_in_zip_read_info->raw))
+ {
+@@ -2015,7 +1973,6 @@
+ err=UNZ_CRCERROR;
+ }
+
+-
+ TRYFREE(pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
+@@ -2025,7 +1982,6 @@
+ BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
+ #endif
+
+-
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE(pfile_in_zip_read_info);
+
+@@ -2034,7 +1990,6 @@
+ return err;
+ }
+
+-
+ /*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+--- a/backend/epub/minizip/unzip.h
++++ b/backend/epub/minizip/unzip.h
+@@ -70,7 +70,6 @@
+ typedef voidp unzFile;
+ #endif
+
+-
+ #define UNZ_OK (0)
+ #define UNZ_END_OF_LIST_OF_FILE (-100)
+ #define UNZ_ERRNO (Z_ERRNO)
+@@ -162,7 +161,6 @@
+ (like 1 on Unix, 2 on Windows)
+ */
+
+-
+ extern unzFile ZEXPORT unzOpen OF((const char *path));
+ extern unzFile ZEXPORT unzOpen64 OF((const void *path));
+ /*
+@@ -180,7 +178,6 @@
+ does not describe the reality
+ */
+
+-
+ extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def));
+ /*
+@@ -212,7 +209,6 @@
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+-
+ extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+ char *szComment,
+ uLong uSizeBuf));
+@@ -222,7 +218,6 @@
+ return the number of byte copied or an error code <0
+ */
+
+-
+ /***************************************************************************/
+ /* Unzip package allow you browse the directory of the zipfile */
+
+@@ -251,7 +246,6 @@
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+ */
+
+-
+ /* ****************************************** */
+ /* Ryan supplied functions */
+ /* unz_file_info contain information about a file in the zipfile */
+@@ -315,14 +309,12 @@
+ (commentBufferSize is the size of the buffer)
+ */
+
+-
+ /** Addition for GDAL : START */
+
+ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
+
+ /** Addition for GDAL : END */
+
+-
+ /***************************************************************************/
+ /* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+@@ -369,7 +361,6 @@
+ but you CANNOT set method parameter as NULL
+ */
+
+-
+ extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+ /*
+ Close the file in zip opened with unzOpenCurrentFile
+@@ -428,8 +419,6 @@
+ extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
+ extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+-
+-
+ #ifdef __cplusplus
+ }
+ #endif
+--- a/backend/pdf/ev-poppler.h
++++ b/backend/pdf/ev-poppler.h
+@@ -34,7 +34,6 @@
+
+ G_MODULE_EXPORT GType register_atril_backend (GTypeModule *module);
+
+-
+ G_END_DECLS
+
+ #endif /* __PDF_DOCUMENT_H__ */
+--- a/backend/pixbuf/pixbuf-document.c
++++ b/backend/pixbuf/pixbuf-document.c
+@@ -201,7 +201,6 @@
+ iface->get_dimensions = pixbuf_document_thumbnails_get_dimensions;
+ }
+
+-
+ static void
+ pixbuf_document_init (PixbufDocument *pixbuf_document)
+ {
+--- a/backend/tiff/tiff-document.c
++++ b/backend/tiff/tiff-document.c
+@@ -361,7 +361,6 @@
+ if (width <= 0 || height <= 0)
+ return NULL;
+
+-
+ if (width >= INT_MAX / 4)
+ /* overflow */
+ return NULL;
+--- a/backend/tiff/tiff2ps.c
++++ b/backend/tiff/tiff2ps.c
+@@ -449,7 +449,6 @@
+ return splitpage;
+ }
+
+-
+ void
+ tiff2ps_process_page(TIFF2PSContext* ctx, TIFF* tif, double pw, double ph,
+ double lm, double bm, gboolean cnt)
+@@ -592,7 +591,6 @@
+ }
+ }
+
+-
+ static char DuplexPreamble[] = "\
+ %%BeginFeature: *Duplex True\n\
+ systemdict begin\n\
+--- a/backend/xps/xps-document.c
++++ b/backend/xps/xps-document.c
+@@ -176,7 +176,6 @@
+ EV_DOCUMENT_INFO_N_PAGES |
+ EV_DOCUMENT_INFO_PAPER_SIZE;
+
+-
+ if (gxps_document_get_n_pages (xps->doc) > 0) {
+ ev_document_get_page_size (document, 0,
+ &(info->paper_width),
+@@ -483,7 +482,6 @@
+ iface->find_link_page = xps_document_links_find_link_page;
+ }
+
+-
+ /* EvDocumentPrint */
+ static void
+ xps_document_print_print_page (EvDocumentPrint *document,
+--- a/cut-n-paste/toolbar-editor/egg-editable-toolbar.c
++++ b/cut-n-paste/toolbar-editor/egg-editable-toolbar.c
+@@ -541,7 +541,6 @@
+ }
+ }
+
+-
+ static void
+ configure_item_tooltip (GtkToolItem *item)
+ {
+@@ -557,7 +556,6 @@
+ }
+ }
+
+-
+ static void
+ connect_widget_signals (GtkWidget *proxy, EggEditableToolbar *etoolbar)
+ {
+--- a/cut-n-paste/toolbar-editor/egg-toolbar-editor.c
++++ b/cut-n-paste/toolbar-editor/egg-toolbar-editor.c
+@@ -36,7 +36,6 @@
+ {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0},
+ };
+
+-
+ static void egg_toolbar_editor_finalize (GObject *object);
+ static void update_editor_sheet (EggToolbarEditor *editor);
+
+--- a/cut-n-paste/toolbar-editor/egg-toolbar-editor.h
++++ b/cut-n-paste/toolbar-editor/egg-toolbar-editor.h
+@@ -34,7 +34,6 @@
+ #define EGG_IS_TOOLBAR_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TOOLBAR_EDITOR))
+ #define EGG_TOOLBAR_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TOOLBAR_EDITOR, EggToolbarEditorClass))
+
+-
+ typedef struct EggToolbarEditor EggToolbarEditor;
+ typedef struct EggToolbarEditorPrivate EggToolbarEditorPrivate;
+
+@@ -51,7 +50,6 @@
+ GtkBoxClass parent_class;
+ };
+
+-
+ GType egg_toolbar_editor_get_type (void);
+ GtkWidget *egg_toolbar_editor_new (GtkUIManager *manager,
+ EggToolbarsModel *model);
+--- a/cut-n-paste/toolbar-editor/egg-toolbars-model.c
++++ b/cut-n-paste/toolbar-editor/egg-toolbars-model.c
+@@ -213,7 +213,6 @@
+ EggToolbarsItem *idata2;
+ GNode *toolbar, *item;
+
+-
+ for(toolbar = g_node_first_child (model->priv->toolbars);
+ toolbar != NULL; toolbar = g_node_next_sibling (toolbar))
+ {
+@@ -330,7 +329,6 @@
+ 0, toolbar_position);
+ }
+
+-
+ char *
+ egg_toolbars_model_get_data (EggToolbarsModel *model,
+ GdkAtom type,
+--- a/cut-n-paste/zoom-control/ephy-zoom.c
++++ b/cut-n-paste/zoom-control/ephy-zoom.c
+@@ -54,7 +54,6 @@
+ return n_zoom_levels - 1;
+ }
+
+-
+ float
+ ephy_zoom_get_changed_zoom_level (float level, gint steps)
+ {
+--- a/libdocument/ev-document-attachments.c
++++ b/libdocument/ev-document-attachments.c
+@@ -52,4 +52,3 @@
+ return iface->get_attachments (document_attachments);
+ }
+
+-
+--- a/libdocument/ev-document-factory.c
++++ b/libdocument/ev-document-factory.c
+@@ -106,7 +106,6 @@
+ return EV_COMPRESSION_NONE;
+ }
+
+-
+ /*
+ * get_document_from_uri:
+ * @uri: the document URI
+--- a/libdocument/ev-document-fonts.h
++++ b/libdocument/ev-document-fonts.h
+@@ -37,7 +37,6 @@
+
+ G_BEGIN_DECLS
+
+-
+ #define EV_TYPE_DOCUMENT_FONTS (ev_document_fonts_get_type ())
+ #define EV_DOCUMENT_FONTS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT_FONTS, EvDocumentFonts))
+ #define EV_DOCUMENT_FONTS_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT_FONTS, EvDocumentFontsInterface))
+--- a/libdocument/ev-document-misc.c
++++ b/libdocument/ev-document-misc.c
+@@ -149,7 +149,6 @@
+ }
+ }
+
+-
+ void
+ ev_document_misc_paint_one_page (cairo_t *cr,
+ GtkWidget *widget,
+--- a/libdocument/ev-document-security.h
++++ b/libdocument/ev-document-security.h
+@@ -35,7 +35,6 @@
+
+ G_BEGIN_DECLS
+
+-
+ #define EV_TYPE_DOCUMENT_SECURITY (ev_document_security_get_type ())
+ #define EV_DOCUMENT_SECURITY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT_SECURITY, EvDocumentSecurity))
+ #define EV_DOCUMENT_SECURITY_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT_SECURITY, EvDocumentSecurityInterface))
+--- a/libdocument/ev-document-text.c
++++ b/libdocument/ev-document-text.c
+@@ -42,7 +42,6 @@
+ return iface->get_text (document_text, page);
+ }
+
+-
+ gboolean
+ ev_document_text_get_text_layout (EvDocumentText *document_text,
+ EvPage *page,
+--- a/libdocument/ev-document.c
++++ b/libdocument/ev-document.c
+@@ -388,7 +388,6 @@
+ return klass->get_page (document, index);
+ }
+
+-
+ #ifdef ENABLE_SYNCTEX
+ static gboolean
+ _ev_document_support_synctex (EvDocument *document)
+--- a/libdocument/ev-file-helpers.h
++++ b/libdocument/ev-file-helpers.h
+@@ -66,7 +66,6 @@
+ EvCompressionType type,
+ GError **error);
+
+-
+ G_END_DECLS
+
+ #endif /* EV_FILE_HELPERS_H */
+--- a/libdocument/ev-form-field.h
++++ b/libdocument/ev-form-field.h
+@@ -209,7 +209,6 @@
+ GType ev_form_field_signature_get_type (void) G_GNUC_CONST;
+ EvFormField *ev_form_field_signature_new (gint id);
+
+-
+ G_END_DECLS
+
+ #endif /* !EV_FORM_FIELD_H */
+--- a/libdocument/ev-image.h
++++ b/libdocument/ev-image.h
+@@ -62,7 +62,6 @@
+ GdkPixbuf *pixbuf);
+ const gchar *ev_image_get_tmp_uri (EvImage *image);
+
+-
+ G_END_DECLS
+
+ #endif /* __EV_IMAGE_H__ */
+--- a/libdocument/ev-render-context.h
++++ b/libdocument/ev-render-context.h
+@@ -52,7 +52,6 @@
+ gdouble scale;
+ };
+
+-
+ GType ev_render_context_get_type (void) G_GNUC_CONST;
+ EvRenderContext *ev_render_context_new (EvPage *page,
+ gint rotation,
+@@ -64,7 +63,6 @@
+ void ev_render_context_set_scale (EvRenderContext *rc,
+ gdouble scale);
+
+-
+ G_END_DECLS
+
+ #endif /* !EV_RENDER_CONTEXT */
+--- a/libdocument/ev-transition-effect.h
++++ b/libdocument/ev-transition-effect.h
+@@ -61,7 +61,6 @@
+ EV_TRANSITION_DIRECTION_OUTWARD
+ } EvTransitionEffectDirection;
+
+-
+ typedef struct EvTransitionEffect EvTransitionEffect;
+ typedef struct EvTransitionEffectClass EvTransitionEffectClass;
+
+@@ -75,7 +74,6 @@
+ GObjectClass parent_class;
+ };
+
+-
+ GType ev_transition_effect_get_type (void) G_GNUC_CONST;
+
+ EvTransitionEffect *ev_transition_effect_new (EvTransitionEffectType type,
+--- a/libmisc/ev-page-action-widget.c
++++ b/libmisc/ev-page-action-widget.c
+@@ -305,7 +305,6 @@
+ return TRUE;
+ }
+
+-
+ static void
+ display_completion_text (GtkCellLayout *cell_layout,
+ GtkCellRenderer *renderer,
+@@ -349,7 +348,6 @@
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+
+-
+ if (link) {
+ text = ev_link_get_title (link);
+ g_object_unref (link);
+@@ -445,7 +443,6 @@
+ return filter_model;
+ }
+
+-
+ void
+ ev_page_action_widget_update_links_model (EvPageActionWidget *proxy, GtkTreeModel *model)
+ {
+--- a/libview/ev-page-accessible.c
++++ b/libview/ev-page-accessible.c
+@@ -37,7 +37,6 @@
+ gboolean children_initialized;
+ };
+
+-
+ enum {
+ PROP_0,
+ PROP_VIEW_ACCESSIBLE,
+@@ -412,7 +411,6 @@
+ EvRectangle *next_word_end;
+ gint prev_offset, next_offset;
+
+-
+ if (!log_attrs[offset].is_white)
+ return FALSE;
+
+--- a/libview/ev-pixbuf-cache.c
++++ b/libview/ev-pixbuf-cache.c
+@@ -72,7 +72,6 @@
+ void (* job_finished) (EvPixbufCache *pixbuf_cache);
+ };
+
+-
+ enum
+ {
+ JOB_FINISHED,
+@@ -92,7 +91,6 @@
+ gint page,
+ gfloat scale);
+
+-
+ /* These are used for iterating through the prev and next arrays */
+ #define FIRST_VISIBLE_PREV(pixbuf_cache) \
+ (MAX (0, pixbuf_cache->preload_cache_size - pixbuf_cache->start_page))
+@@ -223,7 +221,6 @@
+ G_OBJECT_CLASS (ev_pixbuf_cache_parent_class)->dispose (object);
+ }
+
+-
+ EvPixbufCache *
+ ev_pixbuf_cache_new (GtkWidget *view,
+ EvDocumentModel *model,
+@@ -985,7 +982,6 @@
+ }
+ }
+
+-
+ void
+ ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache)
+ {
+@@ -1265,7 +1261,6 @@
+ }
+ }
+
+-
+ /* Returns what the pixbuf cache thinks is */
+
+ GList *
+@@ -1356,4 +1351,3 @@
+ EV_JOB_PRIORITY_URGENT);
+ }
+
+-
+--- a/libview/ev-pixbuf-cache.h
++++ b/libview/ev-pixbuf-cache.h
+@@ -39,8 +39,6 @@
+ #define EV_PIXBUF_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_PIXBUF_CACHE, EvPixbufCache))
+ #define EV_IS_PIXBUF_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_PIXBUF_CACHE))
+
+-
+-
+ /* The coordinates in the rect here are at scale == 1.0, so that we can ignore
+ * resizings. There is one per page, maximum.
+ */
+--- a/libview/ev-timeline.c
++++ b/libview/ev-timeline.c
+@@ -56,10 +56,8 @@
+
+ static guint signals [LAST_SIGNAL] = { 0, };
+
+-
+ G_DEFINE_TYPE_WITH_PRIVATE (EvTimeline, ev_timeline, G_TYPE_OBJECT)
+
+-
+ static void
+ ev_timeline_init (EvTimeline *timeline)
+ {
+--- a/libview/ev-timeline.h
++++ b/libview/ev-timeline.h
+@@ -59,7 +59,6 @@
+ gdouble progress);
+ };
+
+-
+ GType ev_timeline_get_type (void) G_GNUC_CONST;
+
+ EvTimeline *ev_timeline_new (guint duration);
+@@ -84,7 +83,6 @@
+
+ gdouble ev_timeline_get_progress (EvTimeline *timeline);
+
+-
+ G_END_DECLS
+
+ #endif /* __EV_TIMELINE_H__ */
+--- a/libview/ev-transition-animation.c
++++ b/libview/ev-transition-animation.c
+@@ -41,10 +41,8 @@
+ PROP_DEST_SURFACE
+ };
+
+-
+ G_DEFINE_TYPE_WITH_PRIVATE (EvTransitionAnimation, ev_transition_animation, EV_TYPE_TIMELINE)
+
+-
+ static void
+ ev_transition_animation_init (EvTransitionAnimation *animation)
+ {
+--- a/libview/ev-transition-animation.h
++++ b/libview/ev-transition-animation.h
+@@ -50,7 +50,6 @@
+ EvTimelineClass parent_class;
+ };
+
+-
+ GType ev_transition_animation_get_type (void) G_GNUC_CONST;
+
+ EvTransitionAnimation * ev_transition_animation_new (EvTransitionEffect *effect);
+@@ -67,7 +66,6 @@
+ GdkRectangle page_area);
+ gboolean ev_transition_animation_ready (EvTransitionAnimation *animation);
+
+-
+ G_END_DECLS
+
+ #endif /* __EV_TRANSITION_ANIMATION_H__ */
+--- a/libview/ev-view-presentation.c
++++ b/libview/ev-view-presentation.c
+@@ -1385,7 +1385,6 @@
+ return TRUE;
+ }
+
+-
+ static void
+ add_change_page_binding_keypad (GtkBindingSet *binding_set,
+ guint keyval,
+--- a/libview/ev-view.c
++++ b/libview/ev-view.c
+@@ -5621,7 +5621,6 @@
+
+ /*** Drawing ***/
+
+-
+ static void
+ draw_rubberband (EvView *view,
+ cairo_t *cr,
+@@ -5652,7 +5651,6 @@
+ cairo_restore (cr);
+ }
+
+-
+ static void
+ highlight_find_results (EvView *view, cairo_t *cr, int page)
+ {
+--- a/libview/ev-web-view.c
++++ b/libview/ev-web-view.c
+@@ -31,7 +31,6 @@
+ #include "ev-document-model.h"
+ #include "ev-jobs.h"
+
+-
+ typedef enum {
+ EV_WEB_VIEW_FIND_NEXT,
+ EV_WEB_VIEW_FIND_PREV
+@@ -322,7 +321,6 @@
+ web_view_update_range_and_current_page (webview);
+ }
+
+-
+ gboolean
+ ev_web_view_next_page (EvWebView *webview)
+ {
+--- a/libview/ev-web-view.h
++++ b/libview/ev-web-view.h
+@@ -35,7 +35,6 @@
+ #include <glib-object.h>
+ G_BEGIN_DECLS
+
+-
+ typedef struct _EvWebView EvWebView;
+ typedef struct _EvWebViewClass EvWebViewClass;
+
+--- a/previewer/ev-previewer-window.c
++++ b/previewer/ev-previewer-window.c
+@@ -621,7 +621,6 @@
+ return object;
+ }
+
+-
+ static void
+ ev_previewer_window_class_init (EvPreviewerWindowClass *klass)
+ {
+--- a/shell/eggfindbar.c
++++ b/shell/eggfindbar.c
+@@ -573,7 +573,6 @@
+ g_object_thaw_notify (G_OBJECT (find_bar));
+ }
+
+-
+ /**
+ * egg_find_bar_get_search_string:
+ *
+--- a/shell/eggfindbar.h
++++ b/shell/eggfindbar.h
+@@ -77,4 +77,3 @@
+
+ #endif /* __EGG_FIND_BAR_H__ */
+
+-
+--- a/shell/ev-application.c
++++ b/shell/ev-application.c
+@@ -21,7 +21,6 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-
+ #include <config.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -311,7 +310,6 @@
+ return empty_window;
+ }
+
+-
+ #ifdef ENABLE_DBUS
+ typedef struct {
+ gchar *uri;
+--- a/shell/ev-bookmarks.h
++++ b/shell/ev-bookmarks.h
+@@ -50,8 +50,6 @@
+ void ev_bookmarks_update (EvBookmarks *bookmarks,
+ EvBookmark *bookmark);
+
+-
+-
+ G_END_DECLS
+
+ #endif /* EV_BOOKMARKS_H */
+--- a/shell/ev-daemon.c
++++ b/shell/ev-daemon.c
+@@ -43,7 +43,6 @@
+
+ #define LOG g_debug
+
+-
+ #define EV_TYPE_DAEMON_APPLICATION (ev_daemon_application_get_type ())
+ #define EV_DAEMON_APPLICATION(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplication))
+
+--- a/shell/ev-history.c
++++ b/shell/ev-history.c
+@@ -24,7 +24,6 @@
+
+ #include "ev-history.h"
+
+-
+ enum
+ {
+ HISTORY_CHANGED,
+--- a/shell/ev-loading-message.c
++++ b/shell/ev-loading-message.c
+@@ -174,4 +174,3 @@
+ return message;
+ }
+
+-
+--- a/shell/ev-media-player-keys.h
++++ b/shell/ev-media-player-keys.h
+@@ -37,7 +37,6 @@
+ typedef struct _EvMediaPlayerKeys EvMediaPlayerKeys;
+ typedef struct _EvMediaPlayerKeysClass EvMediaPlayerKeysClass;
+
+-
+ GType ev_media_player_keys_get_type (void) G_GNUC_CONST;
+
+ EvMediaPlayerKeys *ev_media_player_keys_new (void);
+--- a/shell/ev-navigation-action.c
++++ b/shell/ev-navigation-action.c
+@@ -26,7 +26,6 @@
+ #include "ev-navigation-action.h"
+ #include "ev-navigation-action-widget.h"
+
+-
+ enum
+ {
+ WIDGET_ACTIVATE_LINK,
+--- a/shell/ev-open-recent-action.c
++++ b/shell/ev-open-recent-action.c
+@@ -24,7 +24,6 @@
+
+ #include "ev-open-recent-action.h"
+
+-
+ enum {
+ ITEM_ACTIVATED,
+ N_SIGNALS
+--- a/shell/ev-password-view.c
++++ b/shell/ev-password-view.c
+@@ -18,7 +18,6 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+@@ -47,7 +46,6 @@
+
+ static guint password_view_signals [LAST_SIGNAL] = { 0 };
+
+-
+ G_DEFINE_TYPE_WITH_PRIVATE (EvPasswordView, ev_password_view, GTK_TYPE_VIEWPORT)
+
+ static void
+--- a/shell/ev-sidebar-attachments.c
++++ b/shell/ev-sidebar-attachments.c
+@@ -631,7 +631,6 @@
+ g_object_unref (job);
+ }
+
+-
+ static void
+ ev_sidebar_attachments_document_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+--- a/shell/ev-sidebar-bookmarks.c
++++ b/shell/ev-sidebar-bookmarks.c
+@@ -122,7 +122,6 @@
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+-
+ selection = gtk_tree_view_get_selection (tree_view);
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ GtkTreePath *path;
+--- a/shell/ev-sidebar-layers.c
++++ b/shell/ev-sidebar-layers.c
+@@ -239,7 +239,6 @@
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (tree_view),
+ GTK_SELECTION_NONE);
+
+-
+ column = gtk_tree_view_column_new ();
+
+ renderer = gtk_cell_renderer_toggle_new ();
+--- a/shell/ev-sidebar-links.c
++++ b/shell/ev-sidebar-links.c
+@@ -379,7 +379,6 @@
+ return FALSE;
+ }
+
+-
+ static void
+ ev_sidebar_links_construct (EvSidebarLinks *ev_sidebar_links)
+ {
+@@ -425,7 +424,6 @@
+ "markup", EV_DOCUMENT_LINKS_COLUMN_MARKUP,
+ NULL);
+
+-
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_end (GTK_TREE_VIEW_COLUMN (column), renderer, FALSE);
+ gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
+@@ -566,7 +564,6 @@
+ }
+ }
+
+-
+ static gint
+ page_link_tree_sort (gconstpointer a, gconstpointer b, void *data)
+ {
+--- a/shell/ev-sidebar-links.h
++++ b/shell/ev-sidebar-links.h
+@@ -63,4 +63,3 @@
+
+ #endif /* __EV_SIDEBAR_LINKS_H__ */
+
+-
+--- a/shell/ev-sidebar-page.c
++++ b/shell/ev-sidebar-page.c
+@@ -74,7 +74,6 @@
+ return iface->get_label (sidebar_page);
+ }
+
+-
+ static void
+ ev_sidebar_page_default_init (EvSidebarPageInterface *iface)
+ {
+--- a/shell/ev-sidebar-page.h
++++ b/shell/ev-sidebar-page.h
+@@ -58,7 +58,6 @@
+ EvDocumentModel *model);
+ const gchar* ev_sidebar_page_get_label (EvSidebarPage *page);
+
+-
+ G_END_DECLS
+
+ #endif /* EV_SIDEBAR_PAGE */
+--- a/shell/ev-sidebar-thumbnails.c
++++ b/shell/ev-sidebar-thumbnails.c
+@@ -245,7 +245,6 @@
+ return cache;
+ }
+
+-
+ static void
+ ev_sidebar_thumbnails_dispose (GObject *object)
+ {
+--- a/shell/ev-sidebar-thumbnails.h
++++ b/shell/ev-sidebar-thumbnails.h
+@@ -56,4 +56,3 @@
+
+ #endif /* __EV_SIDEBAR_THUMBNAILS_H__ */
+
+-
+--- a/shell/ev-sidebar.c
++++ b/shell/ev-sidebar.c
+@@ -446,7 +446,6 @@
+ gtk_list_store_move_before(GTK_LIST_STORE(ev_sidebar->priv->page_model),
+ &iter, NULL);
+
+-
+ /* Set the first item added as active */
+ gtk_tree_model_get_iter_first (ev_sidebar->priv->page_model, &iter);
+ gtk_tree_model_get (ev_sidebar->priv->page_model,
+--- a/shell/ev-sidebar.h
++++ b/shell/ev-sidebar.h
+@@ -64,4 +64,3 @@
+
+ #endif /* __EV_SIDEBAR_H__ */
+
+-
+--- a/shell/ev-window.c
++++ b/shell/ev-window.c
+@@ -418,7 +418,6 @@
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+ }
+
+-
+ static void
+ ev_window_setup_action_sensitivity (EvWindow *ev_window)
+ {
+@@ -1555,7 +1554,6 @@
+ ev_document_model_set_scale (model, g_settings_get_double (settings, "zoom"));
+ }
+
+-
+ static void
+ ev_window_clear_thumbnail_job (EvWindow *ev_window)
+ {
+@@ -3636,7 +3634,6 @@
+ GtkWidget *dialog;
+ GError *error = NULL;
+
+-
+ ev_print_operation_get_error (op, &error);
+
+ /* The message area is already used by
+@@ -3891,7 +3888,6 @@
+ return FALSE;
+ }
+
+-
+ text = g_markup_printf_escaped (_("Save a copy of document “%s” before closing?"),
+ gtk_window_get_title (GTK_WINDOW (ev_window)));
+
+@@ -4414,7 +4410,6 @@
+ _("Running in presentation mode"));
+ }
+
+-
+ static void
+ ev_window_uninhibit_screensaver (EvWindow *window)
+ {
+@@ -4727,7 +4722,6 @@
+ ev_window_update_actions (window);
+ }
+
+-
+ static void
+ ev_window_cmd_edit_rotate_left (GtkAction *action, EvWindow *ev_window)
+ {
+@@ -5977,7 +5971,6 @@
+ * the new expanded window size.
+ */
+
+-
+ if (ev_window->priv->chrome & EV_CHROME_SIDEBAR)
+ {
+ GtkAllocation alloc;
+@@ -6491,7 +6484,6 @@
+ { "EditSaveSettings", NULL, N_("Save Current Settings as _Default"), "<control>T", NULL,
+ G_CALLBACK (ev_window_cmd_edit_save_settings) },
+
+-
+ /* View menu */
+ { "ViewZoomIn", "zoom-in", N_("Zoom _In"), "<control>plus",
+ N_("Enlarge the document"),
+@@ -7746,7 +7738,6 @@
+ ev_atril_window_emit_document_loaded (window->priv->skeleton, window->priv->uri);
+ }
+
+-
+ #ifdef ENABLE_SYNCTEX
+ static gboolean
+ handle_sync_view_cb (EvAtrilWindow *object,
+--- a/shell/ev-window.h
++++ b/shell/ev-window.h
+@@ -58,7 +58,6 @@
+ #define EV_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_WINDOW))
+ #define EV_WINDOW_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_WINDOW, EvWindowClass))
+
+-
+ struct _EvWindow {
+ GtkApplicationWindow base_instance;
+ EvWindowPrivate *priv;
+@@ -87,7 +86,6 @@
+ int last_page);
+ const gchar * ev_window_get_dbus_object_path (EvWindow *ev_window);
+
+-
+ G_END_DECLS
+
+ #endif /* !EV_WINDOW_H */
+--- a/shell/main.c
++++ b/shell/main.c
+@@ -36,7 +36,6 @@
+ #include "eggsmclient.h"
+ #include "eggdesktopfile.h"
+
+-
+ static gchar *ev_page_label;
+ static gchar *ev_find_string;
+ static gint ev_page_index = 0;
+@@ -48,7 +47,6 @@
+ static gchar *print_settings;
+ static const char **file_arguments = NULL;
+
+-
+ static gboolean
+ option_version_cb (const gchar *option_name,
+ const gchar *value,
+@@ -206,8 +204,6 @@
+ continue;
+ }
+
+-
+-
+ ev_application_open_uri_at_dest (EV_APP, uri, screen, dest,
+ mode, ev_find_string,
+ GDK_CURRENT_TIME);
diff -Nru atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch
--- atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch 1970-01-01 01:00:00.000000000 +0100
+++ atril-1.26.0/debian/patches/0006-comics-Use-libarchive-to-unpack-documents.patch 2024-01-23 10:06:08.000000000 +0100
@@ -0,0 +1,1814 @@
+From aa8e9dad472cbadc96719a8f521768aeeb0913f0 Mon Sep 17 00:00:00 2001
+From: lukefromdc <lukefromdc@hushmail.com>
+Date: Mon, 25 Dec 2023 15:11:04 -0500
+Subject: [PATCH 2/2] comics: Use libarchive to unpack documents
+
+This commit eliminates the use of external commands for opening
+comic documents, and uses libarchive instead.
+
+Signed-off-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+---
+ backend/comics/Makefile.am | 5 +-
+ backend/comics/comics-document.c | 1143 +++++++++++-------------------
+ backend/comics/comics-document.h | 7 +-
+ backend/comics/ev-archive.c | 323 +++++++++
+ backend/comics/ev-archive.h | 56 ++
+ configure.ac | 3 +
+ libdocument/ev-document.h | 1 +
+ 7 files changed, 799 insertions(+), 739 deletions(-)
+ create mode 100644 backend/comics/ev-archive.c
+ create mode 100644 backend/comics/ev-archive.h
+
+diff --git a/backend/comics/Makefile.am b/backend/comics/Makefile.am
+index b27f9b85..77f3dedb 100644
+--- a/backend/comics/Makefile.am
++++ b/backend/comics/Makefile.am
+@@ -12,12 +12,15 @@ backend_LTLIBRARIES = libcomicsdocument.la
+
+ libcomicsdocument_la_SOURCES = \
+ comics-document.c \
+- comics-document.h
++ comics-document.h \
++ ev-archive.c \
++ ev-archive.h
+
+ libcomicsdocument_la_LDFLAGS = $(BACKEND_LIBTOOL_FLAGS)
+ libcomicsdocument_la_LIBADD = \
+ $(top_builddir)/libdocument/libatrildocument.la \
+ $(BACKEND_LIBS) \
++ $(COMICS_LIBS) \
+ $(LIB_LIBS)
+
+ backend_in_files = comicsdocument.atril-backend.desktop.in
+diff --git a/backend/comics/comics-document.c b/backend/comics/comics-document.c
+index ed02a35c..1da1eee2 100644
+--- a/backend/comics/comics-document.c
++++ b/backend/comics/comics-document.c
+@@ -30,24 +30,17 @@
+ #include <glib/gstdio.h>
+ #include <gio/gio.h>
+
+-#include <sys/wait.h>
+-
+ #include "comics-document.h"
+ #include "ev-document-misc.h"
+ #include "ev-document-thumbnails.h"
+ #include "ev-file-helpers.h"
++#include "ev-archive.h"
++#include <archive.h>
++#include <archive_entry.h>
+
+ #define EV_EOL "\n"
+
+-typedef enum
+-{
+- RARLABS,
+- GNAUNRAR,
+- UNZIP,
+- P7ZIP,
+- TAR,
+- UNARCHIVER
+-} ComicBookDecompressType;
++#define BLOCK_SIZE 10240
+
+ typedef struct _ComicsDocumentClass ComicsDocumentClass;
+
+@@ -58,398 +51,269 @@ struct _ComicsDocumentClass
+
+ struct _ComicsDocument
+ {
+- EvDocument parent_instance;
+-
+- gchar *archive, *dir;
+- GPtrArray *page_names;
+- gchar *selected_command, *alternative_command;
+- gchar *extract_command, *list_command, *decompress_tmp;
+- gboolean regex_arg;
+- gint offset;
+- ComicBookDecompressType command_usage;
++ EvDocument parent_instance;
++ EvArchive *archive;
++ gchar *archive_path;
++ gchar *archive_uri;
++ GPtrArray *page_names; /* elem: char * */
++ GHashTable *page_positions; /* key: char *, value: uint + 1 */
++
+ };
+
+-#define OFFSET_7Z 53
+-#define OFFSET_ZIP 2
+-#define NO_OFFSET 0
+-
+-/* For perfomance reasons of 7z* we've choosen to decompress on the temporary
+- * directory instead of decompressing on the stdout */
+-
+-/**
+- * @extract: command line arguments to pass to extract a file from the archive
+- * to stdout.
+- * @list: command line arguments to list the archive contents
+- * @decompress_tmp: command line arguments to pass to extract the archive
+- * into a directory.
+- * @regex_arg: whether the command can accept regex expressions
+- * @offset: the position offset of the filename on each line in the output of
+- * running the @list command
+- */
+-typedef struct {
+- char *extract;
+- char *list;
+- char *decompress_tmp;
+- gboolean regex_arg;
+- gint offset;
+-} ComicBookDecompressCommand;
++static void
++comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
++EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,
++ {
++ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
++ comics_document_document_thumbnails_iface_init);
++ } );
++
++#define FORMAT_UNKNOWN 0
++#define FORMAT_SUPPORTED 1
++#define FORMAT_UNSUPPORTED 2
++
++/* Returns a GHashTable of:
++ * <key>: file extensions
++ * <value>: degree of support in gdk-pixbuf */
++static GHashTable *
++get_image_extensions(void)
++{
++ GHashTable *extensions;
++ GSList *formats = gdk_pixbuf_get_formats ();
++ GSList *l;
++ guint i;
++ const char *known_image_formats[] = {
++ "png",
++ "jpg",
++ "jpeg",
++ "webp"
++ };
++
++ extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
++ g_free, NULL);
++ for (l = formats; l != NULL; l = l->next) {
++ int i;
++ gchar **ext = gdk_pixbuf_format_get_extensions (l->data);
++
++ for (i = 0; ext[i] != NULL; i++) {
++ g_hash_table_insert (extensions,
++ g_strdup (ext[i]),
++ GINT_TO_POINTER (FORMAT_SUPPORTED));
++ }
+
+-static const ComicBookDecompressCommand command_usage_def[] = {
+- /* RARLABS unrar */
+- {"%s p -c- -ierr --", "%s vb -c- -- %s", NULL , FALSE, NO_OFFSET},
++ g_strfreev (ext);
++ }
++ g_slist_free (formats);
+
+- /* GNA! unrar */
+- {NULL , "%s t %s" , "%s -xf %s %s" , FALSE, NO_OFFSET},
++ /* Add known image formats that aren't supported by gdk-pixbuf */
++ for (i = 0; i < G_N_ELEMENTS (known_image_formats); i++) {
++ if (!g_hash_table_lookup (extensions, known_image_formats[i])) {
++ g_hash_table_insert (extensions,
++ g_strdup (known_image_formats[i]),
++ GINT_TO_POINTER (FORMAT_UNSUPPORTED));
++ }
++ }
+
+- /* unzip */
+- {"%s -p -C --" , "%s %s" , NULL , TRUE , OFFSET_ZIP},
++ return extensions;
++}
+
+- /* 7zip */
+- {NULL , "%s l -- %s" , "%s x -y %s -o%s", FALSE, OFFSET_7Z},
++static int
++has_supported_extension (const char *name,
++ GHashTable *supported_extensions)
++{
++ gboolean ret = FALSE;
++ gchar *suffix;
++ suffix = g_strrstr (name, ".");
++ if (!suffix)
++ return ret;
+
+- /* tar */
+- {"%s -xOf" , "%s -tf %s" , NULL , FALSE, NO_OFFSET},
++ suffix = g_ascii_strdown (suffix + 1, -1);
++ ret = GPOINTER_TO_INT (g_hash_table_lookup (supported_extensions, suffix));
++ g_free (suffix);
+
+- /* UNARCHIVER */
+- {"unar -o -" , "%s %s" , NULL , FALSE, NO_OFFSET}
+-};
++ return ret;
++}
+
+-static void comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
++#define APPLE_DOUBLE_PREFIX "._"
++static gboolean
++is_apple_double (const char *name)
++{
++char *basename;
++ gboolean ret = FALSE;
+
+-static GSList* get_supported_image_extensions (void);
+-static void get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
+- gpointer data);
+-static void render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
+- gint width,
+- gint height,
+- gpointer data);
+-static char** extract_argv (EvDocument *document,
+- gint page);
++ basename = g_path_get_basename (name);
++ if (basename == NULL) {
++ g_debug ("Filename '%s' doesn't have a basename?", name);
++ return ret;
++ }
++ ret = g_str_has_prefix (basename, APPLE_DOUBLE_PREFIX);
++ g_free (basename);
+
+-EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,
+- {
+- EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+- comics_document_document_thumbnails_iface_init);
+- } );
+-
+-/**
+- * comics_regex_quote:
+- * @unquoted_string: a literal string
+- *
+- * Quotes a string so unzip will not interpret the regex expressions of
+- * @unquoted_string. Basically, this functions uses [] to disable regex
+- * expressions. The return value must be freed with * g_free()
+- *
+- * Return value: quoted and disabled-regex string
+- **/
+-static gchar *
+-comics_regex_quote (const gchar *unquoted_string)
++ return ret;
++}
++
++static gboolean
++archive_reopen_if_needed (ComicsDocument *comics_document,
++ const char *page_wanted,
++ GError **error)
+ {
+- const gchar *p;
+- GString *dest;
+-
+- dest = g_string_new ("'");
+-
+- p = unquoted_string;
+-
+- while (*p) {
+- switch (*p) {
+- /* * matches a sequence of 0 or more characters */
+- case ('*'):
+- /* ? matches exactly 1 charactere */
+- case ('?'):
+- /* [...] matches any single character found inside
+- * the brackets. Disabling the first bracket is enough.
+- */
+- case ('['):
+- g_string_append (dest, "[");
+- g_string_append_c (dest, *p);
+- g_string_append (dest, "]");
+- break;
+- /* Because \ escapes regex expressions that we are
+- * disabling for unzip, we need to disable \ too */
+- case ('\\'):
+- g_string_append (dest, "[\\\\]");
+- break;
+- /* Escape single quote inside the string */
+- case ('\''):
+- g_string_append (dest, "'\\''");
+- break;
+- default:
+- g_string_append_c (dest, *p);
+- break;
++ const char *current_page;
++ guint current_page_idx, page_wanted_idx;
++
++ if (ev_archive_at_entry (comics_document->archive)) {
++ current_page = ev_archive_get_entry_pathname (comics_document->archive);
++ if (current_page) {
++ current_page_idx = GPOINTER_TO_UINT (g_hash_table_lookup (comics_document->page_positions, current_page));
++ page_wanted_idx = GPOINTER_TO_UINT (g_hash_table_lookup (comics_document->page_positions, page_wanted));
++
++ if (current_page_idx != 0 &&
++ page_wanted_idx != 0 &&
++ page_wanted_idx > current_page_idx)
++ return TRUE;
+ }
+- ++p;
++
++ ev_archive_reset (comics_document->archive);
+ }
+- g_string_append_c (dest, '\'');
+- return g_string_free (dest, FALSE);
++return ev_archive_open_filename (comics_document->archive, comics_document->archive_path, error);
+ }
+
+-/* This function manages the command for decompressing a comic book */
+-static gboolean
+-comics_decompress_temp_dir (const gchar *command_decompress_tmp,
+- const gchar *command,
+- GError **error)
++static GPtrArray *
++comics_document_list (ComicsDocument *comics_document,
++ GError **error)
+ {
+- gboolean success;
+- gchar *std_out, *basename;
+- GError *err = NULL;
+- gint retval;
+-
+- success = g_spawn_command_line_sync (command_decompress_tmp, &std_out,
+- NULL, &retval, &err);
+- basename = g_path_get_basename (command);
+- if (!success) {
+- g_set_error (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("Error launching the command “%s” in order to "
+- "decompress the comic book: %s"),
+- basename,
+- err->message);
+- g_error_free (err);
+- } else if (WIFEXITED (retval)) {
+- if (WEXITSTATUS (retval) == EXIT_SUCCESS) {
+- g_free (std_out);
+- g_free (basename);
+- return TRUE;
+- } else {
+- g_set_error (error,
++GPtrArray *array = NULL;
++ gboolean has_encrypted_files, has_unsupported_images, has_archive_errors;
++ GHashTable *supported_extensions = NULL;
++
++ if (!ev_archive_open_filename (comics_document->archive, comics_document->archive_path, error)) {
++ if (*error != NULL) {
++ g_warning ("Fatal error handling archive (%s): %s", G_STRFUNC, (*error)->message);
++ g_clear_error (error);
++ }
++
++ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+- _("The command “%s” failed at "
+- "decompressing the comic book."),
+- basename);
+- g_free (std_out);
++ _("File is corrupted"));
++ goto out;
++ }
++
++ supported_extensions = get_image_extensions ();
++
++ has_encrypted_files = FALSE;
++ has_unsupported_images = FALSE;
++ has_archive_errors = FALSE;
++ array = g_ptr_array_sized_new (64);
++
++ while (1) {
++ const char *name;
++ int supported;
++
++ if (!ev_archive_read_next_header (comics_document->archive, error)) {
++ if (*error != NULL) {
++ g_debug ("Fatal error handling archive (%s): %s", G_STRFUNC, (*error)->message);
++ g_clear_error (error);
++ has_archive_errors = TRUE;
++ goto out;
++ }
++ break;
+ }
+- } else {
+- g_set_error (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("The command “%s” did not end normally."),
+- basename);
+- g_free (std_out);
++
++ name = ev_archive_get_entry_pathname (comics_document->archive);
++ /* Ignore https://en.wikipedia.org/wiki/AppleSingle_and_AppleDouble_formats */
++ if (is_apple_double (name)) {
++ g_debug ("Not adding AppleDouble file '%s' to the list of files in the comics", name);
++ continue;
++ }
++
++ supported = has_supported_extension (name, supported_extensions);
++ if (supported == FORMAT_UNKNOWN) {
++ g_debug ("Not adding unsupported file '%s' to the list of files in the comics", name);
++ continue;
++ } else if (supported == FORMAT_UNSUPPORTED) {
++ g_debug ("Not adding unsupported image '%s' to the list of files in the comics", name);
++ has_unsupported_images = TRUE;
++ continue;
++ }
++
++ if (ev_archive_get_entry_is_encrypted (comics_document->archive)) {
++ g_debug ("Not adding encrypted file '%s' to the list of files in the comics", name);
++ has_encrypted_files = TRUE;
++ continue;
++ }
++
++ g_debug ("Adding '%s' to the list of files in the comics", name);
++ g_ptr_array_add (array, g_strdup (name));
+ }
+- g_free (basename);
+- return FALSE;
++out:
++ if (array->len == 0) {
++ g_ptr_array_free (array, TRUE);
++ array = NULL;
++
++ if (has_encrypted_files) {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_ENCRYPTED,
++ _("Archive is encrypted"));
++ } else if (has_unsupported_images) {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_UNSUPPORTED_CONTENT,
++ _("No supported images in archive"));
++ } else if (has_archive_errors) {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_INVALID,
++ _("File is corrupted"));
++ } else {
++ g_set_error_literal (error,
++ EV_DOCUMENT_ERROR,
++ EV_DOCUMENT_ERROR_INVALID,
++ _("No files in archive"));
++ }
++ }
++
++ if (supported_extensions)
++ g_hash_table_destroy (supported_extensions);
++ ev_archive_reset (comics_document->archive);
++ return array;
+ }
+
+-/* This function shows how to use the choosen command for decompressing a
+- * comic book file. It modifies fields of the ComicsDocument struct with
+- * this information */
+-static gboolean
+-comics_generate_command_lines (ComicsDocument *comics_document,
+- GError **error)
++static GHashTable *
++save_positions (GPtrArray *page_names)
+ {
+- gchar *quoted_file, *quoted_file_aux;
+- gchar *quoted_command;
+- ComicBookDecompressType type;
+-
+- type = comics_document->command_usage;
+- comics_document->regex_arg = command_usage_def[type].regex_arg;
+- quoted_command = g_shell_quote (comics_document->selected_command);
+- if (comics_document->regex_arg) {
+- quoted_file = comics_regex_quote (comics_document->archive);
+- quoted_file_aux = g_shell_quote (comics_document->archive);
+- comics_document->list_command =
+- g_strdup_printf (command_usage_def[type].list,
+- comics_document->alternative_command,
+- quoted_file_aux);
+- g_free (quoted_file_aux);
+- } else {
+- quoted_file = g_shell_quote (comics_document->archive);
+- comics_document->list_command =
+- g_strdup_printf (command_usage_def[type].list,
+- quoted_command, quoted_file);
+- }
+- comics_document->extract_command =
+- g_strdup_printf (command_usage_def[type].extract,
+- quoted_command);
+- comics_document->offset = command_usage_def[type].offset;
+- if (command_usage_def[type].decompress_tmp) {
+- comics_document->dir = ev_mkdtemp ("atril-comics-XXXXXX", error);
+- if (comics_document->dir == NULL)
+- return FALSE;
+-
+- /* unrar-free can't create directories, but ev_mkdtemp already created the dir */
+-
+- comics_document->decompress_tmp =
+- g_strdup_printf (command_usage_def[type].decompress_tmp,
+- quoted_command, quoted_file,
+- comics_document->dir);
+- g_free (quoted_file);
+- g_free (quoted_command);
+-
+- if (!comics_decompress_temp_dir (comics_document->decompress_tmp,
+- comics_document->selected_command, error))
+- return FALSE;
+- else
+- return TRUE;
+- } else {
+- g_free (quoted_file);
+- g_free (quoted_command);
+- return TRUE;
+- }
++ guint i;
++ GHashTable *ht;
+
++ ht = g_hash_table_new (g_str_hash, g_str_equal);
++ for (i = 0; i < page_names->len; i++)
++ g_hash_table_insert (ht, page_names->pdata[i], GUINT_TO_POINTER(i + 1));
++ return ht;
+ }
+
+-/* This function chooses an external command for decompressing a comic
+- * book based on its mime tipe. */
++/*This function chooses the archive decompression support
++ * book based on its mime type. */
+ static gboolean
+-comics_check_decompress_command (gchar *mime_type,
++comics_check_decompress_support (gchar *mime_type,
+ ComicsDocument *comics_document,
+ GError **error)
+ {
+- gboolean success;
+- gchar *std_out, *std_err;
+- gint retval;
+- GError *err = NULL;
+-
+- /* FIXME, use proper cbr/cbz mime types once they're
+- * included in shared-mime-info */
+-
+ if (g_content_type_is_a (mime_type, "application/x-cbr") ||
+ g_content_type_is_a (mime_type, "application/x-rar")) {
+- /* The RARLAB provides a no-charge proprietary (freeware)
+- * decompress-only client for Linux called unrar. Another
+- * option is a GPLv2-licensed command-line tool developed by
+- * the Gna! project. Confusingly enough, the free software RAR
+- * decoder is also named unrar. For this reason we need to add
+- * some lines for disambiguation. Sorry for the added the
+- * complexity but it's life :)
+- * Finally, some distributions, like Debian, rename this free
+- * option as unrar-free.
+- * */
+- comics_document->selected_command =
+- g_find_program_in_path ("unrar");
+- if (comics_document->selected_command) {
+- /* We only use std_err to avoid printing useless error
+- * messages on the terminal */
+- success =
+- g_spawn_command_line_sync (
+- comics_document->selected_command,
+- &std_out, &std_err,
+- &retval, &err);
+- if (!success) {
+- g_propagate_error (error, err);
+- g_error_free (err);
+- return FALSE;
+- /* I don't check retval status because RARLAB unrar
+- * doesn't have a way to return 0 without involving an
+- * operation with a file*/
+- } else if (WIFEXITED (retval)) {
+- if (g_strrstr (std_out,"freeware") != NULL)
+- /* The RARLAB freeware client */
+- comics_document->command_usage = RARLABS;
+- else
+- /* The Gna! free software client */
+- comics_document->command_usage = GNAUNRAR;
+-
+- g_free (std_out);
+- g_free (std_err);
+- return TRUE;
+- }
+- }
+- /* The Gna! free software client with Debian naming convention */
+- comics_document->selected_command =
+- g_find_program_in_path ("unrar-free");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = GNAUNRAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_RAR))
+ return TRUE;
+- }
+-
+ } else if (g_content_type_is_a (mime_type, "application/x-cbz") ||
+ g_content_type_is_a (mime_type, "application/zip")) {
+- /* InfoZIP's unzip program */
+- comics_document->selected_command =
+- g_find_program_in_path ("unzip");
+- comics_document->alternative_command =
+- g_find_program_in_path ("zipnote");
+- if (comics_document->selected_command &&
+- comics_document->alternative_command) {
+- comics_document->command_usage = UNZIP;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_ZIP))
+ return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+-
+ } else if (g_content_type_is_a (mime_type, "application/x-cb7") ||
+ g_content_type_is_a (mime_type, "application/x-7z-compressed")) {
+- /* 7zr, 7za and 7z are the commands from the p7zip project able
+- * to decompress .7z files */
+- comics_document->selected_command =
+- g_find_program_in_path ("7zr");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = P7ZIP;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_7Z))
+ return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("7za");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = P7ZIP;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("7z");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = P7ZIP;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+ } else if (g_content_type_is_a (mime_type, "application/x-cbt") ||
+ g_content_type_is_a (mime_type, "application/x-tar")) {
+- /* tar utility (Tape ARchive) */
+- comics_document->selected_command =
+- g_find_program_in_path ("tar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
++ if (ev_archive_set_archive_type (comics_document->archive, EV_ARCHIVE_TYPE_TAR))
+ return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("bsdtar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = TAR;
+- return TRUE;
+- }
+- comics_document->selected_command =
+- g_find_program_in_path ("lsar");
+- if (comics_document->selected_command) {
+- comics_document->command_usage = UNARCHIVER;
+- return TRUE;
+- }
+ } else {
+ g_set_error (error,
+ EV_DOCUMENT_ERROR,
+@@ -461,8 +325,9 @@ comics_check_decompress_command (gchar *mime_type,
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+- _("Can't find an appropriate command to "
+- "decompress this type of comic book"));
++ _("libarchive lacks support for this comic book’s "
++ "compression, please contact your distributor"));
++
+ return FALSE;
+ }
+
+@@ -470,43 +335,15 @@ static int
+ sort_page_names (gconstpointer a,
+ gconstpointer b)
+ {
+- const char *name_1, *name_2;
+- gchar *key_1, *key_2;
+- gboolean sort_last_1, sort_last_2;
+- int compare;
+-
+- name_1 = * (const char **) a;
+- name_2 = * (const char **) b;
+-
+- #define SORT_LAST_CHAR1 '.'
+- #define SORT_LAST_CHAR2 '#'
+-
+- sort_last_1 = name_1[0] == SORT_LAST_CHAR1 || name_1[0] == SORT_LAST_CHAR2;
+- sort_last_2 = name_2[0] == SORT_LAST_CHAR1 || name_2[0] == SORT_LAST_CHAR2;
+-
+- #undef SORT_LAST_CHAR1
+- #undef SORT_LAST_CHAR2
+-
+- if (sort_last_1 && !sort_last_2)
+- {
+- compare = +1;
+- }
+- else if (!sort_last_1 && sort_last_2)
+- {
+- compare = -1;
+- }
+- else
+- {
+- key_1 = g_utf8_collate_key_for_filename (name_1, -1);
+- key_2 = g_utf8_collate_key_for_filename (name_2, -1);
+-
+- compare = strcmp (key_1, key_2);
+-
+- g_free (key_1);
+- g_free (key_2);
+- }
+-
+- return compare;
++ gchar *temp1, *temp2;
++ gint ret;
++ temp1 = g_utf8_collate_key_for_filename (* (const char **) a, -1);
++ temp2 = g_utf8_collate_key_for_filename (* (const char **) b, -1);
++ ret = strcmp (temp1, temp2);
++
++ g_free (temp1);
++ g_free (temp2);
++ return ret;
+ }
+
+ static gboolean
+@@ -515,50 +352,13 @@ comics_document_load (EvDocument *document,
+ GError **error)
+ {
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+- GSList *supported_extensions;
+- gchar *std_out;
+ gchar *mime_type;
+- gchar **cb_files, *cb_file;
+- gboolean success;
+- int i, retval;
+- GError *err = NULL;
+-
+- comics_document->archive = g_filename_from_uri (uri, NULL, error);
+- if (!comics_document->archive)
+- return FALSE;
+-
+- mime_type = ev_file_get_mime_type (uri, FALSE, &err);
+- if (!mime_type) {
+- if (err) {
+- g_propagate_error (error, err);
+- } else {
+- g_set_error_literal (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("Unknown MIME Type"));
+- }
+-
+- return FALSE;
+- }
+-
+- if (!comics_check_decompress_command (mime_type, comics_document,
+- error)) {
+- g_free (mime_type);
+- return FALSE;
+- } else if (!comics_generate_command_lines (comics_document, error)) {
+- g_free (mime_type);
+- return FALSE;
+- }
++ GFile *file;
++ file = g_file_new_for_uri (uri);
++ comics_document->archive_path = g_file_get_path (file);
++ g_object_unref (file);
+
+- g_free (mime_type);
+-
+- /* Get list of files in archive */
+- success = g_spawn_command_line_sync (comics_document->list_command,
+- &std_out, NULL, &retval, error);
+-
+- if (!success) {
+- return FALSE;
+- } else if (!WIFEXITED(retval) || WEXITSTATUS(retval) != EXIT_SUCCESS) {
++ if (!comics_document->archive_path) {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+@@ -566,58 +366,26 @@ comics_document_load (EvDocument *document,
+ return FALSE;
+ }
+
+- /* FIXME: is this safe against filenames containing \n in the archive ? */
+- cb_files = g_strsplit (std_out, EV_EOL, 0);
++ comics_document->archive_uri = g_strdup (uri);
++ mime_type = ev_file_get_mime_type (uri, FALSE, error);
+
+- g_free (std_out);
++ if (mime_type == NULL)
++ return FALSE;
+
+- if (!cb_files) {
+- g_set_error_literal (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("No files in archive"));
++ if (!comics_check_decompress_support (mime_type, comics_document, error)) {
++ g_free (mime_type);
+ return FALSE;
+ }
+
+- comics_document->page_names = g_ptr_array_sized_new (64);
+-
+- supported_extensions = get_supported_image_extensions ();
+- for (i = 0; cb_files[i] != NULL; i++) {
+- if (comics_document->offset != NO_OFFSET) {
+- if (g_utf8_strlen (cb_files[i],-1) >
+- comics_document->offset) {
+- cb_file =
+- g_utf8_offset_to_pointer (cb_files[i],
+- comics_document->offset);
+- } else {
+- continue;
+- }
+- } else {
+- cb_file = cb_files[i];
+- }
+- gchar *suffix = g_strrstr (cb_file, ".");
+- if (!suffix)
+- continue;
+- suffix = g_ascii_strdown (suffix + 1, -1);
+- if (g_slist_find_custom (supported_extensions, suffix,
+- (GCompareFunc) strcmp) != NULL) {
+- g_ptr_array_add (comics_document->page_names,
+- g_strstrip (g_strdup (cb_file)));
+- }
+- g_free (suffix);
+- }
+- g_strfreev (cb_files);
+- g_slist_foreach (supported_extensions, (GFunc) g_free, NULL);
+- g_slist_free (supported_extensions);
++ g_free (mime_type);
+
+- if (comics_document->page_names->len == 0) {
+- g_set_error (error,
+- EV_DOCUMENT_ERROR,
+- EV_DOCUMENT_ERROR_INVALID,
+- _("No images found in archive %s"),
+- uri);
++ /* Get list of files in archive */
++ comics_document->page_names = comics_document_list (comics_document, error);
++ if (!comics_document->page_names)
+ return FALSE;
+- }
++
++ /* Keep an index */
++ comics_document->page_positions = save_positions (comics_document->page_names);
+
+ /* Now sort the pages */
+ g_ptr_array_sort (comics_document->page_names, sort_page_names);
+@@ -632,7 +400,7 @@ comics_document_save (EvDocument *document,
+ {
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+
+- return ev_xfer_uri_simple (comics_document->archive, uri, error);
++ return ev_xfer_uri_simple (comics_document->archive_uri, uri, error);
+ }
+
+ static int
+@@ -646,6 +414,23 @@ comics_document_get_n_pages (EvDocument *document)
+ return comics_document->page_names->len;
+ }
+
++typedef struct {
++ gboolean got_info;
++ int height;
++ int width;
++} PixbufInfo;
++
++static void
++get_page_size_prepared_cb (GdkPixbufLoader *loader,
++ int width,
++ int height,
++ PixbufInfo *info)
++{
++ info->got_info = TRUE;
++ info->height = height;
++ info->width = width;
++}
++
+ static void
+ comics_document_get_page_size (EvDocument *document,
+ EvPage *page,
+@@ -653,74 +438,89 @@ comics_document_get_page_size (EvDocument *document,
+ double *height)
+ {
+ GdkPixbufLoader *loader;
+- char **argv;
+- guchar buf[1024];
+- gboolean success, got_size = FALSE;
+- gint outpipe = -1;
+- GPid child_pid;
+- gssize bytes;
+- GdkPixbuf *pixbuf;
+- gchar *filename;
++
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+
+- if (!comics_document->decompress_tmp) {
+- argv = extract_argv (document, page->index);
+- success = g_spawn_async_with_pipes (NULL, argv, NULL,
+- G_SPAWN_SEARCH_PATH |
+- G_SPAWN_STDERR_TO_DEV_NULL,
+- NULL, NULL,
+- &child_pid,
+- NULL, &outpipe, NULL, NULL);
+- g_strfreev (argv);
+- g_return_if_fail (success == TRUE);
+-
+- loader = gdk_pixbuf_loader_new ();
+- g_signal_connect (loader, "area-prepared",
+- G_CALLBACK (get_page_size_area_prepared_cb),
+- &got_size);
+-
+- while (outpipe >= 0) {
+- bytes = read (outpipe, buf, 1024);
+-
+- if (bytes > 0)
+- gdk_pixbuf_loader_write (loader, buf, bytes, NULL);
+- if (bytes <= 0 || got_size) {
+- close (outpipe);
+- outpipe = -1;
+- gdk_pixbuf_loader_close (loader, NULL);
++ const char *page_path;
++ PixbufInfo info;
++ GError *error = NULL;
++
++ page_path = g_ptr_array_index (comics_document->page_names, page->index);
++
++ if (!archive_reopen_if_needed (comics_document, page_path, &error)) {
++ g_warning ("Fatal error opening archive: %s", error->message);
++ g_error_free (error);
++ return;
++ }
++
++ loader = gdk_pixbuf_loader_new ();
++ info.got_info = FALSE;
++ g_signal_connect (loader, "size-prepared",
++ G_CALLBACK (get_page_size_prepared_cb),
++ &info);
++
++ while (1) {
++ const char *name;
++ GError *error = NULL;
++
++ if (!ev_archive_read_next_header (comics_document->archive, &error)) {
++ if (error != NULL) {
++ g_warning ("Fatal error handling archive (%s): %s", G_STRFUNC, error->message);
++ g_error_free (error);
+ }
++ break;
+ }
+- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+- if (pixbuf) {
+- if (width)
+- *width = gdk_pixbuf_get_width (pixbuf);
+- if (height)
+- *height = gdk_pixbuf_get_height (pixbuf);
+- }
+- g_spawn_close_pid (child_pid);
+- g_object_unref (loader);
+- } else {
+- filename = g_build_filename (comics_document->dir,
+- (char *) comics_document->page_names->pdata[page->index],
+- NULL);
+- pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+- if (pixbuf) {
+- if (width)
+- *width = gdk_pixbuf_get_width (pixbuf);
+- if (height)
+- *height = gdk_pixbuf_get_height (pixbuf);
+- g_object_unref (pixbuf);
++
++ name = ev_archive_get_entry_pathname (comics_document->archive);
++ if (g_strcmp0 (name, page_path) == 0) {
++ char buf[BLOCK_SIZE];
++ gssize read;
++ gint64 left;
++
++ left = ev_archive_get_entry_size (comics_document->archive);
++ read = ev_archive_read_data (comics_document->archive, buf,
++ MIN(BLOCK_SIZE, left), &error);
++ while (read > 0 && !info.got_info) {
++ if (!gdk_pixbuf_loader_write (loader, (guchar *) buf, read, &error)) {
++ read = -1;
++ break;
++ }
++ left -= read;
++ read = ev_archive_read_data (comics_document->archive, buf,
++ MIN(BLOCK_SIZE, left), &error);
++ }
++ if (read < 0) {
++ g_warning ("Fatal error reading '%s' in archive: %s", name, error->message);
++ g_error_free (error);
++ }
++ break;
+ }
+- g_free (filename);
++ }
++
++ gdk_pixbuf_loader_close (loader, NULL);
++ g_object_unref (loader);
++
++ if (info.got_info) {
++ if (width)
++ *width = info.width;
++ if (height)
++ *height = info.height;
+ }
+ }
+
+ static void
+-get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
+- gpointer data)
++render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
++ gint width,
++ gint height,
++ EvRenderContext *rc)
+ {
+- gboolean *got_size = data;
+- *got_size = TRUE;
++ // int scaled_width, scaled_height;
++ double scale = rc->scale;
++ int w = (width * scale + 0.5);
++ int h = (height * scale + 0.5);
++
++ // ev_render_context_compute_scaled_size (rc, width, height, &scaled_width, &scaled_height);
++ gdk_pixbuf_loader_set_size (loader, w, h);
+ }
+
+ static GdkPixbuf *
+@@ -728,69 +528,68 @@ comics_document_render_pixbuf (EvDocument *document,
+ EvRenderContext *rc)
+ {
+ GdkPixbufLoader *loader;
+- GdkPixbuf *rotated_pixbuf, *tmp_pixbuf;
+- char **argv;
+- guchar buf[4096];
+- gboolean success;
+- gint outpipe = -1;
+- GPid child_pid;
+- gssize bytes;
+- gint width, height;
+- gchar *filename;
++ GdkPixbuf *tmp_pixbuf;
++ GdkPixbuf *rotated_pixbuf = NULL;
+ ComicsDocument *comics_document = COMICS_DOCUMENT (document);
++ const char *page_path;
++ GError *error = NULL;
++
++ page_path = g_ptr_array_index (comics_document->page_names, rc->page->index);
++
++ if (!archive_reopen_if_needed (comics_document, page_path, &error)) {
++ g_warning ("Fatal error opening archive: %s", error->message);
++ g_error_free (error);
++ return NULL;
++ }
+
+- if (!comics_document->decompress_tmp) {
+- argv = extract_argv (document, rc->page->index);
+- success = g_spawn_async_with_pipes (NULL, argv, NULL,
+- G_SPAWN_SEARCH_PATH |
+- G_SPAWN_STDERR_TO_DEV_NULL,
+- NULL, NULL,
+- &child_pid,
+- NULL, &outpipe, NULL, NULL);
+- g_strfreev (argv);
+- g_return_val_if_fail (success == TRUE, NULL);
+-
+- loader = gdk_pixbuf_loader_new ();
+- g_signal_connect (loader, "size-prepared",
+- G_CALLBACK (render_pixbuf_size_prepared_cb),
+- &rc->scale);
+-
+- while (outpipe >= 0) {
+- bytes = read (outpipe, buf, 4096);
+-
+- if (bytes > 0) {
+- gdk_pixbuf_loader_write (loader, buf, bytes,
+- NULL);
++ loader = gdk_pixbuf_loader_new ();
++ g_signal_connect (loader, "size-prepared",
++ G_CALLBACK (render_pixbuf_size_prepared_cb),
++ rc);
++
++ while (1) {
++ const char *name;
++
++ if (!ev_archive_read_next_header (comics_document->archive, &error)) {
++ if (error != NULL) {
++ g_warning ("Fatal error handling archive (%s): %s", G_STRFUNC, error->message);
++ g_error_free (error);
++ }
++ break;
++ }
++
++ name = ev_archive_get_entry_pathname (comics_document->archive);
++ if (g_strcmp0 (name, page_path) == 0) {
++ size_t size = ev_archive_get_entry_size (comics_document->archive);
++ char *buf;
++ ssize_t read;
++
++ buf = g_malloc (size);
++ read = ev_archive_read_data (comics_document->archive, buf, size, &error);
++ if (read <= 0) {
++ if (read < 0) {
++ g_warning ("Fatal error reading '%s' in archive: %s", name, error->message);
++ g_error_free (error);
++ } else {
++ g_warning ("Read an empty file from the archive");
++ }
+ } else {
+- close (outpipe);
+- gdk_pixbuf_loader_close (loader, NULL);
+- outpipe = -1;
++ gdk_pixbuf_loader_write (loader, (guchar *) buf, size, NULL);
+ }
++ g_free (buf);
++ gdk_pixbuf_loader_close (loader, NULL);
++ break;
+ }
+- tmp_pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+- rotated_pixbuf =
+- gdk_pixbuf_rotate_simple (tmp_pixbuf,
+- 360 - rc->rotation);
+- g_spawn_close_pid (child_pid);
+- g_object_unref (loader);
+- } else {
+- filename =
+- g_build_filename (comics_document->dir,
+- (char *) comics_document->page_names->pdata[rc->page->index],
+- NULL);
+-
+- gdk_pixbuf_get_file_info (filename, &width, &height);
+-
+- tmp_pixbuf =
+- gdk_pixbuf_new_from_file_at_size (
+- filename, width * (rc->scale) + 0.5,
+- height * (rc->scale) + 0.5, NULL);
+- rotated_pixbuf =
+- gdk_pixbuf_rotate_simple (tmp_pixbuf,
+- 360 - rc->rotation);
+- g_free (filename);
+- g_object_unref (tmp_pixbuf);
+ }
++ tmp_pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
++ if (tmp_pixbuf) {
++ if ((rc->rotation % 360) == 0)
++ rotated_pixbuf = g_object_ref (tmp_pixbuf);
++ else
++ rotated_pixbuf = gdk_pixbuf_rotate_simple (tmp_pixbuf,
++ 360 - rc->rotation);
++ }
++ g_object_unref (loader);
+ return rotated_pixbuf;
+ }
+
+@@ -802,79 +601,26 @@ comics_document_render (EvDocument *document,
+ cairo_surface_t *surface;
+
+ pixbuf = comics_document_render_pixbuf (document, rc);
++ if (!pixbuf)
++ return NULL;
+ surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+- g_object_unref (pixbuf);
+-
++ g_clear_object (&pixbuf);
+ return surface;
+ }
+
+-static void
+-render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
+- gint width,
+- gint height,
+- gpointer data)
+-{
+- double *scale = data;
+- int w = (width * (*scale) + 0.5);
+- int h = (height * (*scale) + 0.5);
+-
+- gdk_pixbuf_loader_set_size (loader, w, h);
+-}
+-
+-/**
+- * comics_remove_dir: Removes a directory recursively.
+- * Returns:
+- * 0 if it was successfully deleted,
+- * -1 if an error occurred
+- */
+-static int
+-comics_remove_dir (gchar *path_name)
+-{
+- GDir *content_dir;
+- const gchar *filename;
+- gchar *filename_with_path;
+-
+- if (g_file_test (path_name, G_FILE_TEST_IS_DIR)) {
+- content_dir = g_dir_open (path_name, 0, NULL);
+- filename = g_dir_read_name (content_dir);
+- while (filename) {
+- filename_with_path =
+- g_build_filename (path_name,
+- filename, NULL);
+- comics_remove_dir (filename_with_path);
+- g_free (filename_with_path);
+- filename = g_dir_read_name (content_dir);
+- }
+- g_dir_close (content_dir);
+- }
+- /* Note from g_remove() documentation: on Windows, it is in general not
+- * possible to remove a file that is open to some process, or mapped
+- * into memory.*/
+- return (g_remove (path_name));
+-}
+-
+ static void
+ comics_document_finalize (GObject *object)
+ {
+ ComicsDocument *comics_document = COMICS_DOCUMENT (object);
+
+- if (comics_document->decompress_tmp) {
+- if (comics_remove_dir (comics_document->dir) == -1)
+- g_warning (_("There was an error deleting “%s”."),
+- comics_document->dir);
+- g_free (comics_document->dir);
+- }
+-
+ if (comics_document->page_names) {
+ g_ptr_array_foreach (comics_document->page_names, (GFunc) g_free, NULL);
+ g_ptr_array_free (comics_document->page_names, TRUE);
+ }
+-
+- g_free (comics_document->archive);
+- g_free (comics_document->selected_command);
+- g_free (comics_document->alternative_command);
+- g_free (comics_document->extract_command);
+- g_free (comics_document->list_command);
++ g_clear_pointer (&comics_document->page_positions, g_hash_table_destroy);
++ g_clear_object (&comics_document->archive);
++ g_free (comics_document->archive_path);
++ g_free (comics_document->archive_uri);
+
+ G_OBJECT_CLASS (comics_document_parent_class)->finalize (object);
+ }
+@@ -897,33 +643,7 @@ comics_document_class_init (ComicsDocumentClass *klass)
+ static void
+ comics_document_init (ComicsDocument *comics_document)
+ {
+- comics_document->archive = NULL;
+- comics_document->page_names = NULL;
+- comics_document->extract_command = NULL;
+-}
+-
+-/* Returns a list of file extensions supported by gdk-pixbuf */
+-static GSList*
+-get_supported_image_extensions(void)
+-{
+- GSList *extensions = NULL;
+- GSList *formats = gdk_pixbuf_get_formats ();
+- GSList *l;
+-
+- for (l = formats; l != NULL; l = l->next) {
+- int i;
+- gchar **ext = gdk_pixbuf_format_get_extensions (l->data);
+-
+- for (i = 0; ext[i] != NULL; i++) {
+- extensions = g_slist_append (extensions,
+- g_strdup (ext[i]));
+- }
+-
+- g_strfreev (ext);
+- }
+-
+- g_slist_free (formats);
+- return extensions;
++ comics_document->archive = ev_archive_new ();
+ }
+
+ static GdkPixbuf *
+@@ -971,48 +691,3 @@ comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *i
+ iface->get_thumbnail = comics_document_thumbnails_get_thumbnail;
+ iface->get_dimensions = comics_document_thumbnails_get_dimensions;
+ }
+-
+-static char**
+-extract_argv (EvDocument *document, gint page)
+-{
+- ComicsDocument *comics_document = COMICS_DOCUMENT (document);
+- char **argv;
+- char *command_line, *quoted_archive, *quoted_filename;
+- GError *err = NULL;
+-
+- if (g_strrstr (comics_document->page_names->pdata[page], "--checkpoint-action="))
+- {
+- g_warning ("File unsupported\n");
+- gtk_main_quit ();
+- }
+-
+- if (page >= comics_document->page_names->len)
+- return NULL;
+-
+- if (comics_document->regex_arg) {
+- quoted_archive = g_shell_quote (comics_document->archive);
+- quoted_filename =
+- comics_regex_quote (comics_document->page_names->pdata[page]);
+- } else {
+- quoted_archive = g_shell_quote (comics_document->archive);
+- quoted_filename = g_shell_quote (comics_document->page_names->pdata[page]);
+- }
+-
+- command_line = g_strdup_printf ("%s %s %s",
+- comics_document->extract_command,
+- quoted_archive,
+- quoted_filename);
+- g_free (quoted_archive);
+- g_free (quoted_filename);
+-
+- g_shell_parse_argv (command_line, NULL, &argv, &err);
+- g_free (command_line);
+-
+- if (err) {
+- g_warning (_("Error %s"), err->message);
+- g_error_free (err);
+- return NULL;
+- }
+-
+- return argv;
+-}
+diff --git a/backend/comics/comics-document.h b/backend/comics/comics-document.h
+index f6a4b440..4417a69f 100644
+--- a/backend/comics/comics-document.h
++++ b/backend/comics/comics-document.h
+@@ -16,9 +16,9 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+-#ifndef __COMICS_DOCUMENT_H__
+-#define __COMICS_DOCUMENT_H__
++#pragma once
+
++#include "ev-macros.h"
+ #include "ev-document.h"
+
+ G_BEGIN_DECLS
+@@ -30,9 +30,8 @@ G_BEGIN_DECLS
+ typedef struct _ComicsDocument ComicsDocument;
+
+ GType comics_document_get_type (void) G_GNUC_CONST;
++GType register_atril_backend (GTypeModule *module);
+
+-G_MODULE_EXPORT GType register_atril_backend (GTypeModule *module);
+
+ G_END_DECLS
+
+-#endif /* __COMICS_DOCUMENT_H__ */
+diff --git a/backend/comics/ev-archive.c b/backend/comics/ev-archive.c
+new file mode 100644
+index 00000000..568e1621
+--- /dev/null
++++ b/backend/comics/ev-archive.c
+@@ -0,0 +1,323 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
++/*
++ * Copyright (C) 2017, Bastien Nocera <hadess@hadess.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#include "config.h"
++#include "ev-archive.h"
++
++#include <archive.h>
++#include <archive_entry.h>
++#include <gio/gio.h>
++
++#define BUFFER_SIZE (64 * 1024)
++
++struct _EvArchive {
++ GObject parent_instance;
++ EvArchiveType type;
++
++ /* libarchive */
++ struct archive *libar;
++ struct archive_entry *libar_entry;
++};
++
++G_DEFINE_TYPE(EvArchive, ev_archive, G_TYPE_OBJECT);
++
++static void
++ev_archive_finalize (GObject *object)
++{
++ EvArchive *archive = EV_ARCHIVE (object);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_clear_pointer (&archive->libar, archive_free);
++ break;
++ default:
++ break;
++ }
++
++ G_OBJECT_CLASS (ev_archive_parent_class)->finalize (object);
++}
++
++static void
++ev_archive_class_init (EvArchiveClass *klass)
++{
++ GObjectClass *object_class = (GObjectClass *) klass;
++
++ object_class->finalize = ev_archive_finalize;
++}
++
++EvArchive *
++ev_archive_new (void)
++{
++ return g_object_new (EV_TYPE_ARCHIVE, NULL);
++}
++
++static void
++libarchive_set_archive_type (EvArchive *archive,
++ EvArchiveType archive_type)
++{
++ archive->type = archive_type;
++ archive->libar = archive_read_new ();
++
++ if (archive_type == EV_ARCHIVE_TYPE_ZIP)
++ archive_read_support_format_zip (archive->libar);
++ else if (archive_type == EV_ARCHIVE_TYPE_7Z)
++ archive_read_support_format_7zip (archive->libar);
++ else if (archive_type == EV_ARCHIVE_TYPE_TAR)
++ archive_read_support_format_tar (archive->libar);
++ else if (archive_type == EV_ARCHIVE_TYPE_RAR) {
++ archive_read_support_format_rar (archive->libar);
++ archive_read_support_format_rar5 (archive->libar);
++ } else
++ g_assert_not_reached ();
++}
++
++EvArchiveType
++ev_archive_get_archive_type (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), EV_ARCHIVE_TYPE_NONE);
++
++ return archive->type;
++}
++
++gboolean
++ev_archive_set_archive_type (EvArchive *archive,
++ EvArchiveType archive_type)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type == EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ switch (archive_type) {
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ libarchive_set_archive_type (archive, archive_type);
++ break;
++ default:
++ g_assert_not_reached ();
++ }
++
++ return TRUE;
++}
++
++gboolean
++ev_archive_open_filename (EvArchive *archive,
++ const char *path,
++ GError **error)
++{
++ int r;
++
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++ g_return_val_if_fail (path != NULL, FALSE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ r = archive_read_open_filename (archive->libar, path, BUFFER_SIZE);
++ if (r != ARCHIVE_OK) {
++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ "Error opening archive: %s", archive_error_string (archive->libar));
++ return FALSE;
++ }
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
++static gboolean
++libarchive_read_next_header (EvArchive *archive,
++ GError **error)
++{
++ while (1) {
++ int r;
++
++ r = archive_read_next_header (archive->libar, &archive->libar_entry);
++ if (r != ARCHIVE_OK) {
++ if (r != ARCHIVE_EOF)
++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ "Error reading archive: %s", archive_error_string (archive->libar));
++ return FALSE;
++ }
++
++ if (archive_entry_filetype (archive->libar_entry) != AE_IFREG) {
++ g_debug ("Skipping '%s' as it's not a regular file",
++ archive_entry_pathname (archive->libar_entry));
++ continue;
++ }
++
++ g_debug ("At header for file '%s'", archive_entry_pathname (archive->libar_entry));
++
++ break;
++ }
++
++ return TRUE;
++}
++
++gboolean
++ev_archive_read_next_header (EvArchive *archive,
++ GError **error)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ return libarchive_read_next_header (archive, error);
++ }
++
++ return FALSE;
++}
++
++gboolean
++ev_archive_at_entry (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ return (archive->libar_entry != NULL);
++}
++
++const char *
++ev_archive_get_entry_pathname (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), NULL);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, NULL);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, NULL);
++ return archive_entry_pathname (archive->libar_entry);
++ }
++
++ return NULL;
++}
++
++gint64
++ev_archive_get_entry_size (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), -1);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, -1);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, -1);
++ return archive_entry_size (archive->libar_entry);
++ }
++
++ return -1;
++}
++
++gboolean
++ev_archive_get_entry_is_encrypted (EvArchive *archive)
++{
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), FALSE);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, FALSE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, -1);
++ return archive_entry_is_encrypted (archive->libar_entry);
++ }
++
++ return FALSE;
++}
++
++gssize
++ev_archive_read_data (EvArchive *archive,
++ void *buf,
++ gsize count,
++ GError **error)
++{
++ gssize r = -1;
++
++ g_return_val_if_fail (EV_IS_ARCHIVE (archive), -1);
++ g_return_val_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE, -1);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_NONE:
++ g_assert_not_reached ();
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_return_val_if_fail (archive->libar_entry != NULL, -1);
++ r = archive_read_data (archive->libar, buf, count);
++ if (r < 0) {
++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ "Failed to decompress data: %s", archive_error_string (archive->libar));
++ }
++ break;
++ }
++
++ return r;
++}
++
++void
++ev_archive_reset (EvArchive *archive)
++{
++ g_return_if_fail (EV_IS_ARCHIVE (archive));
++ g_return_if_fail (archive->type != EV_ARCHIVE_TYPE_NONE);
++
++ switch (archive->type) {
++ case EV_ARCHIVE_TYPE_RAR:
++ case EV_ARCHIVE_TYPE_ZIP:
++ case EV_ARCHIVE_TYPE_7Z:
++ case EV_ARCHIVE_TYPE_TAR:
++ g_clear_pointer (&archive->libar, archive_free);
++ libarchive_set_archive_type (archive, archive->type);
++ archive->libar_entry = NULL;
++ break;
++ default:
++ g_assert_not_reached ();
++ }
++}
++
++static void
++ev_archive_init (EvArchive *archive)
++{
++}
+diff --git a/backend/comics/ev-archive.h b/backend/comics/ev-archive.h
+new file mode 100644
+index 00000000..b4e1399c
+--- /dev/null
++++ b/backend/comics/ev-archive.h
+@@ -0,0 +1,56 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
++/*
++ * Copyright (C) 2017, Bastien Nocera <hadess@hadess.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#pragma once
++
++#include <glib-object.h>
++
++G_BEGIN_DECLS
++
++#define EV_TYPE_ARCHIVE ev_archive_get_type ()
++G_DECLARE_FINAL_TYPE (EvArchive, ev_archive, EV, ARCHIVE, GObject)
++
++typedef enum {
++ EV_ARCHIVE_TYPE_NONE = 0,
++ EV_ARCHIVE_TYPE_RAR,
++ EV_ARCHIVE_TYPE_ZIP,
++ EV_ARCHIVE_TYPE_7Z,
++ EV_ARCHIVE_TYPE_TAR
++} EvArchiveType;
++
++EvArchive *ev_archive_new (void);
++gboolean ev_archive_set_archive_type (EvArchive *archive,
++ EvArchiveType archive_type);
++EvArchiveType ev_archive_get_archive_type (EvArchive *archive);
++gboolean ev_archive_open_filename (EvArchive *archive,
++ const char *path,
++ GError **error);
++gboolean ev_archive_read_next_header (EvArchive *archive,
++ GError **error);
++gboolean ev_archive_at_entry (EvArchive *archive);
++const char *ev_archive_get_entry_pathname (EvArchive *archive);
++gint64 ev_archive_get_entry_size (EvArchive *archive);
++gboolean ev_archive_get_entry_is_encrypted (EvArchive *archive);
++gssize ev_archive_read_data (EvArchive *archive,
++ void *buf,
++ gsize count,
++ GError **error);
++void ev_archive_reset (EvArchive *archive);
++
++G_END_DECLS
+diff --git a/configure.ac b/configure.ac
+index e25de054..d5830716 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -580,8 +580,11 @@ AC_ARG_ENABLE(comics,
+ [enable_comics=$enableval],
+ [enable_comics=yes])
+
++COMICS_DEPS="libarchive"
+ if test "x$enable_comics" = "xyes"; then
+ AC_DEFINE([ENABLE_COMICS], [1], [Enable support for comics.])
++ PKG_CHECK_MODULES([COMICS], [$COMICS_DEPS])
++ AC_SUBST(COMICS_LIBS)
+ fi
+ AM_CONDITIONAL(ENABLE_COMICS, test x$enable_comics = xyes)
+
+diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h
+index 67f53abb..8f54e6b5 100644
+--- a/libdocument/ev-document.h
++++ b/libdocument/ev-document.h
+@@ -59,6 +59,7 @@ typedef struct _EvDocumentPrivate EvDocumentPrivate;
+ typedef enum
+ {
+ EV_DOCUMENT_ERROR_INVALID,
++ EV_DOCUMENT_ERROR_UNSUPPORTED_CONTENT,
+ EV_DOCUMENT_ERROR_ENCRYPTED
+ } EvDocumentError;
+
+--
+2.39.2
+
diff -Nru atril-1.26.0/debian/patches/series atril-1.26.0/debian/patches/series
--- atril-1.26.0/debian/patches/series 2024-01-06 07:18:28.000000000 +0100
+++ atril-1.26.0/debian/patches/series 2024-01-23 10:06:53.000000000 +0100
@@ -3,3 +3,5 @@
0001-Accessibility-add-button-description.patch
0003-epub-Fix-index-loading-for-certain-documents-look-fo.patch
0004-epub-add-fallback-for-malformed-epub-files-in-check_.patch
+0005-Use-a-blank-line-at-most.patch
+0006-comics-Use-libarchive-to-unpack-documents.patch
Reply to: