summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--atril-view.h1
-rw-r--r--backend/Makefile.am4
-rw-r--r--backend/epub/Makefile.am37
-rw-r--r--backend/epub/epub-document.c1391
-rw-r--r--backend/epub/epub-document.h21
-rw-r--r--backend/epub/epubdocument.atril-backend.in4
-rw-r--r--backend/epub/minizip/Makefile.am14
-rw-r--r--backend/epub/minizip/ioapi.c247
-rw-r--r--backend/epub/minizip/ioapi.h208
-rw-r--r--backend/epub/minizip/unzip.c2125
-rw-r--r--backend/epub/minizip/unzip.h437
-rw-r--r--configure.ac49
-rw-r--r--help/reference/shell/Makefile.am2
-rw-r--r--libdocument/ev-document-find.c9
-rw-r--r--libdocument/ev-document-find.h9
-rw-r--r--libdocument/ev-document-thumbnails.c3
-rw-r--r--libdocument/ev-document-thumbnails.h4
-rw-r--r--libdocument/ev-document.c70
-rw-r--r--libdocument/ev-document.h5
-rw-r--r--libdocument/ev-link-dest.c10
-rw-r--r--libdocument/ev-link-dest.h2
-rw-r--r--libview/Makefile.am6
-rw-r--r--libview/ev-document-model.c16
-rw-r--r--libview/ev-document-model.h4
-rw-r--r--libview/ev-jobs.c205
-rw-r--r--libview/ev-jobs.h13
-rwxr-xr-x[-rw-r--r--]libview/ev-view.c38
-rwxr-xr-x[-rw-r--r--]libview/ev-view.h2
-rw-r--r--libview/ev-web-view.c874
-rw-r--r--libview/ev-web-view.h89
-rw-r--r--previewer/Makefile.am6
-rw-r--r--shell/Makefile.am4
-rw-r--r--shell/ev-convert-metadata.c4
-rw-r--r--shell/ev-sidebar-thumbnails.c26
-rw-r--r--shell/ev-window.c421
35 files changed, 6211 insertions, 149 deletions
diff --git a/atril-view.h b/atril-view.h
index b9261c97..7ed8898a 100644
--- a/atril-view.h
+++ b/atril-view.h
@@ -26,6 +26,7 @@
#include <libview/ev-document-model.h>
#include <libview/ev-print-operation.h>
#include <libview/ev-view.h>
+#include <libview/ev-web-view.h>
#include <libview/ev-view-type-builtins.h>
#include <libview/ev-stock-icons.h>
diff --git a/backend/Makefile.am b/backend/Makefile.am
index ef76c4ee..49bfdf6a 100644
--- a/backend/Makefile.am
+++ b/backend/Makefile.am
@@ -6,6 +6,10 @@ if ENABLE_PDF
SUBDIRS += pdf
endif
+if ENABLE_EPUB
+SUBDIRS += epub
+endif
+
if ENABLE_PS
SUBDIRS += ps
endif
diff --git a/backend/epub/Makefile.am b/backend/epub/Makefile.am
new file mode 100644
index 00000000..31dd455e
--- /dev/null
+++ b/backend/epub/Makefile.am
@@ -0,0 +1,37 @@
+SUBDIRS = minizip
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/libdocument \
+ -I$(srcdir)/minizip \
+ -DMATELOCALEDIR=\"$(datadir)/locale\" \
+ -DATRIL_COMPILATION \
+ $(BACKEND_CFLAGS) \
+ $(WARN_CXXFLAGS) \
+ $(WEBKIT_CFLAGS) \
+ $(DISABLE_DEPRECATED)
+
+backend_LTLIBRARIES = libepubdocument.la
+
+libepubdocument_la_SOURCES = \
+ epub-document.c \
+ epub-document.h
+
+libepubdocument_la_LDFLAGS = $(BACKEND_LIBTOOL_FLAGS)
+libepubdocument_la_LIBADD = \
+ $(top_builddir)/libdocument/libatrildocument.la \
+ minizip/libminizip.la \
+ $(WEBKIT_LIBS) \
+ $(BACKEND_LIBS)
+
+
+backend_in_files = epubdocument.atril-backend.in
+backend_DATA = $(backend_in_files:.atril-backend.in=.atril-backend)
+
+EXTRA_DIST = $(backend_in_files)
+
+CLEANFILES = $(backend_DATA)
+
+@EV_INTLTOOL_ATRIL_BACKEND_RULE@
+
+-include $(top_srcdir)/git.mk
diff --git a/backend/epub/epub-document.c b/backend/epub/epub-document.c
new file mode 100644
index 00000000..d0dce118
--- /dev/null
+++ b/backend/epub/epub-document.c
@@ -0,0 +1,1391 @@
+/* this file is part of atril, a mate document viewer
+ *
+ * Copyright (C) 2014 Avishkar Gupta
+ *
+ * Author:
+ * Avishkar Gupta <[email protected]>
+ *
+ * Atril 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Atril 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 "epub-document.h"
+#include "ev-file-helpers.h"
+#include "unzip.h"
+#include "ev-document-thumbnails.h"
+#include "ev-document-find.h"
+#include "ev-document-links.h"
+#include "ev-document-misc.h"
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/HTMLparser.h>
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include <gtk/gtk.h>
+
+/*For strcasestr(),strstr()*/
+#include <string.h>
+
+typedef enum _xmlParseReturnType
+{
+ XML_ATTRIBUTE,
+ XML_KEYWORD
+}xmlParseReturnType;
+
+typedef struct _contentListNode {
+ gchar* key ;
+ gchar* value ;
+ gint index ;
+}contentListNode;
+
+typedef struct _linknode {
+ gchar *pagelink;
+ gchar *linktext;
+ guint page;
+}linknode;
+
+typedef struct _EpubDocumentClass EpubDocumentClass;
+
+struct _EpubDocumentClass
+{
+ EvDocumentClass parent_class;
+};
+
+struct _EpubDocument
+{
+ EvDocument parent_instance;
+ /*Stores the path to the source archive*/
+ gchar* archivename ;
+ /*Stores the path of the directory where we unzipped the epub*/
+ gchar* tmp_archive_dir ;
+ /*Stores the contentlist in a sorted manner*/
+ GList* contentList ;
+ /* A variable to hold our epubDocument for unzipping*/
+ unzFile epubDocument ;
+ /*The (sub)directory that actually houses the document*/
+ gchar* documentdir;
+ /*Stores the table of contents*/
+ GList *index;
+ /*Document title, for the sidebar links*/
+ gchar *docTitle;
+};
+
+static void epub_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
+static void epub_document_document_find_iface_init (EvDocumentFindInterface *iface);
+static void epub_document_document_links_iface_init (EvDocumentLinksInterface *iface);
+
+EV_BACKEND_REGISTER_WITH_CODE (EpubDocument, epub_document,
+ {
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+ epub_document_document_thumbnails_iface_init);
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
+ epub_document_document_find_iface_init);
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
+ epub_document_document_links_iface_init);
+
+ } );
+
+static void
+epub_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
+ EvRenderContext *rc,
+ gint *width,
+ gint *height)
+{
+ gdouble page_width, page_height;
+
+ page_width = 800;
+ page_height = 1080;
+
+ *width = MAX ((gint)(page_width * rc->scale + 0.5), 1);
+ *height = MAX ((gint)(page_height * rc->scale + 0.5), 1);
+}
+
+static GdkPixbuf *
+epub_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
+ EvRenderContext *rc,
+ gboolean border)
+{
+ cairo_surface_t *webpage;
+ GdkPixbuf *thumbnailpix = NULL ;
+ gint width,height;
+ epub_document_thumbnails_get_dimensions(document,rc,&width,&height);
+ webpage = ev_document_misc_surface_rotate_and_scale(rc->page->backend_page,width,height,0);
+ thumbnailpix = ev_document_misc_pixbuf_from_surface(webpage);
+ return thumbnailpix;
+}
+
+static gboolean
+in_tag(const char* found)
+{
+ const char* bracket = found ;
+
+ /* Since the dump started with the body tag, the '<' will be the first
+ * character in the haystack.
+ */
+ while (*bracket != '<') {
+ bracket--;
+ if (*bracket == '>') {
+ /*We encounted a close brace before an open*/
+ return FALSE ;
+ }
+ }
+
+ return TRUE;
+}
+
+static int
+get_substr_count(const char * haystack,const char *needle,gboolean case_sensitive)
+{
+ const char* tmp = haystack ;
+ char* (*string_compare_function)(const char*,const char*);
+ int count=0;
+ if (case_sensitive) {
+ string_compare_function = strstr ;
+ }
+ else {
+ string_compare_function = strcasestr;
+ }
+
+ while ((tmp=string_compare_function(tmp,needle))) {
+ if (!in_tag(tmp)) {
+ count++;
+ }
+ tmp = tmp + strlen(needle);
+ }
+
+ return count;
+}
+
+static guint
+epub_document_check_hits(EvDocumentFind *document_find,
+ EvPage *page,
+ const gchar *text,
+ gboolean case_sensitive)
+{
+ gchar *filepath = g_filename_from_uri((gchar*)page->backend_page,NULL,NULL);
+ htmlDocPtr htmldoc = xmlParseFile(filepath);
+ htmlNodePtr htmltag = xmlDocGetRootElement(htmldoc);
+ int count=0;
+ htmlNodePtr bodytag = htmltag->xmlChildrenNode;
+
+ while ( xmlStrcmp(bodytag->name,(xmlChar*)"body") ) {
+ bodytag = bodytag->next;
+ }
+
+ xmlBufferPtr bodybuffer = xmlBufferCreate();
+ xmlNodeDump(bodybuffer,htmldoc,bodytag,0,1);
+
+ count = get_substr_count((char*)bodybuffer->content,text,case_sensitive);
+
+ xmlBufferFree(bodybuffer);
+ xmlFreeDoc(htmldoc);
+
+ return count;
+}
+
+static gboolean
+epub_document_links_has_document_links(EvDocumentLinks *document_links)
+{
+ EpubDocument *epub_document = EPUB_DOCUMENT(document_links);
+
+ g_return_if_fail(EPUB_IS_DOCUMENT(epub_document));
+
+ if (!epub_document->index)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+typedef struct _LinksCBStruct {
+ GtkTreeModel *model;
+ GtkTreeIter *parent;
+}LinksCBStruct;
+
+static void
+epub_document_make_tree_entry(linknode* ListData,LinksCBStruct* UserData)
+{
+ GtkTreeIter tree_iter;
+ EvLink *link = NULL;
+ gboolean expand;
+ char *title_markup;
+
+ //These are all children of the document title, and have no chlidren nodes
+ expand = FALSE;
+
+ EvLinkDest *ev_dest = NULL;
+ EvLinkAction *ev_action;
+
+ /* We shall use a EV_LINK_DEST_TYPE_PAGE for page links,
+ * and a EV_LINK_DEST_TYPE_HLINK(custom) for refs on a page of type url#label
+ * because we need both dest and page label for this.
+ */
+
+ if (g_strrstr(ListData->pagelink,"#") == NULL) {
+ ev_dest = ev_link_dest_new_page(ListData->page);
+ }
+ else {
+ ev_dest = ev_link_dest_new_hlink((gchar*)ListData->pagelink,ListData->page);
+ }
+
+ ev_action = ev_link_action_new_dest (ev_dest);
+
+ link = ev_link_new((gchar*)ListData->linktext,ev_action);
+
+ gtk_tree_store_append (GTK_TREE_STORE (UserData->model), &tree_iter,(UserData->parent));
+ title_markup = g_strdup((gchar*)ListData->linktext);
+
+ gtk_tree_store_set (GTK_TREE_STORE (UserData->model), &tree_iter,
+ EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, link,
+ EV_DOCUMENT_LINKS_COLUMN_EXPAND, expand,
+ -1);
+
+ g_free (title_markup);
+ g_object_unref (link);
+}
+
+static GtkTreeModel *
+epub_document_links_get_links_model(EvDocumentLinks *document_links)
+{
+ GtkTreeModel *model = NULL;
+
+ g_return_val_if_fail (EPUB_IS_DOCUMENT (document_links), NULL);
+
+ EpubDocument *epub_document = EPUB_DOCUMENT(document_links);
+
+ model = (GtkTreeModel*) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_OBJECT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING);
+
+ LinksCBStruct linkStruct;
+ linkStruct.model = model;
+ EvLink *link = ev_link_new(epub_document->docTitle,
+ ev_link_action_new_dest(ev_link_dest_new_page(0)));
+ GtkTreeIter parent;
+
+ linkStruct.parent = &parent;
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent,NULL);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
+ EV_DOCUMENT_LINKS_COLUMN_MARKUP, epub_document->docTitle,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, link,
+ EV_DOCUMENT_LINKS_COLUMN_EXPAND, TRUE,
+ -1);
+
+ g_object_unref(link);
+
+ if (epub_document->index) {
+ g_list_foreach (epub_document->index,(GFunc)epub_document_make_tree_entry,&linkStruct);
+ }
+
+ return model;
+}
+
+static void
+epub_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface)
+{
+ iface->get_thumbnail = epub_document_thumbnails_get_thumbnail;
+ iface->get_dimensions = epub_document_thumbnails_get_dimensions;
+}
+
+static void
+epub_document_document_find_iface_init (EvDocumentFindInterface *iface)
+{
+ iface->check_for_hits = epub_document_check_hits;
+}
+
+static void
+epub_document_document_links_iface_init(EvDocumentLinksInterface *iface)
+{
+ iface->has_document_links = epub_document_links_has_document_links;
+ iface->get_links_model = epub_document_links_get_links_model;
+}
+
+static gboolean
+epub_document_save (EvDocument *document,
+ const char *uri,
+ GError **error)
+{
+ EpubDocument *epub_document = EPUB_DOCUMENT (document);
+
+ return ev_xfer_uri_simple (epub_document->archivename, uri, error);
+}
+
+static int
+epub_document_get_n_pages (EvDocument *document)
+{
+ EpubDocument *epub_document = EPUB_DOCUMENT (document);
+
+ if (epub_document-> contentList == NULL)
+ return 0;
+
+ return g_list_length(epub_document->contentList);
+}
+
+/**
+ * epub_remove_temporary_dir : Removes a directory recursively.
+ * This function is same as comics_remove_temporary_dir
+ * Returns:
+ * 0 if it was successfully deleted,
+ * -1 if an error occurred
+ */
+static int
+epub_remove_temporary_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);
+ epub_remove_temporary_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 gboolean
+check_mime_type (const gchar* uri,
+ GError** error);
+
+static gboolean
+open_xml_document (const gchar* filename);
+
+static gboolean
+set_xml_root_node (xmlChar* rootname);
+
+static xmlNodePtr
+xml_get_pointer_to_node (xmlChar* parserfor,
+ xmlChar* attributename,
+ xmlChar* attributevalue);
+static void
+xml_parse_children_of_node (xmlNodePtr parent,
+ xmlChar* parserfor,
+ xmlChar* attributename,
+ xmlChar* attributevalue);
+
+static gboolean
+xml_check_attribute_value (xmlNode* node,
+ xmlChar * attributename,
+ xmlChar* attributevalue);
+
+static xmlChar*
+xml_get_data_from_node (xmlNodePtr node,
+ xmlParseReturnType rettype,
+ xmlChar* attributename);
+
+static void
+xml_free_doc();
+
+static void
+free_tree_nodes (gpointer data);
+
+/*Global variables for XML parsing*/
+static xmlDocPtr xmldocument ;
+static xmlNodePtr xmlroot ;
+static xmlNodePtr xmlretval ;
+
+/*
+**Functions to parse the xml files.
+**Open a XML document for reading
+*/
+static gboolean
+open_xml_document ( const gchar* filename )
+{
+ xmldocument = xmlParseFile(filename);
+
+ if ( xmldocument == NULL )
+ {
+ return FALSE ;
+ }
+ else
+ {
+ return TRUE ;
+ }
+}
+
+/**
+ *Check if the root value is same as rootname .
+ *if supplied rootvalue = NULL ,just set root to rootnode .
+**/
+static gboolean
+set_xml_root_node(xmlChar* rootname)
+{
+ xmlroot = xmlDocGetRootElement(xmldocument);
+
+ if (xmlroot == NULL) {
+
+ xmlFreeDoc(xmldocument);
+ return FALSE;
+ }
+
+ if ( rootname == NULL )
+ {
+ return TRUE ;
+ }
+
+ if ( !xmlStrcmp(xmlroot->name,rootname))
+ {
+ return TRUE ;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static xmlNodePtr
+xml_get_pointer_to_node(xmlChar* parserfor,
+ xmlChar* attributename,
+ xmlChar* attributevalue )
+{
+ xmlNodePtr topchild,children ;
+
+ xmlretval = NULL ;
+
+ if ( !xmlStrcmp( xmlroot->name, parserfor) )
+ {
+ return xmlroot ;
+ }
+
+ topchild = xmlroot->xmlChildrenNode ;
+
+ while ( topchild != NULL )
+ {
+ if ( !xmlStrcmp(topchild->name,parserfor) )
+ {
+ if ( xml_check_attribute_value(topchild,attributename,attributevalue) == TRUE )
+ {
+ xmlretval = topchild;
+ return xmlretval;
+ }
+ else
+ {
+ /*No need to parse children node*/
+ topchild = topchild->next ;
+ continue ;
+ }
+ }
+
+ xml_parse_children_of_node(topchild , parserfor, attributename, attributevalue) ;
+
+ topchild = topchild->next ;
+ }
+
+ return xmlretval ;
+}
+
+static void
+xml_parse_children_of_node(xmlNodePtr parent,
+ xmlChar* parserfor,
+ xmlChar* attributename,
+ xmlChar* attributevalue )
+{
+ xmlNodePtr child = parent->xmlChildrenNode ;
+
+ while ( child != NULL )
+ {
+ if ( !xmlStrcmp(child->name,parserfor))
+ {
+ if ( xml_check_attribute_value(child,attributename,attributevalue) == TRUE )
+ {
+ xmlretval = child;
+ return ;
+ }
+ else
+ {
+ /*No need to parse children node*/
+ child = child->next ;
+ continue ;
+ }
+ }
+
+ /*return already if we have xmlretval set*/
+ if ( xmlretval != NULL )
+ {
+ return ;
+ }
+
+ xml_parse_children_of_node(child,parserfor,attributename,attributevalue) ;
+ child = child->next ;
+ }
+}
+
+static void
+xml_free_doc()
+{
+ xmlFreeDoc(xmldocument);
+ xmldocument = NULL;
+}
+
+static gboolean
+xml_check_attribute_value(xmlNode* node,
+ xmlChar * attributename,
+ xmlChar* attributevalue)
+{
+ xmlChar* attributefromfile ;
+ if ( attributename == NULL || attributevalue == NULL )
+ {
+ return TRUE ;
+ }
+ else if ( !xmlStrcmp(( attributefromfile = xmlGetProp(node,attributename)),
+ attributevalue) )
+ {
+ xmlFree(attributefromfile);
+ return TRUE ;
+ }
+ xmlFree(attributefromfile);
+ return FALSE ;
+}
+
+static xmlChar*
+xml_get_data_from_node(xmlNodePtr node,
+ xmlParseReturnType rettype,
+ xmlChar* attributename)
+{
+ xmlChar* datastring ;
+ if ( rettype == XML_ATTRIBUTE )
+ datastring= xmlGetProp(node,attributename);
+ else
+ datastring= xmlNodeListGetString(xmldocument,node->xmlChildrenNode, 1);
+
+ return datastring;
+}
+
+static gboolean
+check_mime_type(const gchar* uri,GError** error)
+{
+ GError * err = NULL ;
+ const gchar* mimeFromFile = ev_file_get_mime_type(uri,FALSE,&err);
+
+ gchar* mimetypes[] = {"application/epub+zip","application/x-booki+zip"};
+ int typecount = 2;
+ 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 ) {
+ 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;
+ }
+}
+
+static gboolean
+extract_one_file(EpubDocument* epub_document,GError ** error)
+{
+ GFile * outfile ;
+ gsize writesize = 0;
+ GString * gfilepath ;
+ unz_file_info64 info ;
+ gchar* directory;
+ GString* dir_create;
+ GFileOutputStream * outstream ;
+ gpointer currentfilename = g_malloc0(512);
+ gpointer buffer = g_malloc0(512);
+ gchar* createdirnametemp = NULL ;
+ gchar* createdirname = NULL;
+ if ( unzOpenCurrentFile(epub_document->epubDocument) != UNZ_OK )
+ {
+ return FALSE ;
+ }
+
+ unzGetCurrentFileInfo64(epub_document->epubDocument,&info,currentfilename,512,NULL,0,NULL,0) ;
+ directory = g_strrstr(currentfilename,"/") ;
+
+ if ( directory != NULL )
+ directory++;
+
+ gfilepath = g_string_new(epub_document->tmp_archive_dir) ;
+ g_string_append_printf(gfilepath,"/%s",(gchar*)currentfilename);
+
+ /*if we encounter a directory, make a directory inside our temporary folder.*/
+ if (directory != NULL && *directory == '\0')
+ {
+ g_mkdir(gfilepath->str,0777);
+ unzCloseCurrentFile (epub_document->epubDocument) ;
+ g_string_free(gfilepath,TRUE);
+ g_free(currentfilename);
+ g_free(buffer);
+ return TRUE;
+ }
+ else if (directory != NULL && *directory != '\0' ) {
+ gchar* createdir = currentfilename;
+ /*Since a substring can't be longer than the parent string, allocating space equal to the parent's size should suffice*/
+ createdirname = g_malloc0(strlen(currentfilename));
+ /* Add the name of the directory and subdiectories,if any to a buffer and then create it */
+ createdirnametemp = createdirname;
+ while ( createdir != directory ) {
+ (*createdirnametemp) = (*createdir);
+ createdirnametemp++;
+ createdir++;
+ }
+ (*createdirnametemp) = '\0';
+ dir_create = g_string_new(epub_document->tmp_archive_dir);
+ g_string_append_printf(dir_create,"/%s",createdirname);
+ g_mkdir_with_parents(dir_create->str,0777);
+ g_string_free(dir_create,TRUE);
+ }
+
+ outfile = g_file_new_for_path(gfilepath->str);
+ outstream = g_file_create(outfile,G_FILE_CREATE_PRIVATE,NULL,error);
+ while ( (writesize = unzReadCurrentFile(epub_document->epubDocument,buffer,512) ) != 0 )
+ {
+ if ( g_output_stream_write((GOutputStream*)outstream,buffer,writesize,NULL,error) == -1 )
+ {
+ return FALSE ;
+ }
+ }
+ g_output_stream_close((GOutputStream*)outstream,NULL,error);
+ g_object_unref(outfile) ;
+ g_object_unref(outstream) ;
+
+ unzCloseCurrentFile (epub_document->epubDocument) ;
+ g_string_free(gfilepath,TRUE);
+ g_free(currentfilename);
+ g_free(buffer);
+ if ( createdirname != NULL) {
+ g_free(createdirname);
+ }
+ return TRUE;
+}
+
+static gboolean
+extract_epub_from_container (const gchar* uri,
+ EpubDocument *epub_document,
+ GError ** error)
+{
+ GError* err = NULL ;
+ GString * temporary_sub_directory ;
+ epub_document->archivename = g_filename_from_uri(uri,NULL,error);
+ gchar* epubfilename ;
+ if ( !epub_document->archivename )
+ {
+ if (err) {
+ g_propagate_error (error, err);
+ }
+ else {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not retrieve filename"));
+ }
+ return FALSE ;
+ }
+
+ epubfilename = g_strrstr(epub_document->archivename,"/");
+ if ( *epubfilename == '/' )
+ epubfilename++ ;
+
+ temporary_sub_directory = g_string_new( epubfilename );
+ g_string_append(temporary_sub_directory,"XXXXXX") ;
+
+ epub_document->tmp_archive_dir = ev_mkdtemp(temporary_sub_directory->str,error) ;
+
+ if (!epub_document->tmp_archive_dir) {
+ return FALSE ;
+ }
+
+ g_string_free(temporary_sub_directory,TRUE);
+
+ epub_document->epubDocument = unzOpen64(epub_document->archivename);
+
+ if ( epub_document->epubDocument == NULL )
+ {
+ if (err) {
+ g_propagate_error (error, err);
+ }
+ else {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not open archive"));
+ }
+ return FALSE ;
+ }
+ if ( unzGoToFirstFile(epub_document->epubDocument) != UNZ_OK )
+ {
+ if (err) {
+ g_propagate_error (error, err);
+ }
+ else {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not extract archive"));
+ }
+ return FALSE ;
+ }
+ while ( TRUE )
+ {
+ if ( extract_one_file(epub_document,&err) == FALSE )
+ {
+ if (err) {
+ g_propagate_error (error, err);
+ }
+ else {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not extract archive"));
+ }
+ return FALSE;
+ }
+
+ if ( unzGoToNextFile(epub_document->epubDocument) == UNZ_END_OF_LIST_OF_FILE )
+ break ;
+ }
+
+ unzClose(epub_document->epubDocument);
+ return TRUE ;
+}
+
+static gchar*
+get_uri_to_content(const gchar* uri,GError ** error,EpubDocument *epub_document)
+{
+ gchar* tmp_archive_dir = epub_document->tmp_archive_dir;
+ GError * err = NULL ;
+ gchar* containerpath = g_filename_from_uri(uri,NULL,&err);
+ GString* absolutepath ;
+ gchar* content_uri ;
+ xmlNodePtr rootfileNode ;
+ xmlChar* relativepath;
+ gchar* directorybuffer = g_malloc0(sizeof(gchar*)*100);
+
+ if ( !containerpath )
+ {
+ if (err) {
+ g_propagate_error (error,err);
+ }
+ else {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not retrieve container file"));
+ }
+ return NULL ;
+ }
+
+ if ( open_xml_document(containerpath) == FALSE )
+ {
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not open container file"));
+
+ return NULL ;
+ }
+
+ if ( set_xml_root_node((xmlChar*)"container") == FALSE) {
+
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("container file is corrupt"));
+ return NULL ;
+ }
+
+ if ( (rootfileNode = xml_get_pointer_to_node((xmlChar*)"rootfile",(xmlChar*)"media-type",(xmlChar*)"application/oebps-package+xml")) == NULL)
+ {
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("epub file is invalid or corrput"));
+ return NULL ;
+ }
+
+ relativepath = xml_get_data_from_node(rootfileNode,XML_ATTRIBUTE,(xmlChar*)"full-path") ;
+ if ( relativepath == NULL )
+ {
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("epub file is corrupt,no container"));
+ return NULL ;
+ }
+ absolutepath = g_string_new(tmp_archive_dir);
+ gchar* documentfolder = g_strrstr((gchar*)relativepath,"/");
+ if (documentfolder != NULL) {
+ gchar* copybuffer = (gchar*)relativepath ;
+ gchar* writer = directorybuffer;
+
+ while(copybuffer != documentfolder) {
+ (*writer) = (*copybuffer);
+ writer++;copybuffer++;
+ }
+ *writer = '\0';
+ GString *documentdir = g_string_new(tmp_archive_dir);
+ g_string_append_printf(documentdir,"/%s",directorybuffer);
+ epub_document->documentdir = g_strdup(documentdir->str);
+
+ g_string_free(documentdir,TRUE);
+ }
+ else
+ {
+ epub_document->documentdir = g_strdup(tmp_archive_dir);
+ }
+
+ g_string_append_printf(absolutepath,"/%s",relativepath);
+ content_uri = g_filename_to_uri(absolutepath->str,NULL,&err);
+ if ( !content_uri ) {
+ if (err) {
+ g_propagate_error (error,err);
+ }
+ else {
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not retrieve container file"));
+ }
+ return NULL ;
+ }
+ g_string_free(absolutepath,TRUE);
+ g_free(directorybuffer);
+ xml_free_doc();
+ return content_uri ;
+}
+
+static gboolean
+link_present_on_page(const gchar* link,const gchar *page_uri)
+{
+ if (g_strrstr(link, page_uri)) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+static GList*
+setup_document_content_list(const gchar* content_uri, GError** error,gchar *documentdir,GList *docindex)
+{
+ GList* newlist = NULL ;
+ GError * err = NULL ;
+ gint indexcounter= 1;
+ xmlNodePtr manifest,spine,itemrefptr,itemptr ;
+ gboolean errorflag = FALSE;
+ GList *indexcopy = docindex,*indexcopyiter = docindex;
+ gchar* relativepath ;
+ GString* absolutepath = g_string_new(NULL);
+
+ if ( open_xml_document(content_uri) == FALSE )
+ {
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("could not parse content manifest"));
+
+ return FALSE ;
+ }
+ if ( set_xml_root_node((xmlChar*)"package") == FALSE) {
+
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("content file is invalid"));
+ return FALSE ;
+ }
+
+ if ( ( spine = xml_get_pointer_to_node((xmlChar*)"spine",NULL,NULL) )== NULL )
+ {
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("epub file has no spine"));
+ return FALSE ;
+ }
+
+ if ( ( manifest = xml_get_pointer_to_node((xmlChar*)"manifest",NULL,NULL) )== NULL )
+ {
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("epub file has no manifest"));
+ return FALSE ;
+ }
+
+ xmlretval = NULL ;
+
+ /*Get first instance of itemref from the spine*/
+ xml_parse_children_of_node(spine,(xmlChar*)"itemref",NULL,NULL);
+
+ if ( xmlretval != NULL )
+ itemrefptr = xmlretval ;
+ else
+ {
+ errorflag=TRUE;
+ }
+ /*Parse the spine for remaining itemrefs*/
+ do
+ {
+ indexcopyiter = indexcopy ;
+ /*for the first time that we enter the loop, if errorflag is set we break*/
+ if ( errorflag )
+ {
+ break;
+ }
+ if ( xmlStrcmp(itemrefptr->name,(xmlChar*)"itemref") == 0)
+ {
+ contentListNode* newnode = g_malloc0(sizeof(newnode));
+ newnode->key = (gchar*)xml_get_data_from_node(itemrefptr,XML_ATTRIBUTE,(xmlChar*)"idref");
+ if ( newnode->key == NULL )
+ {
+ errorflag =TRUE;
+ break;
+ }
+ xmlretval=NULL ;
+ xml_parse_children_of_node(manifest,(xmlChar*)"item",(xmlChar*)"id",(xmlChar*)newnode->key);
+
+ if ( xmlretval != NULL )
+ {
+ itemptr = xmlretval ;
+ }
+ else
+ {
+ errorflag=TRUE;
+ break;
+ }
+ relativepath = (gchar*)xml_get_data_from_node(itemptr,XML_ATTRIBUTE,(xmlChar*)"href");
+ g_string_assign(absolutepath,documentdir);
+ g_string_append_printf(absolutepath,"/%s",relativepath);
+ newnode->value = g_filename_to_uri(absolutepath->str,NULL,&err);
+ if ( newnode->value == NULL )
+ {
+ errorflag =TRUE;
+ break;
+ }
+
+ newnode->index = indexcounter++ ;
+
+ /* NOTE:Because the TOC is not always in a sorted manner, we need to check all remaining pages every time.
+ */
+ while (indexcopyiter != NULL) {
+ linknode *linkdata = indexcopyiter->data;
+
+ if (link_present_on_page(linkdata->pagelink,newnode->value)) {
+ linkdata->page = newnode->index - 1;
+ indexcopy = indexcopy->next;
+ }
+ indexcopyiter = indexcopyiter->next;
+ }
+
+ newlist = g_list_prepend(newlist,newnode);
+ }
+ itemrefptr = itemrefptr->next ;
+ }
+ while ( itemrefptr != NULL );
+
+ if ( errorflag )
+ {
+ if ( err )
+ {
+ g_propagate_error(error,err);
+ }
+ else
+ {
+ g_set_error_literal(error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("Could not set up document tree for loading, some files missing"));
+ }
+ /*free any nodes that were set up and return empty*/
+ g_string_free(absolutepath,TRUE);
+ g_list_free_full(newlist,(GDestroyNotify)free_tree_nodes);
+ return NULL ;
+ }
+ newlist = g_list_reverse(newlist);
+ g_string_free(absolutepath,TRUE);
+ xml_free_doc();
+ return newlist ;
+
+}
+
+/* Callback function to free the contentlist.*/
+static void
+free_tree_nodes(gpointer data)
+{
+ contentListNode* dataptr = data ;
+ g_free(dataptr->value);
+ g_free(dataptr->key);
+ g_free(dataptr);
+}
+
+static void
+free_link_nodes(gpointer data)
+{
+ linknode* dataptr = data ;
+ g_free(dataptr->pagelink);
+ g_free(dataptr->linktext);
+ g_free(dataptr);
+}
+
+static gchar*
+get_toc_file_name(gchar *containeruri)
+{
+ gchar *containerfilename = g_filename_from_uri(containeruri,NULL,NULL);
+
+ open_xml_document(containerfilename);
+
+ set_xml_root_node(NULL);
+
+ xmlNodePtr manifest = xml_get_pointer_to_node((xmlChar*)"manifest",NULL,NULL);
+ xmlNodePtr spine = xml_get_pointer_to_node((xmlChar*)"spine",NULL,NULL);
+
+ xmlChar *ncx = xml_get_data_from_node(spine,XML_ATTRIBUTE,(xmlChar*)"toc");
+ xmlretval = NULL;
+ xml_parse_children_of_node(manifest,(xmlChar*)"item",(xmlChar*)"id",ncx);
+
+ gchar* tocfilename = (gchar*)xml_get_data_from_node(xmlretval,XML_ATTRIBUTE,(xmlChar*)"href");
+ xml_free_doc();
+
+ return tocfilename;
+}
+
+static GList*
+setup_document_index(EpubDocument *epub_document,gchar *containeruri)
+{
+ GString *tocpath = g_string_new(epub_document->documentdir);
+ gchar *tocfilename = get_toc_file_name(containeruri);
+ GList *index = NULL;
+ g_string_append_printf (tocpath,"/%s",tocfilename);
+ GString *pagelink;
+ open_xml_document(tocpath->str);
+ g_string_free(tocpath,TRUE);
+ set_xml_root_node((xmlChar*)"ncx");
+
+ xmlNodePtr docTitle = xml_get_pointer_to_node((xmlChar*)"docTitle",NULL,NULL);
+ xmlretval = NULL;
+ xml_parse_children_of_node(docTitle,(xmlChar*)"text",NULL,NULL);
+
+ while (epub_document->docTitle == NULL && xmlretval != NULL) {
+ epub_document->docTitle = (gchar*)xml_get_data_from_node(xmlretval,XML_KEYWORD,NULL);
+ xmlretval = xmlretval->next;
+ }
+ xmlNodePtr navMap = xml_get_pointer_to_node((xmlChar*)"navMap",NULL,NULL);
+ xmlretval = NULL;
+ xml_parse_children_of_node(navMap,(xmlChar*)"navPoint",NULL,NULL);
+
+ xmlNodePtr navPoint = xmlretval;
+
+ do {
+
+ if ( !xmlStrcmp(navPoint->name,(xmlChar*)"navPoint")) {
+ xmlretval = NULL;
+ xml_parse_children_of_node(navPoint,(xmlChar*)"navLabel",NULL,NULL);
+ xmlNodePtr navLabel = xmlretval;
+ xmlretval = NULL;
+ gchar *fragment=NULL,*end=NULL;
+ GString *uri = NULL;
+
+ xml_parse_children_of_node(navLabel,(xmlChar*)"text",NULL,NULL);
+ linknode *newnode = g_new0(linknode,1);
+ newnode->linktext = NULL;
+ while (newnode->linktext == NULL) {
+ newnode->linktext = (gchar*)xml_get_data_from_node(xmlretval,XML_KEYWORD,NULL);
+ xmlretval = xmlretval->next;
+ }
+ xmlretval = NULL;
+ xml_parse_children_of_node(navPoint,(xmlChar*)"content",NULL,NULL);
+ pagelink = g_string_new(epub_document->documentdir);
+ newnode->pagelink = (gchar*)xml_get_data_from_node(xmlretval,XML_ATTRIBUTE,(xmlChar*)"src");
+ g_string_append_printf(pagelink,"/%s",newnode->pagelink);
+ xmlFree(newnode->pagelink);
+
+ if ((end = g_strrstr(pagelink->str,"#")) != NULL) {
+ fragment = g_strdup(g_strrstr(pagelink->str,"#"));
+ *end = '\0';
+ }
+ uri = g_string_new(g_filename_to_uri(pagelink->str,NULL,NULL));
+ g_string_free(pagelink,TRUE);
+
+ if (fragment) {
+ g_string_append(uri,fragment);
+ }
+
+ newnode->pagelink = g_strdup(uri->str);
+ g_string_free(uri,TRUE);
+ index = g_list_prepend(index,newnode);
+ }
+
+ navPoint = navPoint->next;
+
+ } while(navPoint != NULL);
+
+ xml_free_doc();
+
+ return g_list_reverse(index);
+}
+
+static EvDocumentInfo*
+epub_document_get_info(EvDocument *document)
+{
+ EpubDocument *epub_document = EPUB_DOCUMENT(document);
+ GError *error = NULL ;
+ gchar* infofile ;
+ xmlNodePtr metanode ;
+ GString* buffer ;
+ gchar* archive_dir = epub_document->tmp_archive_dir;
+ GString* containerpath = g_string_new(epub_document->tmp_archive_dir);
+ g_string_append_printf(containerpath,"/META-INF/container.xml");
+ gchar* containeruri = g_filename_to_uri(containerpath->str,NULL,&error);
+ if ( error )
+ {
+ return NULL ;
+ }
+ gchar* uri = get_uri_to_content (containeruri,&error,epub_document);
+ if ( error )
+ {
+ return NULL ;
+ }
+ EvDocumentInfo* epubinfo = g_new0 (EvDocumentInfo, 1);
+
+ epubinfo->fields_mask = EV_DOCUMENT_INFO_TITLE |
+ EV_DOCUMENT_INFO_FORMAT |
+ EV_DOCUMENT_INFO_AUTHOR |
+ EV_DOCUMENT_INFO_SUBJECT |
+ EV_DOCUMENT_INFO_KEYWORDS |
+ EV_DOCUMENT_INFO_LAYOUT |
+ EV_DOCUMENT_INFO_CREATOR |
+ EV_DOCUMENT_INFO_LINEARIZED |
+ EV_DOCUMENT_INFO_PERMISSIONS |
+ EV_DOCUMENT_INFO_N_PAGES ;
+
+ infofile = g_filename_from_uri(uri,NULL,&error);
+ if ( error )
+ return epubinfo;
+
+ open_xml_document(infofile);
+
+ set_xml_root_node((xmlChar*)"package");
+
+ metanode = xml_get_pointer_to_node((xmlChar*)"title",NULL,NULL);
+ if ( metanode == NULL )
+ epubinfo->title = NULL ;
+ else
+ epubinfo->title = (char*)xml_get_data_from_node(metanode,XML_KEYWORD,NULL);
+
+ metanode = xml_get_pointer_to_node((xmlChar*)"creator",NULL,NULL);
+ if ( metanode == NULL )
+ epubinfo->author = g_strdup("unknown");
+ else
+ epubinfo->author = (char*)xml_get_data_from_node(metanode,XML_KEYWORD,NULL);
+
+ metanode = xml_get_pointer_to_node((xmlChar*)"subject",NULL,NULL);
+ if ( metanode == NULL )
+ epubinfo->subject = g_strdup("unknown");
+ else
+ epubinfo->subject = (char*)xml_get_data_from_node(metanode,XML_KEYWORD,NULL);
+
+ buffer = g_string_new((gchar*)xml_get_data_from_node (xmlroot,XML_ATTRIBUTE,(xmlChar*)"version"));
+ g_string_prepend(buffer,"epub ");
+ epubinfo->format = g_strdup(buffer->str);
+
+ /*FIXME: Add more of these as you write the corresponding modules*/
+
+ epubinfo->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
+
+ metanode = xml_get_pointer_to_node((xmlChar*)"publisher",NULL,NULL);
+ if ( metanode == NULL )
+ epubinfo->creator = g_strdup("unknown");
+ else
+ epubinfo->creator = (char*)xml_get_data_from_node(metanode,XML_KEYWORD,NULL);
+
+ /* number of pages */
+ epubinfo->n_pages = epub_document_get_n_pages(document);
+
+ /*Copying*/
+ epubinfo->permissions = EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
+ /*TODO : Add a function to get date*/
+ g_free(uri);
+ g_string_free(containerpath,TRUE);
+ g_string_free(buffer,TRUE);
+
+ if (xmldocument)
+ xml_free_doc();
+ return epubinfo ;
+}
+
+static EvPage*
+epub_document_get_page(EvDocument *document,
+ gint index)
+{
+ EpubDocument *epub_document = EPUB_DOCUMENT(document);
+ EvPage* page = ev_page_new(index);
+ contentListNode *listptr = g_list_nth_data (epub_document->contentList,index);
+ page->backend_page = g_strdup(listptr->value);
+ return page ;
+}
+
+
+static gboolean
+epub_document_load (EvDocument* document,
+ const char* uri,
+ GError** error)
+{
+ EpubDocument *epub_document = EPUB_DOCUMENT(document);
+ GError* err = NULL ;
+ gchar* containeruri ;
+ GString *containerpath ;
+ gchar* contentOpfUri ;
+ if ( check_mime_type (uri,&err) == FALSE )
+ {
+ /*Error would've been set by the function*/
+ g_propagate_error(error,err);
+ return FALSE;
+ }
+
+ extract_epub_from_container (uri,epub_document,&err);
+
+ if ( err )
+ {
+ g_propagate_error( error,err );
+ return FALSE;
+ }
+
+ /*FIXME : can this be different, ever?*/
+ containerpath = g_string_new(epub_document->tmp_archive_dir);
+ g_string_append_printf(containerpath,"/META-INF/container.xml");
+ containeruri = g_filename_to_uri(containerpath->str,NULL,&err);
+
+ if ( err )
+ {
+ g_propagate_error(error,err);
+ return FALSE;
+ }
+ contentOpfUri = get_uri_to_content (containeruri,&err,epub_document);
+
+ if ( contentOpfUri == NULL )
+ {
+ g_propagate_error(error,err);
+ return FALSE;
+ }
+
+ epub_document->index = setup_document_index(epub_document,contentOpfUri);
+
+ epub_document->contentList = setup_document_content_list (contentOpfUri,&err,epub_document->documentdir,epub_document->index);
+
+ if ( epub_document->contentList == NULL )
+ {
+ g_propagate_error(error,err);
+ return FALSE;
+ }
+
+ return TRUE ;
+}
+
+static void
+epub_document_init (EpubDocument *epub_document)
+{
+ epub_document->archivename = NULL ;
+ epub_document->tmp_archive_dir = NULL ;
+ epub_document->contentList = NULL ;
+ epub_document->documentdir = NULL;
+ epub_document->index = NULL;
+ epub_document->docTitle = NULL;
+}
+
+static void
+epub_document_finalize (GObject *object)
+{
+ EpubDocument *epub_document = EPUB_DOCUMENT (object);
+
+ if (epub_document->epubDocument != NULL) {
+ if (epub_remove_temporary_dir (epub_document->tmp_archive_dir) == -1)
+ g_warning (_("There was an error deleting “%s”."),
+ epub_document->tmp_archive_dir);
+ }
+
+ if ( epub_document->contentList ) {
+ g_list_free_full(epub_document->contentList,(GDestroyNotify)free_tree_nodes);
+ epub_document->contentList = NULL;
+ }
+
+ if (epub_document->index) {
+ g_list_free_full(epub_document->index,(GDestroyNotify)free_link_nodes);
+ epub_document->index = NULL;
+ }
+
+ if ( epub_document->tmp_archive_dir) {
+ g_free (epub_document->tmp_archive_dir);
+ epub_document->tmp_archive_dir = NULL;
+ }
+
+ if (epub_document->docTitle) {
+ g_free(epub_document->docTitle);
+ epub_document->docTitle = NULL;
+ }
+ if ( epub_document->archivename) {
+ g_free (epub_document->archivename);
+ epub_document->archivename = NULL;
+ }
+ if ( epub_document->documentdir) {
+ g_free (epub_document->documentdir);
+ epub_document->documentdir = NULL;
+ }
+ G_OBJECT_CLASS (epub_document_parent_class)->finalize (object);
+}
+
+static void
+epub_document_class_init (EpubDocumentClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
+
+ gobject_class->finalize = epub_document_finalize;
+ ev_document_class->load = epub_document_load;
+ ev_document_class->save = epub_document_save;
+ ev_document_class->get_n_pages = epub_document_get_n_pages;
+ ev_document_class->get_info = epub_document_get_info;
+ ev_document_class->get_page = epub_document_get_page;
+} \ No newline at end of file
diff --git a/backend/epub/epub-document.h b/backend/epub/epub-document.h
new file mode 100644
index 00000000..b1120ec7
--- /dev/null
+++ b/backend/epub/epub-document.h
@@ -0,0 +1,21 @@
+#ifndef __EPUB_DOCUMENT_H__
+#define __EPUB_DOCUMENT_H__
+
+#define _GNU_SOURCE
+#include "ev-document.h"
+
+G_BEGIN_DECLS
+
+#define EPUB_TYPE_DOCUMENT (epub_document_get_type ())
+#define EPUB_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPUB_TYPE_DOCUMENT, EpubDocument))
+#define EPUB_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPUB_TYPE_DOCUMENT))
+
+typedef struct _EpubDocument EpubDocument;
+
+GType epub_document_get_type (void) G_GNUC_CONST;
+
+G_MODULE_EXPORT GType register_atril_backend (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* __EPUB_DOCUMENT_H__ */
diff --git a/backend/epub/epubdocument.atril-backend.in b/backend/epub/epubdocument.atril-backend.in
new file mode 100644
index 00000000..ef7767eb
--- /dev/null
+++ b/backend/epub/epubdocument.atril-backend.in
@@ -0,0 +1,4 @@
+[Atril Backend]
+Module=epubdocument
+_TypeDescription=epub Documents
+MimeType=application/epub+zip;
diff --git a/backend/epub/minizip/Makefile.am b/backend/epub/minizip/Makefile.am
new file mode 100644
index 00000000..315fada0
--- /dev/null
+++ b/backend/epub/minizip/Makefile.am
@@ -0,0 +1,14 @@
+AM_CPPFLAGS = \
+ $(WARN_CFLAGS) \
+ $(ZLIB_CFLAGS)
+
+noinst_LTLIBRARIES = libminizip.la
+
+libminizip_la_SOURCES = \
+ unzip.c \
+ ioapi.c
+
+libminizip_la_LIBADD = \
+ $(ZLIB_LIBS)
+
+-include $(top_srcdir)/git.mk
diff --git a/backend/epub/minizip/ioapi.c b/backend/epub/minizip/ioapi.c
new file mode 100644
index 00000000..7f5c191b
--- /dev/null
+++ b/backend/epub/minizip/ioapi.c
@@ -0,0 +1,247 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+*/
+
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
+ #define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if defined(__APPLE__) || defined(IOAPI_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#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)
+{
+ if (pfilefunc->zfile_func64.zopen64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
+ else
+ {
+ return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
+ }
+}
+
+long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
+{
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
+ else
+ {
+ uLong offsetTruncated = (uLong)offset;
+ if (offsetTruncated != offset)
+ return -1;
+ else
+ return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
+ }
+}
+
+ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
+{
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
+ else
+ {
+ uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+ if ((tell_uLong) == MAXU32)
+ return (ZPOS64_T)-1;
+ else
+ return tell_uLong;
+ }
+}
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
+{
+ p_filefunc64_32->zfile_func64.zopen64_file = NULL;
+ p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
+ p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+ p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
+ p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
+ p_filefunc64_32->zfile_func64.ztell64_file = NULL;
+ p_filefunc64_32->zfile_func64.zseek64_file = NULL;
+ p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
+ p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+ p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+ p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+ 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));
+static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
+static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
+static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
+
+static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = fopen(filename, mode_fopen);
+ return file;
+}
+
+static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = FOPEN_FUNC((const char*)filename, mode_fopen);
+ return file;
+}
+
+
+static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
+{
+ uLong ret;
+ ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
+{
+ uLong ret;
+ ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
+{
+ long ret;
+ ret = ftell((FILE *)stream);
+ return ret;
+}
+
+
+static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+{
+ ZPOS64_T ret;
+ ret = FTELLO_FUNC((FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+ if (fseek((FILE *)stream, offset, fseek_origin) != 0)
+ ret = -1;
+ return ret;
+}
+
+static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+
+ if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
+ ret = -1;
+
+ return ret;
+}
+
+
+static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
+{
+ int ret;
+ ret = fclose((FILE *)stream);
+ return ret;
+}
+
+static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
+{
+ int ret;
+ ret = ferror((FILE *)stream);
+ return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = fopen_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell_file = ftell_file_func;
+ pzlib_filefunc_def->zseek_file = fseek_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
+
+void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
+{
+ pzlib_filefunc_def->zopen64_file = fopen64_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell64_file = ftell64_file_func;
+ pzlib_filefunc_def->zseek64_file = fseek64_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
diff --git a/backend/epub/minizip/ioapi.h b/backend/epub/minizip/ioapi.h
new file mode 100644
index 00000000..8dcbdb06
--- /dev/null
+++ b/backend/epub/minizip/ioapi.h
@@ -0,0 +1,208 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+ Changes
+
+ Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
+ Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
+ More if/def section may be needed to support other platforms
+ Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
+ (but you should use iowin32.c for windows instead)
+
+*/
+
+#ifndef _ZLIBIOAPI64_H
+#define _ZLIBIOAPI64_H
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+
+ // Linux needs this to support file operation on files larger then 4+GB
+ // But might need better if/def to select just the platforms that needs them.
+
+ #ifndef __USE_FILE_OFFSET64
+ #define __USE_FILE_OFFSET64
+ #endif
+ #ifndef __USE_LARGEFILE64
+ #define __USE_LARGEFILE64
+ #endif
+ #ifndef _LARGEFILE64_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #endif
+ #ifndef _FILE_OFFSET_BIT
+ #define _FILE_OFFSET_BIT 64
+ #endif
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zlib.h"
+
+#if defined(USE_FILE32API)
+#define fopen64 fopen
+#define ftello64 ftell
+#define fseeko64 fseek
+#else
+#ifdef __FreeBSD__
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
+#ifdef _MSC_VER
+ #define fopen64 fopen
+ #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
+ #define ftello64 _ftelli64
+ #define fseeko64 _fseeki64
+ #else // old MSC
+ #define ftello64 ftell
+ #define fseeko64 fseek
+ #endif
+#endif
+#endif
+
+/*
+#ifndef ZPOS64_T
+ #ifdef _WIN32
+ #define ZPOS64_T fpos_t
+ #else
+ #include <stdint.h>
+ #define ZPOS64_T uint64_t
+ #endif
+#endif
+*/
+
+#ifdef HAVE_MINIZIP64_CONF_H
+#include "mz64conf.h"
+#endif
+
+/* a type choosen by DEFINE */
+#ifdef HAVE_64BIT_INT_CUSTOM
+typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
+#else
+#ifdef HAS_STDINT_H
+#include "stdint.h"
+typedef uint64_t ZPOS64_T;
+#else
+
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#define MAXU32 0xffffffff
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ZPOS64_T;
+#else
+typedef unsigned long long int ZPOS64_T;
+#endif
+#endif
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#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
+ #else
+ #define ZCALLBACK
+ #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));
+typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+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
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
+
+typedef struct zlib_filefunc64_def_s
+{
+ open64_file_func zopen64_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell64_file_func ztell64_file;
+ seek64_file_func zseek64_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc64_def;
+
+void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+/* now internal definition, only for zip.c and unzip.h */
+typedef struct zlib_filefunc64_32_def_s
+{
+ zlib_filefunc64_def zfile_func64;
+ open_file_func zopen32_file;
+ tell_file_func ztell32_file;
+ 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))
+//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
+#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
+
+voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
+long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
+ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
+
+#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
+#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
+#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/backend/epub/minizip/unzip.c b/backend/epub/minizip/unzip.c
new file mode 100644
index 00000000..90935043
--- /dev/null
+++ b/backend/epub/minizip/unzip.c
@@ -0,0 +1,2125 @@
+/* unzip.c -- IO for uncompress .zip files using zlib
+ Version 1.1, February 14h, 2010
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications of Unzip for Zip64
+ Copyright (C) 2007-2008 Even Rouault
+
+ Modifications for Zip64 support on both zip and unzip
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ 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.
+ Code woven in by Terry Thorsen 1/2003.
+
+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+
+ crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ ------------------------------------------------------------------------------------
+
+ Changes in unzip.c
+
+ 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
+ 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
+ 2007-2008 - Even Rouault - Remove old C style function prototypes
+ 2007-2008 - Even Rouault - Add unzip support for ZIP64
+
+ 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
+ the size from normal header was 0xFFFFFFFF
+ Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant
+ Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)
+ Patch created by Daniel Borca
+
+ Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
+
+ Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef NOUNCRYPT
+ #define NOUNCRYPT
+#endif
+
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# 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
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+const char unz_copyright[] =
+ " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+/* 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
+{
+ char *read_buffer; /* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+#ifdef HAVE_BZIP2
+ bz_stream bstream; /* bzLib stream structure for bziped */
+#endif
+
+ ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
+ uLong stream_initialised; /* flag set if stream structure is initialised*/
+
+ ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
+ uInt size_local_extrafield;/* size of the local extra field */
+ ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/
+ ZPOS64_T total_out_64;
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
+ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+ zlib_filefunc64_32_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ int raw;
+} file_in_zip64_read_info_s;
+
+
+/* unz64_s contain internal information about the zipfile
+*/
+typedef struct
+{
+ zlib_filefunc64_32_def z_filefunc;
+ int is64bitOpenFunction;
+ voidpf filestream; /* io structore of the zipfile */
+ unz_global_info64 gi; /* public global information */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ ZPOS64_T num_file; /* number of the current file in the zipfile*/
+ ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/
+ ZPOS64_T current_file_ok; /* flag about the usability of the current file*/
+ ZPOS64_T central_pos; /* position of the beginning of the central dir*/
+
+ ZPOS64_T size_central_dir; /* size of the central directory */
+ ZPOS64_T offset_central_dir; /* offset of start of central directory with
+ respect to the starting disk number */
+
+ unz_file_info64 cur_file_info; /* public info about the current file in zip*/
+ unz_file_info64_internal cur_file_info_internal; /* private info about it*/
+ file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
+ file if we are decompressing it */
+ int encrypted;
+
+ int isZip64;
+
+# ifndef NOUNCRYPT
+ unsigned long keys[3]; /* keys defining the pseudo-random sequence */
+ const z_crc_t* pcrc_32_tab;
+# endif
+} unz64_s;
+
+
+#ifndef NOUNCRYPT
+#include "crypt.h"
+#endif
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+
+
+local int unz64local_getByte OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ int *pi));
+
+local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
+{
+ unsigned char c;
+ int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
+ if (err==1)
+ {
+ *pi = (int)c;
+ return UNZ_OK;
+ }
+ else
+ {
+ if (ZERROR64(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int unz64local_getShort OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX)
+{
+ uLong x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unz64local_getLong OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX)
+{
+ uLong x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<24;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unz64local_getLong64 OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX));
+
+
+local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX)
+{
+ ZPOS64_T x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (ZPOS64_T)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<24;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<32;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<40;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<48;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<56;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
+{
+ for (;;)
+ {
+ char c1=*(fileName1++);
+ char c2=*(fileName2++);
+ if ((c1>='a') && (c1<='z'))
+ c1 -= 0x20;
+ if ((c2>='a') && (c2<='z'))
+ c2 -= 0x20;
+ if (c1=='\0')
+ return ((c2=='\0') ? 0 : -1);
+ if (c2=='\0')
+ return 1;
+ if (c1<c2)
+ return -1;
+ if (c1>c2)
+ return 1;
+ }
+}
+
+
+#ifdef CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity)
+
+{
+ if (iCaseSensitivity==0)
+ iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+ if (iCaseSensitivity==1)
+ return strcmp(fileName1,fileName2);
+
+ return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+/*
+ Locate the Central directory of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
+local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
+{
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=0;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ return uPosFound;
+}
+
+
+/*
+ Locate the Central directory 64 of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir64 OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream));
+
+local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream)
+{
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=0;
+ uLong uL;
+ ZPOS64_T relativeOffset;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ if (uPosFound == 0)
+ return 0;
+
+ /* Zip64 end of central directory locator */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return 0;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+
+ /* number of the disk with the start of the zip64 end of central directory */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+ if (uL != 0)
+ return 0;
+
+ /* relative offset of the zip64 end of central directory record */
+ if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
+ return 0;
+
+ /* total number of disks */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+ if (uL != 1)
+ return 0;
+
+ /* Goto end of central directory record */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return 0;
+
+ /* the signature */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+
+ if (uL != 0x06064b50)
+ return 0;
+
+ return relativeOffset;
+}
+
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+ "zlib/zlib114.zip".
+ If the zipfile cannot be opened (file doesn't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+local unzFile unzOpenInternal (const void *path,
+ zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
+ int is64bitOpenFunction)
+{
+ unz64_s us;
+ unz64_s *s;
+ ZPOS64_T central_pos;
+ uLong uL;
+
+ uLong number_disk; /* number of the current dist, used for
+ spaning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spaning ZIP, unsupported, always 0*/
+ ZPOS64_T number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+
+ int err=UNZ_OK;
+
+ if (unz_copyright[0]!=' ')
+ return NULL;
+
+ us.z_filefunc.zseek32_file = NULL;
+ us.z_filefunc.ztell32_file = NULL;
+ if (pzlib_filefunc64_32_def==NULL)
+ fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
+ else
+ us.z_filefunc = *pzlib_filefunc64_32_def;
+ us.is64bitOpenFunction = is64bitOpenFunction;
+
+
+
+ us.filestream = ZOPEN64(us.z_filefunc,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+ ZLIB_FILEFUNC_MODE_EXISTING);
+ if (us.filestream==NULL)
+ return NULL;
+
+ central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
+ if (central_pos)
+ {
+ uLong uS;
+ ZPOS64_T uL64;
+
+ us.isZip64 = 1;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* size of zip64 end of central directory record */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version made by */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version needed to extract */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory on this disk */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ us.gi.size_comment = 0;
+ }
+ else
+ {
+ central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
+ if (central_pos==0)
+ err=UNZ_ERRNO;
+
+ us.isZip64 = 0;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.gi.number_entry = uL;
+
+ /* total number of entries in the central dir */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ number_entry_CD = uL;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.size_central_dir = uL;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.offset_central_dir = uL;
+
+ /* zipfile comment length */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+ (err==UNZ_OK))
+ err=UNZ_BADZIPFILE;
+
+ if (err!=UNZ_OK)
+ {
+ ZCLOSE64(us.z_filefunc, us.filestream);
+ return NULL;
+ }
+
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir+us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+
+ s=(unz64_s*)ALLOC(sizeof(unz64_s));
+ if( s != NULL)
+ {
+ *s=us;
+ unzGoToFirstFile((unzFile)s);
+ }
+ return (unzFile)s;
+}
+
+
+extern unzFile ZEXPORT unzOpen2 (const char *path,
+ zlib_filefunc_def* pzlib_filefunc32_def)
+{
+ if (pzlib_filefunc32_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
+ }
+ else
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen2_64 (const void *path,
+ zlib_filefunc64_def* pzlib_filefunc_def)
+{
+ if (pzlib_filefunc_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
+ zlib_filefunc64_32_def_fill.ztell32_file = NULL;
+ zlib_filefunc64_32_def_fill.zseek32_file = NULL;
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
+ }
+ else
+ return unzOpenInternal(path, NULL, 1);
+}
+
+extern unzFile ZEXPORT unzOpen (const char *path)
+{
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen64 (const void *path)
+{
+ return unzOpenInternal(path, NULL, 1);
+}
+
+/*
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (unzFile file)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ if (s->pfile_in_zip_read!=NULL)
+ unzCloseCurrentFile(file);
+
+ ZCLOSE64(s->z_filefunc, s->filestream);
+ TRYFREE(s);
+ return UNZ_OK;
+}
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ *pglobal_info=s->gi;
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ /* to do : check if number_entry is not truncated */
+ pglobal_info32->number_entry = (uLong)s->gi.number_entry;
+ pglobal_info32->size_comment = s->gi.size_comment;
+ return UNZ_OK;
+}
+/*
+ Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
+{
+ ZPOS64_T uDate;
+ uDate = (ZPOS64_T)(ulDosDate>>16);
+ ptm->tm_mday = (uInt)(uDate&0x1f) ;
+ ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+ ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+ Get Info about the current file in the zipfile, with internal only info
+*/
+local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
+ unz_file_info64 *pfile_info,
+ unz_file_info64_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+local int unz64local_GetCurrentFileInfoInternal (unzFile file,
+ unz_file_info64 *pfile_info,
+ unz_file_info64_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize)
+{
+ unz64_s* s;
+ unz_file_info64 file_info;
+ unz_file_info64_internal file_info_internal;
+ int err=UNZ_OK;
+ uLong uMagic;
+ long lSeek=0;
+ uLong uL;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (ZSEEK64(s->z_filefunc, s->filestream,
+ s->pos_in_central_dir+s->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x02014b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info.compressed_size = uL;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info.uncompressed_size = uL;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ // relative offset of local header
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info_internal.offset_curfile = uL;
+
+ lSeek+=file_info.size_filename;
+ if ((err==UNZ_OK) && (szFileName!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_filename<fileNameBufferSize)
+ {
+ *(szFileName+file_info.size_filename)='\0';
+ uSizeRead = file_info.size_filename;
+ }
+ else
+ uSizeRead = fileNameBufferSize;
+
+ if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek -= uSizeRead;
+ }
+
+ // Read extrafield
+ if ((err==UNZ_OK) && (extraField!=NULL))
+ {
+ ZPOS64_T uSizeRead ;
+ if (file_info.size_file_extra<extraFieldBufferSize)
+ uSizeRead = file_info.size_file_extra;
+ else
+ uSizeRead = extraFieldBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+
+ lSeek += file_info.size_file_extra - (uLong)uSizeRead;
+ }
+ else
+ lSeek += file_info.size_file_extra;
+
+
+ if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
+ {
+ uLong acc = 0;
+
+ // since lSeek now points to after the extra field we need to move back
+ lSeek -= file_info.size_file_extra;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ while(acc < file_info.size_file_extra)
+ {
+ uLong headerId;
+ uLong dataSize;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* ZIP64 extra fields */
+ if (headerId == 0x0001)
+ {
+ uLong uL;
+
+ if(file_info.uncompressed_size == MAXU32)
+ {
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info.compressed_size == MAXU32)
+ {
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info_internal.offset_curfile == MAXU32)
+ {
+ /* Relative Header offset */
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info.disk_num_start == MAXU32)
+ {
+ /* Disk Start Number */
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ }
+ else
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+ err=UNZ_ERRNO;
+ }
+
+ acc += 2 + 2 + dataSize;
+ }
+ }
+
+ if ((err==UNZ_OK) && (szComment!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_comment<commentBufferSize)
+ {
+ *(szComment+file_info.size_file_comment)='\0';
+ uSizeRead = file_info.size_file_comment;
+ }
+ else
+ uSizeRead = commentBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek+=file_info.size_file_comment - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_comment;
+
+
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+ if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+ *pfile_info_internal=file_info_internal;
+
+ return err;
+}
+
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
+ unz_file_info64 * pfile_info,
+ char * szFileName, uLong fileNameBufferSize,
+ void *extraField, uLong extraFieldBufferSize,
+ char* szComment, uLong commentBufferSize)
+{
+ return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+}
+
+extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
+ unz_file_info * pfile_info,
+ char * szFileName, uLong fileNameBufferSize,
+ void *extraField, uLong extraFieldBufferSize,
+ char* szComment, uLong commentBufferSize)
+{
+ int err;
+ unz_file_info64 file_info64;
+ err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+ if ((err==UNZ_OK) && (pfile_info != NULL))
+ {
+ pfile_info->version = file_info64.version;
+ pfile_info->version_needed = file_info64.version_needed;
+ pfile_info->flag = file_info64.flag;
+ pfile_info->compression_method = file_info64.compression_method;
+ pfile_info->dosDate = file_info64.dosDate;
+ pfile_info->crc = file_info64.crc;
+
+ pfile_info->size_filename = file_info64.size_filename;
+ pfile_info->size_file_extra = file_info64.size_file_extra;
+ pfile_info->size_file_comment = file_info64.size_file_comment;
+
+ pfile_info->disk_num_start = file_info64.disk_num_start;
+ pfile_info->internal_fa = file_info64.internal_fa;
+ pfile_info->external_fa = file_info64.external_fa;
+
+ 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;
+
+ }
+ return err;
+}
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile (unzFile file)
+{
+ int err=UNZ_OK;
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ s->pos_in_central_dir=s->offset_central_dir;
+ s->num_file=0;
+ err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile (unzFile file)
+{
+ unz64_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
+ if (s->num_file+1==s->gi.number_entry)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+ s->num_file++;
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
+{
+ unz64_s* s;
+ int err;
+
+ /* We remember the 'current' position in the file so that we can jump
+ * back there if we fail.
+ */
+ unz_file_info64 cur_file_infoSaved;
+ unz_file_info64_internal cur_file_info_internalSaved;
+ ZPOS64_T num_fileSaved;
+ ZPOS64_T pos_in_central_dirSaved;
+
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+
+ if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+ return UNZ_PARAMERROR;
+
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ /* Save the current state */
+ num_fileSaved = s->num_file;
+ pos_in_central_dirSaved = s->pos_in_central_dir;
+ cur_file_infoSaved = s->cur_file_info;
+ cur_file_info_internalSaved = s->cur_file_info_internal;
+
+ err = unzGoToFirstFile(file);
+
+ while (err == UNZ_OK)
+ {
+ char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+ err = unzGetCurrentFileInfo64(file,NULL,
+ szCurrentFileName,sizeof(szCurrentFileName)-1,
+ NULL,0,NULL,0);
+ if (err == UNZ_OK)
+ {
+ if (unzStringFileNameCompare(szCurrentFileName,
+ szFileName,iCaseSensitivity)==0)
+ return UNZ_OK;
+ err = unzGoToNextFile(file);
+ }
+ }
+
+ /* We failed, so restore the state of the 'current file' to where we
+ * were.
+ */
+ s->num_file = num_fileSaved ;
+ s->pos_in_central_dir = pos_in_central_dirSaved ;
+ s->cur_file_info = cur_file_infoSaved;
+ s->cur_file_info_internal = cur_file_info_internalSaved;
+ return err;
+}
+
+
+/*
+///////////////////////////////////////////
+// Contributed by Ryan Haksi (mailto://[email protected])
+// I need random access
+//
+// Further optimization could be realized by adding an ability
+// to cache the directory in memory. The goal being a single
+// comprehensive file read to put the file I need in a memory.
+*/
+
+/*
+typedef struct unz_file_pos_s
+{
+ ZPOS64_T pos_in_zip_directory; // offset in file
+ ZPOS64_T num_of_file; // # of file
+} unz_file_pos;
+*/
+
+extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos)
+{
+ unz64_s* s;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ file_pos->pos_in_zip_directory = s->pos_in_central_dir;
+ file_pos->num_of_file = s->num_file;
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetFilePos(
+ unzFile file,
+ unz_file_pos* file_pos)
+{
+ unz64_file_pos file_pos64;
+ int err = unzGetFilePos64(file,&file_pos64);
+ if (err==UNZ_OK)
+ {
+ file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
+ file_pos->num_of_file = (uLong)file_pos64.num_of_file;
+ }
+ return err;
+}
+
+extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)
+{
+ unz64_s* s;
+ int err;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ /* jump to the right spot */
+ s->pos_in_central_dir = file_pos->pos_in_zip_directory;
+ s->num_file = file_pos->num_of_file;
+
+ /* set the current file */
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ /* return results */
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+extern int ZEXPORT unzGoToFilePos(
+ unzFile file,
+ unz_file_pos* file_pos)
+{
+ unz64_file_pos file_pos64;
+ if (file_pos == NULL)
+ return UNZ_PARAMERROR;
+
+ file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
+ file_pos64.num_of_file = file_pos->num_of_file;
+ return unzGoToFilePos64(file,&file_pos64);
+}
+
+/*
+// Unzip Helper Functions - should be here?
+///////////////////////////////////////////
+*/
+
+/*
+ Read the local header of the current zipfile
+ Check the coherency of the local header and info in the end of central
+ directory about this file
+ store in *piSizeVar the size of extra info in local header
+ (filename and size of extra field data)
+*/
+local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
+ ZPOS64_T * poffset_local_extrafield,
+ uInt * psize_local_extrafield)
+{
+ uLong uMagic,uData,uFlags;
+ uLong size_filename;
+ uLong size_extra_field;
+ int err=UNZ_OK;
+
+ *piSizeVar = 0;
+ *poffset_local_extrafield = 0;
+ *psize_local_extrafield = 0;
+
+ if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+ 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)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x04034b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+/*
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+ err=UNZ_BADZIPFILE;
+*/
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+ err=UNZ_BADZIPFILE;
+
+ if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+ (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+ err=UNZ_ERRNO;
+ else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+ err=UNZ_ERRNO;
+ else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+ err=UNZ_BADZIPFILE;
+
+ *piSizeVar += (uInt)size_filename;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+ err=UNZ_ERRNO;
+ *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+ SIZEZIPLOCALHEADER + size_filename;
+ *psize_local_extrafield = (uInt)size_extra_field;
+
+ *piSizeVar += (uInt)size_extra_field;
+
+ return err;
+}
+
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
+ int* level, int raw, const char* password)
+{
+ int err=UNZ_OK;
+ uInt iSizeVar;
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ ZPOS64_T offset_local_extrafield; /* offset of the local extra field */
+ uInt size_local_extrafield; /* size of the local extra field */
+# ifndef NOUNCRYPT
+ char source[12];
+# else
+ if (password != NULL)
+ return UNZ_PARAMERROR;
+# endif
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_PARAMERROR;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile(file);
+
+ if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+ return UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_INTERNALERROR;
+
+ pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+ pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+ pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+ pfile_in_zip_read_info->pos_local_extrafield=0;
+ pfile_in_zip_read_info->raw=raw;
+
+ if (pfile_in_zip_read_info->read_buffer==NULL)
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return UNZ_INTERNALERROR;
+ }
+
+ pfile_in_zip_read_info->stream_initialised=0;
+
+ if (method!=NULL)
+ *method = (int)s->cur_file_info.compression_method;
+
+ if (level!=NULL)
+ {
+ *level = 6;
+ switch (s->cur_file_info.flag & 0x06)
+ {
+ case 6 : *level = 1; break;
+ case 4 : *level = 2; break;
+ case 2 : *level = 9; break;
+ }
+ }
+
+ if ((s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+ (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+
+ err=UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+ pfile_in_zip_read_info->crc32=0;
+ pfile_in_zip_read_info->total_out_64=0;
+ pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
+ pfile_in_zip_read_info->filestream=s->filestream;
+ pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+ pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+ pfile_in_zip_read_info->stream.total_out = 0;
+
+ if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
+ {
+#ifdef HAVE_BZIP2
+ pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
+ pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
+ pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->bstream.state = (voidpf)0;
+
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = (voidpf)0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
+ else
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return err;
+ }
+#else
+ pfile_in_zip_read_info->raw=1;
+#endif
+ }
+ else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
+ {
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = 0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
+ else
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return err;
+ }
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END.
+ * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+ * size of both compressed and uncompressed data
+ */
+ }
+ pfile_in_zip_read_info->rest_read_compressed =
+ s->cur_file_info.compressed_size ;
+ 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;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+ s->encrypted = 0;
+
+# ifndef NOUNCRYPT
+ if (password != NULL)
+ {
+ int i;
+ s->pcrc_32_tab = get_crc_table();
+ init_keys(password,s->keys,s->pcrc_32_tab);
+ if (ZSEEK64(s->z_filefunc, s->filestream,
+ s->pfile_in_zip_read->pos_in_zipfile +
+ s->pfile_in_zip_read->byte_before_the_zipfile,
+ SEEK_SET)!=0)
+ return UNZ_INTERNALERROR;
+ if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
+ return UNZ_INTERNALERROR;
+
+ for (i = 0; i<12; i++)
+ zdecode(s->keys,s->pcrc_32_tab,source[i]);
+
+ s->pfile_in_zip_read->pos_in_zipfile+=12;
+ s->encrypted=1;
+ }
+# endif
+
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzOpenCurrentFile (unzFile file)
+{
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+}
+
+extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password)
+{
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
+}
+
+extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
+{
+ return unzOpenCurrentFile3(file, method, level, raw, NULL);
+}
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ s=(unz64_s*)file;
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+ if (pfile_in_zip_read_info==NULL)
+ return 0; //UNZ_PARAMERROR;
+ return pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile;
+}
+
+/** Addition for GDAL : END */
+
+/*
+ Read bytes from the current file.
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
+{
+ int err=UNZ_OK;
+ uInt iRead = 0;
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ 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)
+ return 0;
+
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+ pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+ if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+ (!(pfile_in_zip_read_info->raw)))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+ if ((len>pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in) &&
+ (pfile_in_zip_read_info->raw))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in;
+
+ while (pfile_in_zip_read_info->stream.avail_out>0)
+ {
+ if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+ (pfile_in_zip_read_info->rest_read_compressed>0))
+ {
+ uInt uReadThis = UNZ_BUFSIZE;
+ if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+ uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+ if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->read_buffer,
+ uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+
+
+# ifndef NOUNCRYPT
+ if(s->encrypted)
+ {
+ uInt i;
+ for(i=0;i<uReadThis;i++)
+ pfile_in_zip_read_info->read_buffer[i] =
+ zdecode(s->keys,s->pcrc_32_tab,
+ pfile_in_zip_read_info->read_buffer[i]);
+ }
+# endif
+
+
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef*)pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+ }
+
+ if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+ {
+ uInt uDoCopy,i ;
+
+ if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ return (iRead==0) ? UNZ_EOF : iRead;
+
+ if (pfile_in_zip_read_info->stream.avail_out <
+ pfile_in_zip_read_info->stream.avail_in)
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+ else
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+ for (i=0;i<uDoCopy;i++)
+ *(pfile_in_zip_read_info->stream.next_out+i) =
+ *(pfile_in_zip_read_info->stream.next_in+i);
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ uDoCopy);
+ pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+ pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+ pfile_in_zip_read_info->stream.next_out += uDoCopy;
+ pfile_in_zip_read_info->stream.next_in += uDoCopy;
+ pfile_in_zip_read_info->stream.total_out += uDoCopy;
+ iRead += uDoCopy;
+ }
+ else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
+ {
+#ifdef HAVE_BZIP2
+ uLong uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ uLong uOutThis;
+
+ pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in;
+ pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in;
+ pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in;
+ pfile_in_zip_read_info->bstream.total_in_hi32 = 0;
+ pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out;
+ pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out;
+ pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
+ pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
+
+ uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
+ bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
+
+ err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
+
+ uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
+ pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
+ pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in;
+ pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32;
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
+ pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
+ pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
+
+ if (err==BZ_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=BZ_OK)
+ break;
+#endif
+ } // end Z_BZIP2ED
+ else
+ {
+ ZPOS64_T uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ ZPOS64_T uOutThis;
+ int flush=Z_SYNC_FLUSH;
+
+ uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+ bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+ /*
+ if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+ pfile_in_zip_read_info->stream.avail_out) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ flush = Z_FINISH;
+ */
+ err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+ if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
+ err = Z_DATA_ERROR;
+
+ uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+ pfile_in_zip_read_info->crc32 =
+ crc32(pfile_in_zip_read_info->crc32,bufBefore,
+ (uInt)(uOutThis));
+
+ pfile_in_zip_read_info->rest_read_uncompressed -=
+ uOutThis;
+
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ if (err==Z_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=Z_OK)
+ break;
+ }
+ }
+
+ if (err==Z_OK)
+ return iRead;
+ return err;
+}
+
+
+/*
+ Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell (unzFile file)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
+{
+
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return (ZPOS64_T)-1;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return (ZPOS64_T)-1;
+
+ return pfile_in_zip_read_info->total_out_64;
+}
+
+
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+extern int ZEXPORT unzeof (unzFile file)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ return 1;
+ else
+ 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
+more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field that can be read
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ uInt read_now;
+ ZPOS64_T size_to_read;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+ pfile_in_zip_read_info->pos_local_extrafield);
+
+ if (buf==NULL)
+ return (int)size_to_read;
+
+ if (len>size_to_read)
+ read_now = (uInt)size_to_read;
+ else
+ read_now = (uInt)len ;
+
+ if (read_now==0)
+ return 0;
+
+ if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->offset_local_extrafield +
+ pfile_in_zip_read_info->pos_local_extrafield,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ buf,read_now)!=read_now)
+ return UNZ_ERRNO;
+
+ return (int)read_now;
+}
+
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile (unzFile file)
+{
+ int err=UNZ_OK;
+
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ 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))
+ {
+ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+ 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)
+ inflateEnd(&pfile_in_zip_read_info->stream);
+#ifdef HAVE_BZIP2
+ else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
+ BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
+#endif
+
+
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE(pfile_in_zip_read_info);
+
+ s->pfile_in_zip_read=NULL;
+
+ return err;
+}
+
+
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
+{
+ unz64_s* s;
+ uLong uReadThis ;
+ if (file==NULL)
+ return (int)UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ uReadThis = uSizeBuf;
+ if (uReadThis>s->gi.size_comment)
+ uReadThis = s->gi.size_comment;
+
+ if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (uReadThis>0)
+ {
+ *szComment='\0';
+ if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+ }
+
+ if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+ *(szComment+s->gi.size_comment)='\0';
+ return (int)uReadThis;
+}
+
+/* Additions by RX '2004 */
+extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
+{
+ unz64_s* s;
+
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return 0;
+ if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
+ if (s->num_file==s->gi.number_entry)
+ return 0;
+ return s->pos_in_central_dir;
+}
+
+extern uLong ZEXPORT unzGetOffset (unzFile file)
+{
+ ZPOS64_T offset64;
+
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ offset64 = unzGetOffset64(file);
+ return (uLong)offset64;
+}
+
+extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
+{
+ unz64_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ s->pos_in_central_dir = pos;
+ s->num_file = s->gi.number_entry; /* hack */
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
+{
+ return unzSetOffset64(file,pos);
+}
diff --git a/backend/epub/minizip/unzip.h b/backend/epub/minizip/unzip.h
new file mode 100644
index 00000000..2104e391
--- /dev/null
+++ b/backend/epub/minizip/unzip.h
@@ -0,0 +1,437 @@
+/* unzip.h -- IO for uncompress .zip files using zlib
+ Version 1.1, February 14h, 2010
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications of Unzip for Zip64
+ Copyright (C) 2007-2008 Even Rouault
+
+ Modifications for Zip64 support on both zip and unzip
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+ ---------------------------------------------------------------------------------
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ ---------------------------------------------------------------------------------
+
+ Changes
+
+ See header of unzip64.c
+
+*/
+
+#ifndef _unz64_H
+#define _unz64_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
+#ifdef HAVE_BZIP2
+#include "bzlib.h"
+#endif
+
+#define Z_BZIP2ED 12
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO (Z_ERRNO)
+#define UNZ_EOF (0)
+#define UNZ_PARAMERROR (-102)
+#define UNZ_BADZIPFILE (-103)
+#define UNZ_INTERNALERROR (-104)
+#define UNZ_CRCERROR (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+ These data comes from the end of central dir */
+typedef struct unz_global_info64_s
+{
+ ZPOS64_T number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info64;
+
+typedef struct unz_global_info_s
+{
+ uLong number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info;
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info64_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ ZPOS64_T compressed_size; /* compressed size 8 bytes */
+ ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info64;
+
+typedef struct unz_file_info_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ uLong compressed_size; /* compressed size 4 bytes */
+ uLong uncompressed_size; /* uncompressed size 4 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity));
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+extern unzFile ZEXPORT unzOpen64 OF((const void *path));
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+ "zlib/zlib113.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+ the "64" function take a const void* pointer, because the path is just the
+ value passed to the open64_file_func callback.
+ Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
+ is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
+ does not describe the reality
+*/
+
+
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def));
+/*
+ Open a Zip file, like unzOpen, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
+ zlib_filefunc64_def* pzlib_filefunc_def));
+/*
+ Open a Zip file, like unz64Open, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
+ return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
+
+extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,
+ unz_global_info64 *pglobal_info));
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ 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));
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity));
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ 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 */
+typedef struct unz_file_pos_s
+{
+ uLong pos_in_zip_directory; /* offset in zip file directory */
+ uLong num_of_file; /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+typedef struct unz64_file_pos_s
+{
+ ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */
+ ZPOS64_T num_of_file; /* # of file */
+} unz64_file_pos;
+
+extern int ZEXPORT unzGetFilePos64(
+ unzFile file,
+ unz64_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos64(
+ unzFile file,
+ const unz64_file_pos* file_pos);
+
+/* ****************************************** */
+
+extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,
+ unz_file_info64 *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+/*
+ Get Info about the current file
+ if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+ the current file
+ if szFileName!=NULL, the filemane string will be copied in szFileName
+ (fileNameBufferSize is the size of the buffer)
+ if extraField!=NULL, the extra field information will be copied in extraField
+ (extraFieldBufferSize is the size of the buffer).
+ This is the Central-header version of the extra field
+ if szComment!=NULL, the comment string of the file will be copied in szComment
+ (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)
+ */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+ const char* password));
+/*
+ Open for reading data the current file in the zipfile.
+ password is a crypting password
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw,
+ const char* password));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read bytes from the current file (opened by unzOpenCurrentFile)
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+
+extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
+/*
+ Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+
+/***************************************************************************/
+
+/* Get the current file offset */
+extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);
+extern uLong ZEXPORT unzGetOffset (unzFile file);
+
+/* Set the current file offset */
+extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz64_H */
diff --git a/configure.ac b/configure.ac
index 13203bbf..fc297187 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,14 +53,14 @@ AM_MAINTAINER_MODE([enable])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-AM_PROG_LIBTOOL
+
AC_ISC_POSIX
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CXX
AC_STDC_HEADERS
-
+AM_PROG_LIBTOOL
AC_PROG_SED
AC_PATH_PROG([GLIB_GENMARSHAL], [glib-genmarshal])
AC_PATH_PROG([GLIB_MKENUMS], [glib-mkenums])
@@ -688,6 +688,44 @@ AM_CONDITIONAL(ENABLE_XPS, test x$enable_xps = xyes)
dnl ================== End of XPS checks ===================================================
+
+dnl ================== EPUB checks ===================================================
+
+AC_ARG_ENABLE(epub,
+ [AS_HELP_STRING([--enable-epub],
+ [Compile with support for epub documents.])],
+ [enable_epub=$enableval],
+ [enable_epub=yes])
+
+if test "x$enable_epub" = "xyes"; then
+ WEBKIT_REQUIRED=2.4.2
+ case "$with_gtk" in
+ 2.0)
+ PKG_CHECK_MODULES(WEBKIT, webkit-1.0 >= $WEBKIT_REQUIRED libxml-2.0 >= $LIBXML_REQUIRED zlib,enable_epub=yes,enable_epub=no)
+ ;;
+ 3.0)
+ PKG_CHECK_MODULES(WEBKIT, webkit2gtk-3.0 >= $WEBKIT_REQUIRED libxml-2.0 >= $LIBXML_REQUIRED zlib,enable_epub=yes,enable_epub=no)
+ ;;
+ esac
+ if test "x$enable_epub" = "xyes"; then
+ AC_DEFINE([ENABLE_EPUB], [1], [Enable support for ePub documents.])
+ else
+ enable_epub="no"
+ AC_MSG_WARN(["ePub support is disabled since webkit-1.0( version >= $WEBKIT_REQUIRED ) is needed"])
+ case "$with_gtk" in
+ 2.0)
+ AC_MSG_WARN(["ePub support is disabled since webkit-1.0( version >= $WEBKIT_REQUIRED ) is needed"])
+ ;;
+ 3.0)AC_MSG_WARN(["ePub support is disabled since webkit2gtk-3.0( version >= $WEBKIT_REQUIRED ) is needed"])
+ ;;
+ esac
+ fi
+fi
+
+AM_CONDITIONAL(ENABLE_EPUB, test x$enable_epub = xyes)
+
+dnl ================== End of EPUB checks ===================================================
+
dnl =================== Mime types list ====================================================
if test "x$enable_pdf" = "xyes" ; then
@@ -714,6 +752,10 @@ fi
if test "x$enable_xps" = "xyes"; then
ATRIL_MIME_TYPES="${ATRIL_MIME_TYPES}application/oxps;application/vnd.ms-xpsdocument;"
fi
+if test "x$enable_epub" = "xyes"; then
+ ATRIL_MIME_TYPES="${ATRIL_MIME_TYPES}application/epub+zip"
+fi
+
AC_SUBST(ATRIL_MIME_TYPES)
AC_CHECK_FUNC(localtime_r, AC_DEFINE(HAVE_LOCALTIME_R, 1, [Defines if localtime_r is available on your system]))
@@ -766,6 +808,8 @@ backend/comics/Makefile
backend/djvu/Makefile
backend/dvi/Makefile
backend/dvi/mdvi-lib/Makefile
+backend/epub/Makefile
+backend/epub/minizip/Makefile
backend/pdf/Makefile
backend/pixbuf/Makefile
backend/ps/Makefile
@@ -854,4 +898,5 @@ Configure summary:
Pixbuf Backend.....: $enable_pixbuf
Comics Backend.....: $enable_comics
XPS Backend........: $enable_xps
+ ePub Backend.......: $enable_epub
"
diff --git a/help/reference/shell/Makefile.am b/help/reference/shell/Makefile.am
index a78201d7..40ece8fc 100644
--- a/help/reference/shell/Makefile.am
+++ b/help/reference/shell/Makefile.am
@@ -106,6 +106,7 @@ GTKDOC_CFLAGS = \
-DATRIL_COMPILATION \
$(SHELL_CFLAGS) \
$(WARN_CFLAGS) \
+ $(WEBKIT_CFLAGS) \
$(DISABLE_DEPRECATED) \
$(GTK_PRINT_CFLAGS)
@@ -126,6 +127,7 @@ GTKDOC_LIBS = \
$(top_builddir)/libmisc/libevmisc.la \
$(SHELL_LIBS) \
$(GTK_PRINT_LIBS) \
+ $(WEBKIT_LIBS) \
$(filter-out $(FILTER_OUT),$(wildcard $(top_builddir)/shell/*.o))
# This includes the standard gtk-doc make rules, copied by gtkdocize.
diff --git a/libdocument/ev-document-find.c b/libdocument/ev-document-find.c
index 0b5fac01..92dfffe5 100644
--- a/libdocument/ev-document-find.c
+++ b/libdocument/ev-document-find.c
@@ -40,3 +40,12 @@ ev_document_find_find_text (EvDocumentFind *document_find,
return iface->find_text (document_find, page, text, case_sensitive);
}
+guint
+ev_document_find_check_for_hits(EvDocumentFind *document_find,
+ EvPage *page,
+ const gchar *text,
+ gboolean case_sensitive)
+{
+ EvDocumentFindInterface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find);
+ return iface->check_for_hits (document_find, page, text, case_sensitive);
+} \ No newline at end of file
diff --git a/libdocument/ev-document-find.h b/libdocument/ev-document-find.h
index 7fcf49c7..2b6ba68b 100644
--- a/libdocument/ev-document-find.h
+++ b/libdocument/ev-document-find.h
@@ -52,6 +52,11 @@ struct _EvDocumentFindInterface
EvPage *page,
const gchar *text,
gboolean case_sensitive);
+
+ guint (* check_for_hits) (EvDocumentFind *document_find,
+ EvPage *page,
+ const gchar *text,
+ gboolean case_sensitive);
};
GType ev_document_find_get_type (void) G_GNUC_CONST;
@@ -60,6 +65,10 @@ GList *ev_document_find_find_text (EvDocumentFind *document_find,
const gchar *text,
gboolean case_sensitive);
+guint ev_document_find_check_for_hits (EvDocumentFind *document_find,
+ EvPage *page,
+ const gchar *text,
+ gboolean case_sensitive);
G_END_DECLS
#endif /* EV_DOCUMENT_FIND_H */
diff --git a/libdocument/ev-document-thumbnails.c b/libdocument/ev-document-thumbnails.c
index 9482e09e..65248683 100644
--- a/libdocument/ev-document-thumbnails.c
+++ b/libdocument/ev-document-thumbnails.c
@@ -59,5 +59,4 @@ ev_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
iface = EV_DOCUMENT_THUMBNAILS_GET_IFACE (document);
iface->get_dimensions (document, rc, width, height);
-}
-
+} \ No newline at end of file
diff --git a/libdocument/ev-document-thumbnails.h b/libdocument/ev-document-thumbnails.h
index 1a7cb9fd..5f425ef0 100644
--- a/libdocument/ev-document-thumbnails.h
+++ b/libdocument/ev-document-thumbnails.h
@@ -26,7 +26,7 @@
#define EV_DOCUMENT_THUMBNAILS_H
#include <gdk-pixbuf/gdk-pixbuf.h>
-
+#include <gtk/gtk.h>
#include "ev-render-context.h"
G_BEGIN_DECLS
@@ -52,6 +52,7 @@ struct _EvDocumentThumbnailsInterface {
EvRenderContext *rc,
gint *width,
gint *height);
+
};
GType ev_document_thumbnails_get_type (void) G_GNUC_CONST;
@@ -63,7 +64,6 @@ void ev_document_thumbnails_get_dimensions (EvDocumentThumbnails *document
EvRenderContext *rc,
gint *width,
gint *height);
-
G_END_DECLS
#endif /* EV_DOCUMENT_THUMBNAILS_H */
diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c
index 19d51d9b..a242bdf6 100644
--- a/libdocument/ev-document.c
+++ b/libdocument/ev-document.c
@@ -26,6 +26,7 @@
#include "ev-document.h"
#include "synctex_parser.h"
+#include "ev-file-helpers.h"
#define EV_DOCUMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EV_TYPE_DOCUMENT, EvDocumentPrivate))
@@ -141,6 +142,8 @@ ev_document_init (EvDocument *document)
/* Assume all pages are the same size until proven otherwise */
document->priv->uniform = TRUE;
+ /* Assume that the document is not a web document*/
+ document->iswebdocument = FALSE ;
}
static void
@@ -237,6 +240,14 @@ ev_document_load (EvDocument *document,
gboolean retval;
GError *err = NULL;
+ /*
+ * Hardcoding a check for ePub documents, cause it needs a web document DOM
+ * and webkit, support for any other web document types can be added similarly.
+ */
+
+ if ( !g_strcmp0 (ev_file_get_mime_type(uri,TRUE,&err),"application/epub+zip") )
+ document->iswebdocument=TRUE ;
+
retval = klass->load (document, uri, &err);
if (!retval) {
if (err) {
@@ -258,18 +269,34 @@ ev_document_load (EvDocument *document,
/* Cache some info about the document to avoid
* going to the backends since it requires locks
*/
+
priv->uri = g_strdup (uri);
- priv->n_pages = _ev_document_get_n_pages (document);
+ priv->n_pages = _ev_document_get_n_pages (document);
+
for (i = 0; i < priv->n_pages; i++) {
+
+ /*
+ * Since there is no sense of paging in an ePub,it makes no sense to have pages sizes.
+ * We are however geeneralising the scenario by considering epub as a type of web document.
+ * FIXME: Labels, or bookmarks though, can be done.
+ */
+
EvPage *page = ev_document_get_page (document, i);
gdouble page_width = 0;
gdouble page_height = 0;
EvPageSize *page_size;
gchar *page_label;
-
- _ev_document_get_page_size (document, page, &page_width, &page_height);
-
+
+ if ( document->iswebdocument == FALSE ) {
+ _ev_document_get_page_size (document, page, &page_width, &page_height);
+ }
+ else {
+ //Fixed page sized to resolve the X-windowing system error.
+ page_width = 800;
+ page_height= 600;
+ }
+
if (i == 0) {
priv->uniform_width = page_width;
priv->uniform_height = page_height;
@@ -277,14 +304,21 @@ ev_document_load (EvDocument *document,
priv->max_height = priv->uniform_height;
priv->min_width = priv->uniform_width;
priv->min_height = priv->uniform_height;
+ if (document->iswebdocument == TRUE ) {
+ priv->page_sizes = g_new0 (EvPageSize, 1);
+ priv->page_sizes->width = priv->uniform_width;
+ priv->page_sizes->height = priv->uniform_height;
+ priv->uniform = TRUE ;
+ break;
+ }
} else if (priv->uniform &&
(priv->uniform_width != page_width ||
priv->uniform_height != page_height)) {
/* It's a different page size. Backfill the array. */
int j;
-
+
priv->page_sizes = g_new0 (EvPageSize, priv->n_pages);
-
+
for (j = 0; j < i; j++) {
page_size = &(priv->page_sizes[j]);
page_size->width = priv->uniform_width;
@@ -511,15 +545,21 @@ ev_document_get_page_size (EvDocument *document,
{
g_return_if_fail (EV_IS_DOCUMENT (document));
g_return_if_fail (page_index >= 0 || page_index < document->priv->n_pages);
-
- if (width)
- *width = document->priv->uniform ?
- document->priv->uniform_width :
- document->priv->page_sizes[page_index].width;
- if (height)
- *height = document->priv->uniform ?
- document->priv->uniform_height :
- document->priv->page_sizes[page_index].height;
+ if (document->iswebdocument == TRUE ) {
+ if (width)
+ *width = document->priv->uniform_width;
+ if (height)
+ *height = document->priv->uniform_height;
+ } else {
+ if (width)
+ *width = document->priv->uniform ?
+ document->priv->uniform_width :
+ document->priv->page_sizes[page_index].width;
+ if (height)
+ *height = document->priv->uniform ?
+ document->priv->uniform_height :
+ document->priv->page_sizes[page_index].height;
+ }
}
static gchar *
diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h
index d10d261a..24e31912 100644
--- a/libdocument/ev-document.h
+++ b/libdocument/ev-document.h
@@ -85,6 +85,11 @@ struct _EvDocument
GObject base;
EvDocumentPrivate *priv;
+ /*
+ * Since we can only access the members of this structure from the window frontend,
+ * we need a flag to detemine whether to replace the atril-view with a web-view.
+ */
+ gboolean iswebdocument;
};
struct _EvDocumentClass
diff --git a/libdocument/ev-link-dest.c b/libdocument/ev-link-dest.c
index 62f2cd47..b9ea0dfd 100644
--- a/libdocument/ev-link-dest.c
+++ b/libdocument/ev-link-dest.c
@@ -509,3 +509,13 @@ ev_link_dest_new_page_label (const gchar *page_label)
"type", EV_LINK_DEST_TYPE_PAGE_LABEL,
NULL));
}
+
+EvLinkDest *
+ev_link_dest_new_hlink(const gchar* hlink,gint page)
+{
+ return EV_LINK_DEST(g_object_new(EV_TYPE_LINK_DEST,
+ "named",hlink,
+ "page",page,
+ "type", EV_LINK_DEST_TYPE_HLINK,
+ NULL));
+} \ No newline at end of file
diff --git a/libdocument/ev-link-dest.h b/libdocument/ev-link-dest.h
index a0e2539f..dd1f10a1 100644
--- a/libdocument/ev-link-dest.h
+++ b/libdocument/ev-link-dest.h
@@ -49,6 +49,7 @@ typedef enum {
EV_LINK_DEST_TYPE_FITR,
EV_LINK_DEST_TYPE_NAMED,
EV_LINK_DEST_TYPE_PAGE_LABEL,
+ EV_LINK_DEST_TYPE_HLINK,
EV_LINK_DEST_TYPE_UNKNOWN
} EvLinkDestType;
@@ -89,6 +90,7 @@ EvLinkDest *ev_link_dest_new_fitr (gint page,
gdouble top);
EvLinkDest *ev_link_dest_new_named (const gchar *named_dest);
EvLinkDest *ev_link_dest_new_page_label (const gchar *page_label);
+EvLinkDest *ev_link_dest_new_hlink (const gchar* hlink,gint page);
G_END_DECLS
diff --git a/libview/Makefile.am b/libview/Makefile.am
index 7dd0a950..96e80ea3 100644
--- a/libview/Makefile.am
+++ b/libview/Makefile.am
@@ -19,6 +19,7 @@ INST_H_SRC_FILES = \
ev-print-operation.h \
ev-stock-icons.h \
ev-view.h \
+ ev-web-view.h \
ev-view-presentation.h
INST_H_FILES = \
@@ -41,6 +42,7 @@ libatrilview_la_SOURCES = \
ev-timeline.c \
ev-transition-animation.c \
ev-view.c \
+ ev-web-view.c \
ev-view-accessible.c \
ev-view-marshal.c \
ev-view-cursor.c \
@@ -63,6 +65,7 @@ libatrilview_la_CFLAGS = \
$(LIBVIEW_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED) \
+ $(WEBKIT_CFLAGS) \
$(AM_CFLAGS)
libatrilview_la_LDFLAGS = \
@@ -73,7 +76,8 @@ libatrilview_la_LDFLAGS = \
libatrilview_la_LIBADD = \
$(top_builddir)/libdocument/libatrildocument.la \
- $(LIBVIEW_LIBS)
+ $(LIBVIEW_LIBS) \
+ $(WEBKIT_LIBS)
BUILT_SOURCES = \
ev-view-marshal.h \
diff --git a/libview/ev-document-model.c b/libview/ev-document-model.c
index 403df466..dbf0477f 100644
--- a/libview/ev-document-model.c
+++ b/libview/ev-document-model.c
@@ -109,7 +109,12 @@ ev_document_model_set_property (GObject *object,
ev_document_model_set_rotation (model, g_value_get_int (value));
break;
case PROP_INVERTED_COLORS:
- ev_document_model_set_inverted_colors (model, g_value_get_boolean (value));
+ if ( model->document->iswebdocument == TRUE ) {
+ atril_web_document_set_inverted_colors(model,g_value_get_boolean(value));
+ }
+ else {
+ ev_document_model_set_inverted_colors (model, g_value_get_boolean (value));
+ }
break;
case PROP_SCALE:
ev_document_model_set_scale (model, g_value_get_double (value));
@@ -490,6 +495,15 @@ ev_document_model_set_inverted_colors (EvDocumentModel *model,
g_object_notify (G_OBJECT (model), "inverted-colors");
}
+void
+atril_web_document_set_inverted_colors (EvDocumentModel *model,
+ gboolean inverted_colors)
+{
+ //TODO
+ model->inverted_colors = FALSE;
+ g_object_notify (G_OBJECT (model), "inverted-colors");
+}
+
gboolean
ev_document_model_get_inverted_colors (EvDocumentModel *model)
{
diff --git a/libview/ev-document-model.h b/libview/ev-document-model.h
index b8bea62c..f9d175c0 100644
--- a/libview/ev-document-model.h
+++ b/libview/ev-document-model.h
@@ -69,7 +69,9 @@ EvSizingMode ev_document_model_get_sizing_mode (EvDocumentModel *model);
void ev_document_model_set_rotation (EvDocumentModel *model,
gint rotation);
gint ev_document_model_get_rotation (EvDocumentModel *model);
-void ev_document_model_set_inverted_colors (EvDocumentModel *model,
+void ev_document_model_set_inverted_colors (EvDocumentModel *model,
+ gboolean inverted_colors);
+void atril_web_document_set_inverted_colors(EvDocumentModel *model,
gboolean inverted_colors);
gboolean ev_document_model_get_inverted_colors (EvDocumentModel *model);
void ev_document_model_set_continuous (EvDocumentModel *model,
diff --git a/libview/ev-jobs.c b/libview/ev-jobs.c
index d8d3043d..c4324a1c 100644
--- a/libview/ev-jobs.c
+++ b/libview/ev-jobs.c
@@ -24,6 +24,7 @@
#include "ev-document-thumbnails.h"
#include "ev-document-links.h"
#include "ev-document-images.h"
+#include "ev-job-scheduler.h"
#include "ev-document-forms.h"
#include "ev-file-exporter.h"
#include "ev-document-factory.h"
@@ -39,6 +40,14 @@
#include "ev-document-text.h"
#include "ev-debug.h"
+#include <gtk/gtk.h>
+#ifdef ENABLE_EPUB
+#if GTK_CHECK_VERSION(3, 0, 0)
+#include <webkit2/webkit2.h>
+#else
+#include <webkit/webkit.h>
+#endif
+#endif
#include <errno.h>
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
@@ -87,6 +96,9 @@ enum {
FIND_LAST_SIGNAL
};
+static GtkWidget* webview;
+static GtkWidget* offscreenwindow;
+
static guint job_signals[LAST_SIGNAL] = { 0 };
static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
@@ -211,7 +223,7 @@ ev_job_run (EvJob *job)
{
EvJobClass *class = EV_JOB_GET_CLASS (job);
- return class->run (job);
+ return class-> run (job);
}
void
@@ -568,6 +580,24 @@ ev_job_render_run (EvJob *job)
ev_document_fc_mutex_lock ();
ev_page = ev_document_get_page (job->document, job_render->page);
+
+ if ( job->document->iswebdocument == TRUE )
+ {
+ return TRUE;
+
+ if (g_cancellable_is_cancelled (job->cancellable)) {
+ ev_document_fc_mutex_unlock ();
+ ev_document_doc_mutex_unlock ();
+ g_object_unref (rc);
+
+ return FALSE;
+ }
+
+ ev_document_fc_mutex_unlock ();
+ ev_document_doc_mutex_unlock ();
+ ev_job_succeeded (job);
+ return FALSE;
+ }
rc = ev_render_context_new (ev_page, job_render->rotation, job_render->scale);
g_object_unref (ev_page);
@@ -740,7 +770,7 @@ ev_job_page_data_new (EvDocument *document,
static void
ev_job_thumbnail_init (EvJobThumbnail *job)
{
- EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
}
static void
@@ -760,28 +790,139 @@ ev_job_thumbnail_dispose (GObject *object)
(* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
}
+#if !GTK_CHECK_VERSION(3, 0, 0)
+static void
+web_thumbnail_get_screenshot_cb(WebKitWebView *webview,
+ WebKitWebFrame *webframe,
+ EvJobThumbnail *job_thumb)
+{
+ if (webkit_web_view_get_load_status(webview) != WEBKIT_LOAD_FINISHED) {
+ return;
+ }
+ EvPage *page = ev_document_get_page (EV_JOB(job_thumb)->document, job_thumb->page);
+ job_thumb->surface = webkit_web_view_get_snapshot (WEBKIT_WEB_VIEW(webview));
+ EvRenderContext *rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ EvPage *screenshotpage;
+ screenshotpage = ev_page_new(job_thumb->page);
+ screenshotpage->backend_page = (EvBackendPage)job_thumb->surface;
+ screenshotpage->backend_destroy_func = (EvBackendPageDestroyFunc)cairo_surface_destroy ;
+ ev_render_context_set_page(rc,screenshotpage);
+
+ job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB(job_thumb)->document),
+ rc, TRUE);
+ g_object_unref(screenshotpage);
+ g_object_unref(rc);
+
+ ev_document_doc_mutex_unlock();
+ ev_job_succeeded(EV_JOB(job_thumb));
+}
+#else
+
+static void
+snapshot_callback(WebKitWebView *webview,
+ GAsyncResult *results,
+ EvJobThumbnail *job_thumb)
+{
+ EvPage *page = ev_document_get_page (EV_JOB(job_thumb)->document, job_thumb->page);
+ job_thumb->surface = webkit_web_view_get_snapshot_finish (webview,
+ results,
+ NULL);
+ EvRenderContext *rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ EvPage *screenshotpage;
+ screenshotpage = ev_page_new(job_thumb->page);
+ screenshotpage->backend_page = (EvBackendPage)job_thumb->surface;
+ screenshotpage->backend_destroy_func = (EvBackendPageDestroyFunc)cairo_surface_destroy ;
+ ev_render_context_set_page(rc,screenshotpage);
+
+ job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB(job_thumb)->document),
+ rc, TRUE);
+ g_object_unref(screenshotpage);
+ g_object_unref(rc);
+
+ ev_document_doc_mutex_unlock();
+ ev_job_succeeded(EV_JOB(job_thumb));
+}
+
+static void
+web_thumbnail_get_screenshot_cb (WebKitWebView *webview,
+ WebKitLoadEvent event,
+ EvJobThumbnail *job_thumb)
+{
+ if (event != WEBKIT_LOAD_FINISHED) {
+ return;
+ }
+
+ webkit_web_view_get_snapshot (webview,
+ WEBKIT_SNAPSHOT_REGION_VISIBLE,
+ WEBKIT_SNAPSHOT_OPTIONS_NONE,
+ NULL,
+ (GAsyncReadyCallback)snapshot_callback,
+ g_object_ref(job_thumb));
+}
+#endif
+
static gboolean
ev_job_thumbnail_run (EvJob *job)
{
EvJobThumbnail *job_thumb = EV_JOB_THUMBNAIL (job);
EvRenderContext *rc;
EvPage *page;
-
ev_debug_message (DEBUG_JOBS, "%d (%p)", job_thumb->page, job);
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
-
- ev_document_doc_mutex_lock ();
+
+ if (job->document->iswebdocument) {
+ /* Do not block the main loop */
+ if (!ev_document_doc_mutex_trylock ())
+ return TRUE;
+ }
+ else {
+ ev_document_doc_mutex_lock ();
+ }
page = ev_document_get_page (job->document, job_thumb->page);
- rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ if (job->document->iswebdocument == TRUE ) {
+ rc = ev_render_context_new (page, 0, job_thumb->scale);
+ }
+ else {
+ rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ }
g_object_unref (page);
- job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
- rc, TRUE);
- g_object_unref (rc);
- ev_document_doc_mutex_unlock ();
+ if (job->document->iswebdocument == TRUE) {
+ if (!webview) {
+ webview = webkit_web_view_new();
+ }
+
+ if (!offscreenwindow) {
+ offscreenwindow = gtk_offscreen_window_new();
+
+ gtk_container_add(GTK_CONTAINER(offscreenwindow),GTK_WIDGET(webview));
+
+ gtk_window_set_default_size (GTK_WINDOW(offscreenwindow),800,1080);
+
+ gtk_widget_show_all(offscreenwindow);
+ }
+
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)rc->page->backend_page);
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_connect(WEBKIT_WEB_VIEW(webview),"notify::load-status",
+ G_CALLBACK(web_thumbnail_get_screenshot_cb),
+ g_object_ref(job_thumb));
+#else
+ g_signal_connect(WEBKIT_WEB_VIEW(webview),"load-changed",
+ G_CALLBACK(web_thumbnail_get_screenshot_cb),
+ g_object_ref(job_thumb));
- ev_job_succeeded (job);
+#endif
+ }
+ else {
+ job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
+ rc, TRUE);
+ ev_document_doc_mutex_unlock ();
+
+ ev_job_succeeded (job);
+ }
+ g_object_unref (rc);
return FALSE;
}
@@ -1185,6 +1326,10 @@ ev_job_find_dispose (GObject *object)
g_free (job->pages);
job->pages = NULL;
}
+
+ if (job->results) {
+ g_free(job->results);
+ }
(* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
}
@@ -1196,7 +1341,6 @@ ev_job_find_run (EvJob *job)
EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
EvPage *ev_page;
GList *matches;
-
ev_debug_message (DEBUG_JOBS, NULL);
/* Do not block the main loop */
@@ -1210,16 +1354,30 @@ ev_job_find_run (EvJob *job)
#endif
ev_page = ev_document_get_page (job->document, job_find->current_page);
- matches = ev_document_find_find_text (find, ev_page, job_find->text,
- job_find->case_sensitive);
+
+ if (job->document->iswebdocument) {
+ job_find->results[job_find->current_page] = ev_document_find_check_for_hits(find, ev_page, job_find->text,
+ job_find->case_sensitive);
+ }else {
+ matches = ev_document_find_find_text (find, ev_page, job_find->text,
+ job_find->case_sensitive);
+ }
+
g_object_unref (ev_page);
ev_document_doc_mutex_unlock ();
- if (!job_find->has_results)
+ if (!job_find->has_results && !job->document->iswebdocument) {
job_find->has_results = (matches != NULL);
+ }
+ else if (!job_find->has_results && job->document->iswebdocument){
+ job_find->has_results = (job_find->results[job_find->current_page] > 0);
+ }
+
+ if (job->document->iswebdocument == FALSE) {
+ job_find->pages[job_find->current_page] = matches;
+ }
- job_find->pages[job_find->current_page] = matches;
g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
@@ -1269,7 +1427,13 @@ ev_job_find_new (EvDocument *document,
job->start_page = start_page;
job->current_page = start_page;
job->n_pages = n_pages;
- job->pages = g_new0 (GList *, n_pages);
+
+ if (document->iswebdocument) {
+ job->results = g_malloc0 (sizeof(guint) *n_pages);
+ }
+ else {
+ job->pages = g_new0 (GList *, n_pages);
+ }
job->text = g_strdup (text);
job->case_sensitive = case_sensitive;
job->has_results = FALSE;
@@ -1281,7 +1445,12 @@ gint
ev_job_find_get_n_results (EvJobFind *job,
gint page)
{
- return g_list_length (job->pages[page]);
+ if (EV_JOB(job)->document->iswebdocument) {
+ return job->results[page];
+ }
+ else {
+ return g_list_length (job->pages[page]);
+ }
}
gdouble
diff --git a/libview/ev-jobs.h b/libview/ev-jobs.h
index e6ae4552..fdc23bae 100644
--- a/libview/ev-jobs.h
+++ b/libview/ev-jobs.h
@@ -45,6 +45,9 @@ typedef struct _EvJobPageDataClass EvJobPageDataClass;
typedef struct _EvJobThumbnail EvJobThumbnail;
typedef struct _EvJobThumbnailClass EvJobThumbnailClass;
+typedef struct _EvJobWebThumbnail EvJobWebThumbnail;
+typedef struct _EvJobWebThumbnailClass EvJobWebThumbnailClass;
+
typedef struct _EvJobLinks EvJobLinks;
typedef struct _EvJobLinksClass EvJobLinksClass;
@@ -111,6 +114,11 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_JOB_THUMBNAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_THUMBNAIL, EvJobThumbnailClass))
#define EV_IS_JOB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_THUMBNAIL))
+#define EV_TYPE_JOB_WEB_THUMBNAIL (ev_job_web_thumbnail_get_type())
+#define EV_JOB_WEB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_WEB_THUMBNAIL, EvJobWebThumbnail))
+#define EV_JOB_WEB_THUMBNAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_WEB_THUMBNAIL, EvJobWebThumbnailClass))
+#define EV_IS_JOB_WEB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_WEB_THUMBNAIL))
+
#define EV_TYPE_JOB_FONTS (ev_job_fonts_get_type())
#define EV_JOB_FONTS(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_FONTS, EvJobFonts))
#define EV_JOB_FONTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_FONTS, EvJobFontsClass))
@@ -281,11 +289,10 @@ struct _EvJobPageDataClass
struct _EvJobThumbnail
{
EvJob parent;
-
gint page;
gint rotation;
gdouble scale;
-
+ cairo_surface_t *surface;
GdkPixbuf *thumbnail;
};
@@ -343,6 +350,7 @@ struct _EvJobFind
gint current_page;
gint n_pages;
GList **pages;
+ guint *results;
gchar *text;
gboolean case_sensitive;
gboolean has_results;
@@ -450,6 +458,7 @@ EvJob *ev_job_thumbnail_new (EvDocument *document,
gint page,
gint rotation,
gdouble scale);
+
/* EvJobFonts */
GType ev_job_fonts_get_type (void) G_GNUC_CONST;
EvJob *ev_job_fonts_new (EvDocument *document);
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 7bb56cae..ec378758 100644..100755
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -6568,3 +6568,41 @@ ev_view_previous_page (EvView *view)
}
}
+/**
+ * ev_view_disconnect_handlers
+ * @view: #EvView instance
+ *
+ * Disconnect all signal handlers from the model, to ensure error free operation of the webview,
+ * we have an equivalent function for the webview.
+ */
+void
+ev_view_disconnect_handlers(EvView *view)
+{
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_rotation_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_inverted_colors_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_sizing_mode_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_scale_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_continuous_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_dual_page_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_fullscreen_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_page_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_document_changed_cb),
+ view);
+} \ No newline at end of file
diff --git a/libview/ev-view.h b/libview/ev-view.h
index 402b9895..0a9e1718 100644..100755
--- a/libview/ev-view.h
+++ b/libview/ev-view.h
@@ -110,6 +110,8 @@ void ev_view_begin_add_annotation (EvView *view,
EvAnnotationType annot_type);
void ev_view_cancel_add_annotation (EvView *view);
+/*For epub*/
+void ev_view_disconnect_handlers (EvView *view);
G_END_DECLS
#endif /* __EV_VIEW_H__ */
diff --git a/libview/ev-web-view.c b/libview/ev-web-view.c
new file mode 100644
index 00000000..b1fe3b08
--- /dev/null
+++ b/libview/ev-web-view.c
@@ -0,0 +1,874 @@
+/* this file is part of atril, a mate document viewer
+ *
+ * Copyright (C) 2014 Avishkar Gupta
+ * Based on ev-view.c, also a part of atril, a mate document viewer.
+ *
+ * Atril 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Atril 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 <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <stdlib.h>
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+#include <webkit2/webkit2.h>
+#else
+#include <webkit/webkit.h>
+#endif
+
+#include "ev-web-view.h"
+#include "ev-document-model.h"
+#include "ev-jobs.h"
+
+#define EV_WEB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_WEB_VIEW, EvWebViewClass))
+#define EV_IS_WEB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_WEB_VIEW))
+#define EV_WEB_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_WEB_VIEW, EvWebViewClass))
+
+ typedef enum {
+ EV_WEB_VIEW_FIND_NEXT,
+ EV_WEB_VIEW_FIND_PREV
+ } EvWebViewFindDirection;
+
+typedef struct _SearchParams {
+ gboolean case_sensitive;
+ gchar* search_string;
+ EvWebViewFindDirection direction;
+ gboolean search_jump;
+ gint on_result;
+ guint *results;
+}SearchParams;
+
+struct _EvWebView
+{
+ WebKitWebView web_view;
+ EvDocument *document;
+ EvDocumentModel *model;
+ gint current_page;
+ gboolean inverted_colors ;
+ gboolean fullscreen;
+ SearchParams *search;
+#if GTK_CHECK_VERSION (3, 0, 0)
+ WebKitFindController *findcontroller;
+ WebKitFindOptions findoptions;
+ gdouble zoom_level;
+#endif
+ gchar *hlink;
+};
+
+struct _EvWebViewClass
+{
+ WebKitWebViewClass base_class;
+};
+
+/*** Callbacks ***/
+static void ev_web_view_change_page (EvWebView *webview,
+ gint new_page);
+
+static void ev_web_view_page_changed_cb (EvDocumentModel *model,
+ gint old_page,
+ gint new_page,
+ EvWebView *webview);
+/*** GObject ***/
+static void ev_web_view_dispose (GObject *object);
+
+static void ev_web_view_finalize (GObject *object);
+static void ev_web_view_class_init (EvWebViewClass *klass);
+static void ev_web_view_init (EvWebView *webview);
+
+G_DEFINE_TYPE (EvWebView, ev_web_view, WEBKIT_TYPE_WEB_VIEW)
+
+static void
+web_view_update_range_and_current_page (EvWebView *webview)
+{
+ g_return_if_fail(EV_IS_WEB_VIEW(webview));
+
+ if (ev_document_get_n_pages (webview->document) <= 0)
+ return;
+
+ ev_document_model_set_page(webview->model, 0);
+ webview->current_page = 0;
+ EvPage *webpage = ev_document_get_page(webview->document,0);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+}
+
+static void
+ev_web_view_dispose (GObject *object)
+{
+ EvWebView *webview = EV_WEB_VIEW (object);
+
+ if (webview->document) {
+ g_object_unref(webview->document);
+ webview->document = NULL ;
+ }
+
+ if (webview->model) {
+ g_object_unref(webview->model);
+ webview->model = NULL;
+ }
+
+ if (webview->hlink) {
+ g_free(webview->hlink);
+ webview->hlink = NULL;
+ }
+
+ if (webview->search) {
+ g_free(webview->search);
+ webview->search = NULL;
+ }
+
+ G_OBJECT_CLASS (ev_web_view_parent_class)->dispose (object);
+}
+
+static void
+ev_web_view_class_init (EvWebViewClass *klass)
+{
+ G_OBJECT_CLASS(klass)->finalize = ev_web_view_finalize;
+ G_OBJECT_CLASS(klass)->dispose = ev_web_view_dispose;
+}
+
+static void
+ev_web_view_init (EvWebView *webview)
+{
+ gtk_widget_set_can_focus (GTK_WIDGET (webview), TRUE);
+
+ gtk_widget_set_has_window (GTK_WIDGET (webview), TRUE);
+
+ webview->current_page = 0;
+
+ webview->search = g_new0(SearchParams, 1);
+ webview->search->search_string = NULL;
+
+ webview->search->on_result = -1 ;
+ webview->search->results = NULL;
+ webview->search->search_jump = TRUE ;
+
+ webview->fullscreen = FALSE;
+
+ webview->hlink = NULL;
+}
+
+static void
+ev_web_view_finalize (GObject *object)
+{
+ G_OBJECT_CLASS(ev_web_view_parent_class)->finalize(object);
+}
+
+/*** Callbacks ***/
+
+static void
+ev_web_view_change_page (EvWebView *webview,
+ gint new_page)
+{
+ g_return_if_fail(EV_IS_WEB_VIEW(webview));
+
+ EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS(webview->document);
+
+ webview->current_page = new_page;
+ ev_document_model_set_page(webview->model,new_page);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_finish(webview->findcontroller);
+#else
+ webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW(webview));
+#endif
+ if (webview->hlink) {
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webview->hlink);
+ g_free(webview->hlink);
+ webview->hlink = NULL;
+ }
+ else {
+ EvPage *page = klass->get_page(webview->document,new_page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)page->backend_page);
+ }
+}
+
+static void
+ev_web_view_page_changed_cb (EvDocumentModel *model,
+ gint old_page,
+ gint new_page,
+ EvWebView *webview)
+{
+ if (!webview->document)
+ return;
+
+ if (webview->current_page != new_page) {
+ ev_web_view_change_page (webview, new_page);
+ } else {
+ webkit_web_view_reload (WEBKIT_WEB_VIEW(webview));
+ }
+}
+
+GtkWidget*
+ev_web_view_new (void)
+{
+ GtkWidget *webview;
+
+ webview = g_object_new (EV_TYPE_WEB_VIEW, NULL);
+
+ #if GTK_CHECK_VERSION (3, 0, 0)
+ EV_WEB_VIEW(webview)->findcontroller = webkit_web_view_get_find_controller (WEBKIT_WEB_VIEW(webview));
+ EV_WEB_VIEW(webview)->findoptions = webkit_find_controller_get_options (EV_WEB_VIEW(webview)->findcontroller);
+
+ EV_WEB_VIEW(webview)->zoom_level = 1.0;
+
+ EV_WEB_VIEW(webview)->findoptions |= WEBKIT_FIND_OPTIONS_NONE;
+ #endif
+
+ return webview;
+}
+
+static void
+ev_web_view_document_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvWebView *webview)
+{
+ g_return_if_fail(EV_IS_WEB_VIEW(webview));
+
+ EvDocument *document = ev_document_model_get_document (model);
+
+ if (document != webview->document) {
+
+ if (webview->document )
+ g_object_unref(webview->document);
+
+ webview->document = document ;
+
+ if(webview->document) {
+ g_object_ref(webview->document);
+ }
+
+ gint current_page = ev_document_model_get_page(model);
+
+ ev_web_view_change_page (webview, current_page);
+
+ }
+}
+
+static void
+ev_web_view_inverted_colors_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvWebView *webview)
+{
+ guint inverted_colors = ev_document_model_get_inverted_colors (model);
+ inverted_colors = !inverted_colors;
+ /*TODO*/
+}
+
+static void
+ev_web_view_fullscreen_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvWebView *webview)
+{
+ gboolean fullscreen = ev_document_model_get_fullscreen (model);
+
+ webview->fullscreen = fullscreen;
+#if GTK_CHECK_VERSION (3, 0, 0)
+ WebKitWindowProperties *window_properties =
+ webkit_web_view_get_window_properties (WEBKIT_WEB_VIEW(webview));
+
+ webkit_window_properties_get_fullscreen(window_properties);
+ /*TODO*/
+#else
+ webkit_web_view_set_view_mode(WEBKIT_WEB_VIEW(webview), WEBKIT_WEB_VIEW_VIEW_MODE_FULLSCREEN);
+#endif
+}
+void
+ev_web_view_set_model (EvWebView *webview,
+ EvDocumentModel *model)
+{
+ g_return_if_fail (EV_IS_WEB_VIEW (webview));
+ g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
+
+ if (model == webview->model)
+ return;
+
+ if (webview->model) {
+ g_signal_handlers_disconnect_by_func (webview->model,
+ ev_web_view_document_changed_cb,
+ webview);
+ g_signal_handlers_disconnect_by_func (webview->model,
+ ev_web_view_page_changed_cb,
+ webview);
+ g_object_unref (webview->model);
+ }
+ webview->model = g_object_ref (model);
+
+ /* Initialize webview from model */
+ webview->fullscreen = ev_document_model_get_fullscreen (webview->model);
+ webview->document = ev_document_model_get_document(webview->model);
+ webview->inverted_colors = ev_document_model_get_inverted_colors(webview->model);
+ ev_web_view_document_changed_cb (webview->model, NULL, webview);
+
+ g_signal_connect (webview->model, "notify::document",
+ G_CALLBACK (ev_web_view_document_changed_cb),
+ webview);
+ g_signal_connect (webview->model, "notify::inverted-colors",
+ G_CALLBACK (ev_web_view_inverted_colors_changed_cb),
+ webview);
+ g_signal_connect (webview->model,"page-changed",
+ G_CALLBACK(ev_web_view_page_changed_cb),
+ webview);
+}
+
+void
+ev_web_view_reload_page (EvWebView *webview,
+ gint page)
+{
+ webkit_web_view_reload (WEBKIT_WEB_VIEW(webview));
+}
+
+void
+ev_web_view_reload (EvWebView *webview)
+{
+ web_view_update_range_and_current_page (webview);
+}
+
+
+gboolean
+ev_web_view_next_page (EvWebView *webview)
+{
+ int page, n_pages;
+
+ g_return_val_if_fail (EV_IS_WEB_VIEW (webview), FALSE);
+
+ if (!webview->document)
+ return FALSE;
+
+ page = ev_document_model_get_page (webview->model);
+ n_pages = ev_document_get_n_pages (webview->document);
+
+ page = page + 1;
+
+ if (page < n_pages) {
+ ev_document_model_set_page (webview->model, page);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webview->current_page = page ;
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else if (page == n_pages) {
+ ev_document_model_set_page (webview->model, page - 1);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+gboolean
+ev_web_view_previous_page (EvWebView *webview)
+{
+ int page;
+
+ g_return_val_if_fail (EV_IS_WEB_VIEW (webview), FALSE);
+
+ if (!webview->document)
+ return FALSE;
+
+ page = ev_document_model_get_page (webview->model);
+
+ page = page - 1 ;
+
+ if (page >= 0) {
+ ev_document_model_set_page (webview->model, page);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else if (page == -1) {
+ ev_document_model_set_page (webview->model, 0);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+void
+ev_web_view_handle_link(EvWebView *webview,EvLink *link)
+{
+ EvLinkAction *action = NULL;
+ EvLinkDest *dest = NULL;
+ EvLinkDestType dest_type ;
+ action = ev_link_get_action(link);
+
+ if (action == NULL)
+ return;
+
+ dest = ev_link_action_get_dest(action);
+
+ if (dest == NULL)
+ return;
+
+ dest_type = ev_link_dest_get_dest_type(dest);
+
+ switch(dest_type) {
+ case EV_LINK_DEST_TYPE_PAGE: {
+ ev_document_model_set_page(webview->model,ev_link_dest_get_page(dest));
+ break;
+ }
+
+ case EV_LINK_DEST_TYPE_PAGE_LABEL: {
+ const gchar *text = ev_link_dest_get_page_label (dest);
+ gint page = atoi(text);
+
+ if (page <= ev_document_get_n_pages(webview->document) && page > 0) {
+ ev_document_model_set_page(webview->model,page-1);
+ }
+ break;
+ }
+ case EV_LINK_DEST_TYPE_HLINK: {
+ const gchar *uri = ev_link_dest_get_named_dest(dest);
+ ev_document_model_set_page(webview->model,ev_link_dest_get_page(dest));
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),uri);
+ break;
+
+ default:return;
+ }
+ }
+}
+/* Searching */
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+static void
+jump_to_find_result_on_page(EvWebView *webview,
+ EvWebViewFindDirection direction)
+{
+ gboolean forward,wrap;
+
+ if (direction == EV_WEB_VIEW_FIND_NEXT) {
+ forward = TRUE;
+ wrap = FALSE;
+ }
+ else {
+ forward = FALSE;
+ wrap = FALSE;
+ }
+
+ if (webview->search->search_jump) {
+ wrap = TRUE;
+ }
+ webkit_web_view_search_text (WEBKIT_WEB_VIEW(webview),
+ webview->search->search_string,
+ webview->search->case_sensitive,
+ forward,
+ wrap);
+
+ webview->search->search_jump = FALSE;
+}
+#endif
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void
+results_counted_cb(WebKitFindController *findcontroller,
+ guint match_count,
+ EvWebView *webview)
+{
+ if (match_count > 0 && webview->search->on_result < match_count) {
+ webkit_find_controller_search(findcontroller,
+ webview->search->search_string,
+ webview->findoptions,
+ match_count);
+ webview->search->search_jump = FALSE;
+ }
+}
+#endif
+/*
+ * Jump to find results once we have changed the page in the webview.
+ */
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void
+jump_to_find_results(EvWebView *webview,
+ WebKitLoadEvent load_event,
+ gpointer data)
+#else
+static void
+jump_to_find_results(EvWebView *webview,
+ GParamSpec *pspec,
+ gpointer data)
+#endif
+{
+ #if !GTK_CHECK_VERSION (3, 0, 0)
+ gint n_results;
+ gboolean forward ;
+ gboolean wrap ;
+
+ if (webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(webview)) != WEBKIT_LOAD_FINISHED) {
+ return;
+ }
+#else
+ if ( load_event != WEBKIT_LOAD_FINISHED) {
+ return;
+ }
+#endif
+ if (!webview->search->search_string) {
+ return;
+ }
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ if (webview->search->direction == EV_WEB_VIEW_FIND_NEXT) {
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_BACKWARDS;
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ }
+ else {
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_BACKWARDS;
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ }
+
+ webkit_find_controller_count_matches (webview->findcontroller,
+ webview->search->search_string,
+ webview->findoptions,
+ G_MAXUINT);
+#else
+ n_results = webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW(webview),
+ webview->search->search_string,
+ webview->search->case_sensitive,
+ 0);
+
+ ev_web_view_find_set_highlight_search(webview,TRUE);
+
+ if (webview->search->direction == EV_WEB_VIEW_FIND_NEXT) {
+ forward = TRUE ;
+ wrap = FALSE;
+ }
+ else {
+ forward = FALSE;
+ wrap = TRUE ;
+ }
+
+ if (n_results > 0 && webview->search->on_result < n_results) {
+ webkit_web_view_search_text (WEBKIT_WEB_VIEW(webview),
+ webview->search->search_string,
+ webview->search->case_sensitive,
+ forward,
+ wrap);
+
+ webview->search->search_jump = FALSE;
+ }
+#endif
+ webview->search->search_jump = FALSE;
+}
+
+static gint
+ev_web_view_find_get_n_results (EvWebView *webview, gint page)
+{
+ return webview->search->results[page];
+}
+
+/**
+ * jump_to_find_page
+ * @webview: #EvWebView instance
+ * @direction: Direction to look
+ * @shift: Shift from current page
+ *
+ * Jumps to the first page that has occurences of searched word.
+ * Uses a direction where to look and a shift from current page.
+**/
+static void
+jump_to_find_page (EvWebView *webview, EvWebViewFindDirection direction, gint shift)
+{
+ int n_pages, i;
+
+ n_pages = ev_document_get_n_pages (webview->document);
+
+ for (i = 0; i < n_pages; i++) {
+ int page;
+
+ if (direction == EV_WEB_VIEW_FIND_NEXT)
+ page = webview->current_page + i;
+ else
+ page = webview->current_page - i;
+ page += shift;
+
+ if (page >= n_pages) {
+ page = page - n_pages;
+ } else if (page < 0)
+ page = page + n_pages;
+
+ if (page == webview->current_page && ev_web_view_find_get_n_results(webview,page) > 0) {
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ jump_to_find_result_on_page(webview,EV_WEB_VIEW_FIND_NEXT);
+#else
+ if (direction == EV_WEB_VIEW_FIND_PREV) {
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_BACKWARDS;
+ }
+ else {
+ if (webview->search->search_jump)
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ else
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_BACKWARDS;
+ }
+
+ webkit_find_controller_search (webview->findcontroller,
+ webview->search->search_string,
+ webview->findoptions,
+ /*Highlight all the results.*/
+ G_MAXUINT);
+ webview->search->search_jump = FALSE;
+#endif
+ break;
+ }
+
+ if (ev_web_view_find_get_n_results (webview, page) > 0) {
+ webview->search->direction = direction;
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW(webview));
+#else
+ webkit_find_controller_search_finish(webview->findcontroller);
+#endif
+ ev_document_model_set_page (webview->model, page);
+ break;
+ }
+ }
+}
+
+void
+ev_web_view_find_changed (EvWebView *webview, guint *results, gchar *text,gboolean case_sensitive)
+{
+ webview->search->results = results;
+ webview->search->on_result = 0;
+ webview->search->search_string = g_strdup(text);
+ webview->search->case_sensitive = case_sensitive;
+ if (webview->search->search_jump == TRUE) {
+#if GTK_CHECK_VERSION (3, 0, 0)
+ if (!case_sensitive) {
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
+ }
+ else {
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
+ }
+#endif
+ jump_to_find_page (webview, EV_WEB_VIEW_FIND_NEXT, 0);
+ }
+}
+
+void
+ev_web_view_find_next (EvWebView *webview)
+{
+ gint n_results;
+
+ n_results = ev_web_view_find_get_n_results (webview, webview->current_page);
+ webview->search->on_result++;
+
+ if (webview->search->on_result >= n_results) {
+ webview->search->on_result = 0;
+ jump_to_find_page (webview, EV_WEB_VIEW_FIND_NEXT, 1);
+ }
+ else {
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_next(webview->findcontroller);
+#else
+ jump_to_find_result_on_page (webview, EV_WEB_VIEW_FIND_NEXT);
+#endif
+ }
+}
+
+void
+ev_web_view_find_previous (EvWebView *webview)
+{
+ webview->search->on_result--;
+
+ if (webview->search->on_result < 0) {
+ jump_to_find_page (webview, EV_WEB_VIEW_FIND_PREV, -1);
+ webview->search->on_result = MAX (0, ev_web_view_find_get_n_results (webview, webview->current_page) - 1);
+ } else {
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_previous(webview->findcontroller);
+#else
+ jump_to_find_result_on_page (webview,EV_WEB_VIEW_FIND_PREV);
+#endif
+ }
+}
+
+void
+ev_web_view_find_search_changed (EvWebView *webview)
+{
+ /* search string has changed, focus on new search result */
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(webview));
+#endif
+ if (webview->search->search_string) {
+ g_free(webview->search->search_string);
+ webview->search->search_string = NULL;
+ }
+#if GTK_CHECK_VERSION(3, 0, 0)
+ webkit_find_controller_search_finish(webview->findcontroller);
+#endif
+
+ webview->search->search_jump = TRUE;
+}
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+void
+ev_web_view_find_set_highlight_search (EvWebView *webview, gboolean value)
+{
+ webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW(webview),value);
+}
+#endif
+
+void
+ev_web_view_find_cancel (EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_finish (webview->findcontroller);
+#else
+ webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(webview));
+ ev_web_view_find_set_highlight_search(webview,FALSE);
+#endif
+}
+
+
+
+void
+ev_web_view_set_handler(EvWebView *webview,gboolean visible)
+{
+ if (visible) {
+ g_signal_connect(webview,
+#if GTK_CHECK_VERSION (3, 0, 0)
+ "load-changed",
+#else
+ "notify::load-status",
+#endif
+ G_CALLBACK(jump_to_find_results),
+ NULL);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_connect(webview->findcontroller,
+ "counted-matches",
+ G_CALLBACK(results_counted_cb),
+ webview);
+#endif
+ }
+ else {
+ g_signal_handlers_disconnect_by_func(webview,
+ jump_to_find_results,
+ NULL);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_handlers_disconnect_by_func(webview,
+ results_counted_cb,
+ NULL);
+#endif
+ }
+}
+
+/* Selection and copying*/
+#if !GTK_CHECK_VERSION (3, 0, 0)
+gboolean
+ev_web_view_get_has_selection(EvWebView *webview)
+{
+ return webkit_web_view_has_selection(WEBKIT_WEB_VIEW(webview));
+}
+#endif
+
+void
+ev_web_view_select_all(EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_web_view_execute_editing_command(WEBKIT_WEB_VIEW(webview),
+ WEBKIT_EDITING_COMMAND_SELECT_ALL);
+#else
+ webkit_web_view_select_all(WEBKIT_WEB_VIEW(webview));
+#endif
+}
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void
+copy_text_cb(WebKitWebView *webview,
+ GAsyncResult *res,
+ gpointer data)
+{
+ gboolean okay_to_copy = webkit_web_view_can_execute_editing_command_finish (WEBKIT_WEB_VIEW(webview),
+ res,
+ NULL);
+
+ if (okay_to_copy) {
+ webkit_web_view_execute_editing_command (WEBKIT_WEB_VIEW(webview),
+ WEBKIT_EDITING_COMMAND_COPY);
+ }
+}
+#endif
+
+void
+ev_web_view_copy(EvWebView *webview)
+{
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ /* If for some reason we don't have a selection any longer,best to be safe */
+ if (ev_web_view_get_has_selection(webview) == FALSE)
+ return;
+ if (webkit_web_view_can_copy_clipboard(WEBKIT_WEB_VIEW(webview))) {
+ webkit_web_view_copy_clipboard(WEBKIT_WEB_VIEW(webview));
+ }
+#else
+ webkit_web_view_can_execute_editing_command(WEBKIT_WEB_VIEW(webview),
+ WEBKIT_EDITING_COMMAND_COPY,
+ NULL,
+ (GAsyncReadyCallback)copy_text_cb,
+ NULL);
+
+#endif
+
+}
+
+/*Zoom control*/
+gboolean
+ev_web_view_zoom_in(EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(webview),
+ (webview->zoom_level+= 0.1));
+#else
+ webkit_web_view_zoom_in(WEBKIT_WEB_VIEW(webview));
+#endif
+ return TRUE;
+}
+
+gboolean
+ev_web_view_zoom_out(EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ if (webview->zoom_level == 1)
+ return FALSE;
+
+ webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(webview),
+ (webview->zoom_level -= 0.1));
+#else
+ webkit_web_view_zoom_out(WEBKIT_WEB_VIEW(webview));
+#endif
+ return TRUE;
+}
+
+/**
+ * ev_web_view_disconnect_handlers
+ * @webview : #EvWebView instance
+ *
+ * This function call will disconnect all model signal handlers from the webview, to ensure smooth operation of the Atril-view.
+ * Equivalent to function ev_view_disconnect_handlers in ev-view.c
+ */
+void
+ev_web_view_disconnect_handlers(EvWebView *webview)
+{
+ g_signal_handlers_disconnect_by_func(webview->model,
+ ev_web_view_document_changed_cb,
+ webview);
+ g_signal_handlers_disconnect_by_func(webview->model,
+ ev_web_view_inverted_colors_changed_cb,
+ webview);
+ g_signal_handlers_disconnect_by_func(webview->model,
+ ev_web_view_page_changed_cb,
+ webview);
+} \ No newline at end of file
diff --git a/libview/ev-web-view.h b/libview/ev-web-view.h
new file mode 100644
index 00000000..74b7eb6b
--- /dev/null
+++ b/libview/ev-web-view.h
@@ -0,0 +1,89 @@
+/* this file is part of atril, a mate document viewer
+ *
+ * Copyright (C) 2014 Avishkar Gupta
+ * Based on ev-view.h, also a part of atril, a mate document viewer
+ *
+ * Atril 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Atril 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.
+ */
+
+#if !defined (__EV_ATRIL_VIEW_H_INSIDE__) && !defined (ATRIL_COMPILATION)
+#error "Only <atril-web_view.h> can be included directly."
+#endif
+
+#ifndef __EV_WEB_VIEW_H__
+#define __EV_WEB_VIEW_H__
+
+#include <gtk/gtk.h>
+
+#include <atril-document.h>
+#include "ev-jobs.h"
+#include "ev-document-model.h"
+#include <glib-object.h>
+G_BEGIN_DECLS
+
+
+typedef struct _EvWebView EvWebView;
+typedef struct _EvWebViewClass EvWebViewClass;
+
+#define EV_TYPE_WEB_VIEW (ev_web_view_get_type ())
+#define EV_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_WEB_VIEW, EvWebView))
+#define EV_IS_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_WEB_VIEW))
+
+GType ev_web_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget* ev_web_view_new (void);
+
+void ev_web_view_set_model (EvWebView *webview,
+ EvDocumentModel *model);
+
+void ev_web_view_reload (EvWebView *webview);
+
+void ev_web_view_reload_page (EvWebView *webview,
+ gint page);
+
+/* Navigation */
+gboolean ev_web_view_next_page (EvWebView *webview);
+gboolean ev_web_view_previous_page (EvWebView *webview);
+
+/* Sidebar links */
+void ev_web_view_handle_link (EvWebView *webview, EvLink* link);
+
+/* Searching */
+void ev_web_view_find_next (EvWebView *webview);
+void ev_web_view_find_previous (EvWebView *webview);
+
+void ev_web_view_find_changed (EvWebView *webview,
+ guint *results,
+ gchar *text,
+ gboolean case_sensitive);
+
+void ev_web_view_find_search_changed (EvWebView *webview);
+void ev_web_view_find_cancel (EvWebView *webview);
+void ev_web_view_find_set_highlight_search (EvWebView *webview,gboolean visible);
+void ev_web_view_set_handler (EvWebView *webview,gboolean visible);
+/* Selection */
+gboolean ev_web_view_get_has_selection (EvWebView *webview);
+void ev_web_view_select_all (EvWebView *webview);
+void ev_web_view_copy (EvWebView *webview);
+
+/* Zoom control */
+gboolean ev_web_view_zoom_in (EvWebView *webview);
+gboolean ev_web_view_zoom_out (EvWebView *webview);
+
+/*For safe replacement by an EvView*/
+void ev_web_view_disconnect_handlers (EvWebView *webview);
+G_END_DECLS
+
+#endif /* __EV_WEB_VIEW_H__ */
diff --git a/previewer/Makefile.am b/previewer/Makefile.am
index 756446c4..5ac0d110 100644
--- a/previewer/Makefile.am
+++ b/previewer/Makefile.am
@@ -21,7 +21,8 @@ atril_previewer_CFLAGS = \
$(PREVIEWER_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED) \
- $(AM_CFLAGS)
+ $(AM_CFLAGS) \
+ $(WEBKIT_CFLAGS)
atril_previewer_LDFLAGS = $(AM_LDFLAGS)
@@ -33,7 +34,8 @@ atril_previewer_LDADD = \
$(top_builddir)/libdocument/libatrildocument.la \
$(top_builddir)/libview/libatrilview.la \
$(top_builddir)/libmisc/libevmisc.la \
- $(PREVIEWER_LIBS)
+ $(PREVIEWER_LIBS) \
+ $(WEBKIT_LIBS)
EXTRA_DIST = $(man_MANS)
diff --git a/shell/Makefile.am b/shell/Makefile.am
index cd123aad..aff9fde0 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -20,6 +20,7 @@ AM_CPPFLAGS= \
-DATRIL_COMPILATION \
$(SHELL_CFLAGS) \
$(WARN_CFLAGS) \
+ $(WEBKIT_CFLAGS) \
$(DISABLE_DEPRECATED)
bin_PROGRAMS=atril
@@ -109,7 +110,8 @@ atril_LDADD= \
$(top_builddir)/libdocument/libatrildocument.la \
$(top_builddir)/libview/libatrilview.la \
$(top_builddir)/libmisc/libevmisc.la \
- $(SHELL_LIBS)
+ $(SHELL_LIBS) \
+ $(WEBKIT_LIBS)
if PLATFORM_WIN32
atril_LDADD += atril-icon.o
diff --git a/shell/ev-convert-metadata.c b/shell/ev-convert-metadata.c
index 5664253b..72431dd5 100644
--- a/shell/ev-convert-metadata.c
+++ b/shell/ev-convert-metadata.c
@@ -26,7 +26,7 @@
#include <glib/gi18n.h>
#include <string.h>
#include <libxml/tree.h>
-
+#include <X11/Xlib.h>
#define EV_METADATA_NAMESPACE "metadata::atril"
typedef struct {
@@ -294,7 +294,7 @@ main (gint argc, gchar **argv)
g_printerr ("%s\n", "Usage: atril-convert-metadata FILE");
return 1;
}
-
+ XInitThreads();
gtk_init (&argc, &argv);
if (!convert_metadata_file (argv[1]))
diff --git a/shell/ev-sidebar-thumbnails.c b/shell/ev-sidebar-thumbnails.c
index ec03d998..a6102355 100644
--- a/shell/ev-sidebar-thumbnails.c
+++ b/shell/ev-sidebar-thumbnails.c
@@ -68,7 +68,6 @@ struct _EvSidebarThumbnailsPrivate {
EvDocument *document;
EvDocumentModel *model;
EvThumbsSizeCache *size_cache;
-
gint n_pages, pages_done;
int rotation;
@@ -136,8 +135,14 @@ ev_thumbnails_size_cache_new (EvDocument *document)
page = ev_document_get_page (document, i);
- ev_document_get_page_size (document, i, &page_width, &page_height);
-
+ if (document->iswebdocument == FALSE ) {
+ ev_document_get_page_size (document, i, &page_width, &page_height);
+ }
+ else {
+ /* Hardcoding these values to a large enough dimesnsion so as to achieve max content without loss in visibility*/
+ page_width = 800;
+ page_height = 1080;
+ }
if (!rc) {
rc = ev_render_context_new (page, 0, (gdouble)THUMBNAIL_WIDTH / page_width);
} else {
@@ -368,6 +373,7 @@ clear_range (EvSidebarThumbnails *sidebar_thumbnails,
result && start_page <= end_page;
result = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->list_store), &iter), start_page ++) {
EvJobThumbnail *job;
+
GdkPixbuf *loading_icon = NULL;
gint width, height;
@@ -409,9 +415,12 @@ get_scale_for_page (EvSidebarThumbnails *sidebar_thumbnails,
{
EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
gdouble width;
-
- ev_document_get_page_size (priv->document, page, &width, NULL);
-
+ if (priv->document->iswebdocument == TRUE ) {
+ /* Hardcoded for epub documents*/
+ width = 800;
+ } else {
+ ev_document_get_page_size (priv->document, page, &width, NULL);
+ }
return (gdouble)THUMBNAIL_WIDTH / width;
}
@@ -444,6 +453,11 @@ add_range (EvSidebarThumbnails *sidebar_thumbnails,
job = ev_job_thumbnail_new (priv->document,
page, priv->rotation,
get_scale_for_page (sidebar_thumbnails, page));
+
+ if (priv->document->iswebdocument) {
+ ev_job_set_run_mode(job, EV_JOB_RUN_MAIN_LOOP);
+ }
+
ev_job_scheduler_push_job (EV_JOB (job), EV_JOB_PRIORITY_HIGH);
g_object_set_data_full (G_OBJECT (job), "tree_iter",
diff --git a/shell/ev-window.c b/shell/ev-window.c
index d3a8181d..c1e389b3 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -88,6 +88,7 @@
#include "ev-utils.h"
#include "ev-keyring.h"
#include "ev-view.h"
+#include "ev-web-view.h"
#include "ev-view-presentation.h"
#include "ev-view-type-builtins.h"
#include "ev-window.h"
@@ -142,7 +143,9 @@ struct _EvWindowPrivate {
GtkWidget *sidebar_attachments;
GtkWidget *sidebar_layers;
GtkWidget *sidebar_annots;
-
+#ifdef ENABLE_EPUB
+ GtkWidget *webview;
+#endif
/* Settings */
GSettings *settings;
GSettings *default_settings;
@@ -406,7 +409,9 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
if (has_document && EV_IS_SELECTION (document)) {
can_get_text = TRUE;
}
-
+ else if (has_document && document->iswebdocument) {
+ can_get_text = TRUE;
+ }
if (has_pages && EV_IS_DOCUMENT_FIND (document)) {
can_find = TRUE;
}
@@ -445,18 +450,21 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
ev_window_set_action_sensitive (ev_window, "EditSelectAll", has_pages && can_get_text);
ev_window_set_action_sensitive (ev_window, "EditFind", can_find);
ev_window_set_action_sensitive (ev_window, "Slash", can_find);
- ev_window_set_action_sensitive (ev_window, "EditRotateLeft", has_pages);
- ev_window_set_action_sensitive (ev_window, "EditRotateRight", has_pages);
+ ev_window_set_action_sensitive (ev_window, "EditRotateLeft", has_pages && !(document->iswebdocument));
+ ev_window_set_action_sensitive (ev_window, "EditRotateRight", has_pages && !(document->iswebdocument));
/* View menu */
- ev_window_set_action_sensitive (ev_window, "ViewContinuous", has_pages);
- ev_window_set_action_sensitive (ev_window, "ViewDual", has_pages);
- ev_window_set_action_sensitive (ev_window, "ViewBestFit", has_pages);
- ev_window_set_action_sensitive (ev_window, "ViewPageWidth", has_pages);
+ /*If it has pages it is a document, so our check for a webdocument won't lead to a crash. We need to switch these view modes off since more than one
+ *webview is hard to manage, and would lead to unexpected behaviour in case the number of webviews gets too large.
+ */
+ ev_window_set_action_sensitive (ev_window, "ViewContinuous", has_pages && !(document->iswebdocument));
+ ev_window_set_action_sensitive (ev_window, "ViewDual", has_pages && !(document->iswebdocument));
+ ev_window_set_action_sensitive (ev_window, "ViewBestFit", has_pages && !(document->iswebdocument));
+ ev_window_set_action_sensitive (ev_window, "ViewPageWidth", has_pages && !(document->iswebdocument));
ev_window_set_action_sensitive (ev_window, "ViewReload", has_pages);
- ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages);
+ ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages && !(document->iswebdocument));
ev_window_set_action_sensitive (ev_window, "ViewInvertedColors", has_pages);
- ev_window_set_action_sensitive (ev_window, "ViewExpandWindow", has_pages);
+ ev_window_set_action_sensitive (ev_window, "ViewExpandWindow", has_pages && !(document->iswebdocument));
/* Toolbar-specific actions: */
ev_window_set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
@@ -469,7 +477,9 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
static void
ev_window_update_actions (EvWindow *ev_window)
{
- EvView *view = EV_VIEW (ev_window->priv->view);
+ EvWebView *webview = NULL;
+ EvView *view = NULL;
+
int n_pages = 0, page = -1;
gboolean has_pages = FALSE;
gboolean presentation_mode;
@@ -482,12 +492,36 @@ ev_window_update_actions (EvWindow *ev_window)
has_pages = n_pages > 0;
}
+ if (ev_window->priv->document && ev_window->priv->document->iswebdocument == TRUE ) {
+ webview = EV_WEB_VIEW(ev_window->priv->webview);
+ } else {
+ view = EV_VIEW (ev_window->priv->view);
+ }
+
can_find_in_page = (ev_window->priv->find_job &&
ev_job_find_has_results (EV_JOB_FIND (ev_window->priv->find_job)));
-
- ev_window_set_action_sensitive (ev_window, "EditCopy",
- has_pages &&
- ev_view_get_has_selection (view));
+ if (view) {
+ ev_window_set_action_sensitive (ev_window, "EditCopy",
+ has_pages &&
+ ev_view_get_has_selection (view));
+ }
+#if GTK_CHECK_VERSION (3, 0, 0)
+ else if (webview) {
+ /*
+ * The webkit2 function for this is an asynchronous call,
+ * so our only option is to set this to always on, and we'll take care of whether we can copy
+ * or not when this command is actually given.
+ */
+ ev_window_set_action_sensitive (ev_window,"EditCopy",
+ has_pages);
+ }
+#else
+ else if(webview) {
+ ev_window_set_action_sensitive (ev_window, "EditCopy",
+ has_pages &&
+ ev_web_view_get_has_selection (webview));
+ }
+#endif
ev_window_set_action_sensitive (ev_window, "EditFindNext",
has_pages && can_find_in_page);
ev_window_set_action_sensitive (ev_window, "EditFindPrevious",
@@ -497,15 +531,16 @@ ev_window_update_actions (EvWindow *ev_window)
presentation_mode = EV_WINDOW_IS_PRESENTATION (ev_window);
- ev_window_set_action_sensitive (ev_window, "ViewZoomIn",
- has_pages &&
- ev_view_can_zoom_in (view) &&
- !presentation_mode);
- ev_window_set_action_sensitive (ev_window, "ViewZoomOut",
- has_pages &&
- ev_view_can_zoom_out (view) &&
- !presentation_mode);
-
+ if (ev_window->priv->document && ev_window->priv->document->iswebdocument == FALSE ) {
+ ev_window_set_action_sensitive (ev_window, "ViewZoomIn",
+ has_pages &&
+ ev_view_can_zoom_in (view) &&
+ !presentation_mode);
+ ev_window_set_action_sensitive (ev_window, "ViewZoomOut",
+ has_pages &&
+ ev_view_can_zoom_out (view) &&
+ !presentation_mode);
+ }
/* Go menu */
if (has_pages) {
ev_window_set_action_sensitive (ev_window, "GoPreviousPage", page > 0);
@@ -660,8 +695,10 @@ update_sizing_buttons (EvWindow *window)
ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action),
EPHY_ZOOM_BEST_FIT);
} else if (page_width) {
- ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action),
- EPHY_ZOOM_FIT_WIDTH);
+ if (!window->priv->document || (window->priv->document && !window->priv->document->iswebdocument)) {
+ ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action),
+ EPHY_ZOOM_FIT_WIDTH);
+ }
}
}
@@ -904,6 +941,15 @@ view_selection_changed_cb (EvView *view,
ev_window_set_action_sensitive (window, "EditCopy",
ev_view_get_has_selection (view));
}
+#if !GTK_CHECK_VERSION (3, 0, 0)
+static void
+web_view_selection_changed_cb(EvWebView *webview,
+ EvWindow *window)
+{
+ ev_window_set_action_sensitive (window,"EditCopy",
+ ev_web_view_get_has_selection(webview));
+}
+#endif
static void
ev_window_page_changed_cb (EvWindow *ev_window,
@@ -987,6 +1033,12 @@ static void
update_document_mode (EvWindow *window, EvDocumentMode mode)
{
if (mode == EV_DOCUMENT_MODE_PRESENTATION) {
+ if (window->priv->document) {
+ if (window->priv->document->iswebdocument) {
+ ev_window_warning_message(window,_("Cannot enter presentation mode with ePub documents use fullscreen mode instead."));
+ return;
+ }
+ }
ev_window_run_presentation (window);
}
else if (mode == EV_DOCUMENT_MODE_FULL_SCREEN) {
@@ -1278,7 +1330,12 @@ setup_view_from_metadata (EvWindow *window)
/* Presentation */
if (ev_metadata_get_boolean (window->priv->metadata, "presentation", &presentation)) {
if (presentation) {
- ev_window_run_presentation (window);
+ if (window->priv->document->iswebdocument == TRUE ) {
+ return;
+ }
+ else {
+ ev_window_run_presentation (window);
+ }
}
}
}
@@ -1333,6 +1390,10 @@ ev_window_refresh_window_thumbnail (EvWindow *ev_window)
rotation = ev_document_model_get_rotation (ev_window->priv->model);
ev_window->priv->thumbnail_job = ev_job_thumbnail_new (document, 0, rotation, scale);
+
+ if (document->iswebdocument) {
+ ev_job_set_run_mode(EV_JOB(ev_window->priv->thumbnail_job), EV_JOB_RUN_MAIN_LOOP);
+ }
g_signal_connect (ev_window->priv->thumbnail_job, "finished",
G_CALLBACK (ev_window_set_icon_from_thumbnail),
ev_window);
@@ -1363,10 +1424,10 @@ ev_window_setup_document (EvWindow *ev_window)
GtkAction *action;
ev_window->priv->setup_document_idle = 0;
-
ev_window_refresh_window_thumbnail (ev_window);
-
+
ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT);
+
ev_window_title_set_document (ev_window->priv->title, document);
ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
@@ -1403,12 +1464,15 @@ ev_window_setup_document (EvWindow *ev_window)
info = ev_document_get_info (document);
update_document_mode (ev_window, info->mode);
-
- if (EV_WINDOW_IS_PRESENTATION (ev_window))
+ /*FIXME*/
+ if (EV_WINDOW_IS_PRESENTATION (ev_window) && document->iswebdocument == FALSE)
gtk_widget_grab_focus (ev_window->priv->presentation_view);
- else
- gtk_widget_grab_focus (ev_window->priv->view);
-
+ else {
+ if ( document->iswebdocument == FALSE )
+ gtk_widget_grab_focus (ev_window->priv->view);
+ else
+ gtk_widget_grab_focus (ev_window->priv->webview);
+ }
return FALSE;
}
@@ -1429,15 +1493,40 @@ ev_window_set_document (EvWindow *ev_window, EvDocument *document)
if (ev_document_get_n_pages (document) <= 0) {
ev_window_warning_message (ev_window, "%s",
_("The document contains no pages"));
- } else if (!ev_document_check_dimensions (document)) {
+ } else if (!ev_document_check_dimensions (document) && document->iswebdocument == FALSE) {
ev_window_warning_message (ev_window, "%s",
_("The document contains only empty pages"));
}
-
- if (EV_WINDOW_IS_PRESENTATION (ev_window)) {
+#ifdef ENABLE_EPUB
+ GtkWidget *parent= gtk_widget_get_parent(ev_window->priv->webview);
+ if (document->iswebdocument == TRUE &&
+ parent == NULL )
+ {
+ /*We have encountered a web document, replace the atril view with a web view, if the web view is not already loaded.*/
+ gtk_container_remove (GTK_CONTAINER(ev_window->priv->scrolled_window),
+ ev_window->priv->view);
+ ev_view_disconnect_handlers(EV_VIEW(ev_window->priv->view));
+ g_object_unref(ev_window->priv->view);
+ ev_window->priv->view = NULL;
+ gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
+ ev_window->priv->webview);
+ gtk_widget_show(ev_window->priv->webview);
+ }
+ else {
+ /*Since the document is not a webdocument might as well get rid of the webview now*/
+ ev_web_view_disconnect_handlers(EV_WEB_VIEW(ev_window->priv->webview));
+ g_object_ref_sink(ev_window->priv->webview);
+ g_object_unref(ev_window->priv->webview);
+ }
+#endif
+ if (EV_WINDOW_IS_PRESENTATION (ev_window) && document->iswebdocument == FALSE) {
gtk_widget_destroy (ev_window->priv->presentation_view);
ev_window->priv->presentation_view = NULL;
ev_window_run_presentation (ev_window);
+ } else if ( EV_WINDOW_IS_PRESENTATION (ev_window) && document->iswebdocument == TRUE )
+ {
+ ev_window_warning_message (ev_window, "%s",
+ _("Presentation mode is not supported for ePub documents."));
}
if (ev_window->priv->setup_document_idle > 0)
@@ -1505,6 +1594,9 @@ static void
ev_window_handle_link (EvWindow *ev_window,
EvLinkDest *dest)
{
+ if (ev_window->priv->document->iswebdocument == FALSE ) {
+ return;
+ }
if (dest) {
EvLink *link;
EvLinkAction *link_action;
@@ -1535,9 +1627,8 @@ ev_window_load_job_cb (EvJob *job,
g_assert (job_load->uri);
ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
-
/* Success! */
- if (!ev_job_is_failed (job)) {
+ if (!ev_job_is_failed (job)) {
ev_document_model_set_document (ev_window->priv->model, document);
#ifdef ENABLE_DBUS
@@ -1799,6 +1890,8 @@ static void
ev_window_load_remote_failed (EvWindow *ev_window,
GError *error)
{
+ if ( !ev_window->priv->view ) return;
+
ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
ev_window->priv->in_reload = FALSE;
ev_window_error_message (ev_window, error,
@@ -2054,9 +2147,6 @@ ev_window_open_document (EvWindow *ev_window,
EvWindowRunMode mode,
const gchar *search_string)
{
- if (document == ev_window->priv->document)
- return;
-
ev_window_close_dialogs (ev_window);
ev_window_clear_load_job (ev_window);
ev_window_clear_local_uri (ev_window);
@@ -2078,7 +2168,7 @@ ev_window_open_document (EvWindow *ev_window,
setup_document_from_metadata (ev_window);
setup_view_from_metadata (ev_window);
- if (dest) {
+ if (dest && document->iswebdocument == FALSE) {
EvLink *link;
EvLinkAction *link_action;
@@ -2272,13 +2362,10 @@ ev_window_reload_document (EvWindow *ev_window,
EvLinkDest *dest)
{
gint page;
-
-
ev_window_clear_reload_job (ev_window);
ev_window->priv->in_reload = TRUE;
page = ev_document_model_get_page (ev_window->priv->model);
-
if (ev_window->priv->dest)
g_object_unref (ev_window->priv->dest);
ev_window->priv->dest = dest ? g_object_ref (dest) : NULL;
@@ -3605,12 +3692,18 @@ ev_window_cmd_focus_page_selector (GtkAction *act, EvWindow *window)
static void
ev_window_cmd_scroll_forward (GtkAction *action, EvWindow *window)
{
+ /*If the webview is occupying the window*/
+ if ( window->priv->document->iswebdocument == TRUE) return ;
+
ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_FORWARD, FALSE);
}
static void
ev_window_cmd_scroll_backward (GtkAction *action, EvWindow *window)
{
+ /*If the webview is occupying the window*/
+ if ( window->priv->document->iswebdocument == TRUE ) return ;
+
ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_BACKWARD, FALSE);
}
@@ -3673,8 +3766,10 @@ ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window)
*/
if (ev_window->priv->chrome & EV_CHROME_FINDBAR) {
egg_find_bar_grab_focus(ev_window->priv->find_bar);
- } else {
+ } else if (ev_window->priv->document->iswebdocument == FALSE ) {
ev_view_select_all (EV_VIEW (ev_window->priv->view));
+ } else {
+ ev_web_view_select_all(EV_WEB_VIEW(ev_window->priv->webview));
}
}
@@ -3701,7 +3796,11 @@ ev_window_cmd_edit_find_next (GtkAction *action, EvWindow *ev_window)
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
update_chrome_visibility (ev_window);
gtk_widget_grab_focus (ev_window->priv->find_bar);
- ev_view_find_next (EV_VIEW (ev_window->priv->view));
+ if (ev_window->priv->document->iswebdocument == FALSE) {
+ ev_view_find_next (EV_VIEW (ev_window->priv->view));
+ } else {
+ ev_web_view_find_next(EV_WEB_VIEW(ev_window->priv->webview));
+ }
}
static void
@@ -3712,15 +3811,23 @@ ev_window_cmd_edit_find_previous (GtkAction *action, EvWindow *ev_window)
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
update_chrome_visibility (ev_window);
gtk_widget_grab_focus (ev_window->priv->find_bar);
- ev_view_find_previous (EV_VIEW (ev_window->priv->view));
+ if (ev_window->priv->document->iswebdocument == FALSE) {
+ ev_view_find_previous (EV_VIEW (ev_window->priv->view));
+ } else {
+ ev_web_view_find_previous(EV_WEB_VIEW(ev_window->priv->webview));
+ }
}
static void
ev_window_cmd_edit_copy (GtkAction *action, EvWindow *ev_window)
{
g_return_if_fail (EV_IS_WINDOW (ev_window));
-
- ev_view_copy (EV_VIEW (ev_window->priv->view));
+
+ if (ev_window->priv->document->iswebdocument) {
+ ev_web_view_copy(EV_WEB_VIEW(ev_window->priv->webview));
+ } else {
+ ev_view_copy (EV_VIEW (ev_window->priv->view));
+ }
}
static void
@@ -3832,8 +3939,12 @@ ev_window_run_fullscreen (EvWindow *window)
if (fullscreen_window)
gtk_window_fullscreen (GTK_WINDOW (window));
- gtk_widget_grab_focus (window->priv->view);
-
+ if (window->priv->view) {
+ gtk_widget_grab_focus (window->priv->view);
+ }
+ else {
+ gtk_widget_grab_focus(window->priv->webview);
+ }
if (window->priv->metadata && !ev_window_is_empty (window))
ev_metadata_set_boolean (window->priv->metadata, "fullscreen", TRUE);
}
@@ -3903,7 +4014,11 @@ ev_window_run_presentation (EvWindow *window)
if (EV_WINDOW_IS_PRESENTATION (window))
return;
-
+
+ if (window->priv->document->iswebdocument) {
+ ev_window_warning_message(window,_("Presentation mode is not supported for ePub documents"));
+ return;
+ }
if (ev_document_model_get_fullscreen (window->priv->model)) {
ev_window_stop_fullscreen (window, FALSE);
fullscreen_window = FALSE;
@@ -3961,9 +4076,13 @@ ev_window_stop_presentation (EvWindow *window,
update_chrome_visibility (window);
if (unfullscreen_window)
gtk_window_unfullscreen (GTK_WINDOW (window));
-
- gtk_widget_grab_focus (window->priv->view);
-
+
+ if (window->priv->view) {
+ gtk_widget_grab_focus (window->priv->view);
+ } else {
+ gtk_widget_grab_focus (window->priv->webview);
+ }
+
ev_application_screensaver_enable (EV_APP);
if (window->priv->metadata && !ev_window_is_empty (window))
@@ -4099,7 +4218,12 @@ ev_window_set_page_mode (EvWindow *window,
switch (page_mode) {
case PAGE_MODE_DOCUMENT:
- child = window->priv->view;
+ if ( window->priv->document && window->priv->document->iswebdocument == FALSE ) {
+ child = window->priv->view;
+ }
+ else {
+ child=window->priv->webview;
+ }
break;
case PAGE_MODE_PASSWORD:
child = window->priv->password_view;
@@ -4241,7 +4365,12 @@ ev_window_cmd_view_zoom_in (GtkAction *action, EvWindow *ev_window)
g_return_if_fail (EV_IS_WINDOW (ev_window));
ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FREE);
- ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
+ if (ev_window->priv->document->iswebdocument) {
+ ev_web_view_zoom_in(EV_WEB_VIEW(ev_window->priv->webview));
+ }
+ else {
+ ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
+ }
}
static void
@@ -4250,15 +4379,24 @@ ev_window_cmd_view_zoom_out (GtkAction *action, EvWindow *ev_window)
g_return_if_fail (EV_IS_WINDOW (ev_window));
ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FREE);
- ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
+
+ if ( ev_window->priv->document->iswebdocument) {
+ ev_web_view_zoom_out(EV_WEB_VIEW(ev_window->priv->webview));
+ }
+ else {
+ ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
+ }
}
static void
ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
{
g_return_if_fail (EV_IS_WINDOW (ev_window));
-
- ev_view_previous_page (EV_VIEW (ev_window->priv->view));
+ if ( ev_window->priv->document->iswebdocument == TRUE ) {
+ ev_web_view_previous_page(EV_WEB_VIEW(ev_window->priv->webview));
+ } else {
+ ev_view_previous_page (EV_VIEW (ev_window->priv->view));
+ }
}
static void
@@ -4266,7 +4404,11 @@ ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
{
g_return_if_fail (EV_IS_WINDOW (ev_window));
- ev_view_next_page (EV_VIEW (ev_window->priv->view));
+ if ( ev_window->priv->document->iswebdocument == TRUE ) {
+ ev_web_view_next_page(EV_WEB_VIEW(ev_window->priv->webview));
+ } else {
+ ev_view_next_page (EV_VIEW (ev_window->priv->view));
+ }
}
static void
@@ -4332,7 +4474,12 @@ ev_window_cmd_view_expand_window (GtkAction *action, EvWindow *ev_window)
static void
ev_window_cmd_view_autoscroll (GtkAction *action, EvWindow *ev_window)
{
- ev_view_autoscroll_start (EV_VIEW (ev_window->priv->view));
+ EvDocument* document = ev_window->priv->document;
+ if (document->iswebdocument == TRUE ) {
+ return ;
+ }else {
+ ev_view_autoscroll_start (EV_VIEW (ev_window->priv->view));
+ }
}
#define EV_HELP "help:atril"
@@ -4370,13 +4517,18 @@ ev_window_cmd_escape (GtkAction *action, EvWindow *window)
{
GtkWidget *widget;
- ev_view_autoscroll_stop (EV_VIEW (window->priv->view));
+ if (!window->priv->document->iswebdocument && window->priv->view)
+ ev_view_autoscroll_stop (EV_VIEW (window->priv->view));
widget = gtk_window_get_focus (GTK_WINDOW (window));
if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
update_chrome_flag (window, EV_CHROME_FINDBAR, FALSE);
update_chrome_visibility (window);
- gtk_widget_grab_focus (window->priv->view);
+
+ if (window->priv->view)
+ gtk_widget_grab_focus (window->priv->view);
+ else
+ gtk_widget_grab_focus (window->priv->webview);
} else {
gboolean fullscreen;
@@ -4388,7 +4540,10 @@ ev_window_cmd_escape (GtkAction *action, EvWindow *window)
ev_window_stop_presentation (window, TRUE);
gtk_widget_grab_focus (window->priv->view);
} else {
- gtk_widget_grab_focus (window->priv->view);
+ if (window->priv->view)
+ gtk_widget_grab_focus (window->priv->view);
+ else
+ gtk_widget_grab_focus (window->priv->webview);
}
if (fullscreen && EV_WINDOW_IS_PRESENTATION (window))
@@ -4585,6 +4740,7 @@ ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
"Perberos <[email protected]>",
"Stefano Karapetsas <[email protected]>",
"Steve Zesch <[email protected]>",
+ "Avishkar Gupta <[email protected]>",
NULL
};
@@ -4707,6 +4863,8 @@ view_menu_link_popup (EvWindow *ev_window,
gboolean show_external = FALSE;
gboolean show_internal = FALSE;
GtkAction *action;
+
+ if ( ev_window->priv->document->iswebdocument == TRUE ) return ;
if (ev_window->priv->link)
g_object_unref (ev_window->priv->link);
@@ -4759,7 +4917,8 @@ view_menu_image_popup (EvWindow *ev_window,
{
GtkAction *action;
gboolean show_image = FALSE;
-
+
+ if (ev_window->priv->document->iswebdocument == TRUE ) return ;
if (ev_window->priv->image)
g_object_unref (ev_window->priv->image);
@@ -4785,7 +4944,7 @@ view_menu_annot_popup (EvWindow *ev_window,
{
GtkAction *action;
gboolean show_annot = FALSE;
-
+ if (ev_window->priv->document->iswebdocument == TRUE ) return ;
if (ev_window->priv->annot)
g_object_unref (ev_window->priv->annot);
ev_window->priv->annot = (annot) ? g_object_ref (annot) : NULL;
@@ -4934,10 +5093,15 @@ ev_window_find_job_updated_cb (EvJobFind *job,
EvWindow *ev_window)
{
ev_window_update_actions (ev_window);
-
- ev_view_find_changed (EV_VIEW (ev_window->priv->view),
- ev_job_find_get_results (job),
- page);
+ if (ev_window->priv->document->iswebdocument == TRUE ) {
+ ev_web_view_find_changed(EV_WEB_VIEW(ev_window->priv->webview),
+ job->results,job->text, job->case_sensitive);
+ }
+ else {
+ ev_view_find_changed (EV_VIEW (ev_window->priv->view),
+ ev_job_find_get_results (job),
+ page);
+ }
ev_window_update_find_status_message (ev_window);
}
@@ -4963,21 +5127,34 @@ static void
find_bar_previous_cb (EggFindBar *find_bar,
EvWindow *ev_window)
{
- ev_view_find_previous (EV_VIEW (ev_window->priv->view));
+ if (ev_window->priv->document->iswebdocument == TRUE ) {
+ ev_web_view_find_previous(EV_WEB_VIEW(ev_window->priv->webview));
+ }else {
+ ev_view_find_previous (EV_VIEW (ev_window->priv->view));
+ }
}
static void
find_bar_next_cb (EggFindBar *find_bar,
EvWindow *ev_window)
{
- ev_view_find_next (EV_VIEW (ev_window->priv->view));
+ if (ev_window->priv->document->iswebdocument == TRUE ) {
+ ev_web_view_find_next(EV_WEB_VIEW(ev_window->priv->webview));
+ } else {
+ ev_view_find_next (EV_VIEW (ev_window->priv->view));
+ }
}
static void
find_bar_close_cb (EggFindBar *find_bar,
EvWindow *ev_window)
{
- ev_view_find_cancel (EV_VIEW (ev_window->priv->view));
+ if (ev_window->priv->document->iswebdocument == TRUE ) {
+ ev_web_view_find_cancel(EV_WEB_VIEW(ev_window->priv->webview));
+ }
+ else {
+ ev_view_find_cancel (EV_VIEW (ev_window->priv->view));
+ }
ev_window_clear_find_job (ev_window);
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE);
update_chrome_visibility (ev_window);
@@ -4998,8 +5175,11 @@ find_bar_search_changed_cb (EggFindBar *find_bar,
case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
search_string = egg_find_bar_get_search_string (find_bar);
- ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
-
+ if (ev_window->priv->document->iswebdocument) {
+ ev_web_view_find_search_changed(EV_WEB_VIEW(ev_window->priv->webview));
+ } else {
+ ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
+ }
ev_window_clear_find_job (ev_window);
if (search_string && search_string[0]) {
@@ -5008,6 +5188,7 @@ find_bar_search_changed_cb (EggFindBar *find_bar,
ev_document_get_n_pages (ev_window->priv->document),
search_string,
case_sensitive);
+
g_signal_connect (ev_window->priv->find_job, "finished",
G_CALLBACK (ev_window_find_job_finished_cb),
ev_window);
@@ -5019,7 +5200,9 @@ find_bar_search_changed_cb (EggFindBar *find_bar,
ev_window_update_actions (ev_window);
egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
NULL);
- gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
+ if (ev_window->priv->document->iswebdocument == FALSE) {
+ gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
+ }
}
}
@@ -5029,13 +5212,23 @@ find_bar_visibility_changed_cb (EggFindBar *find_bar,
EvWindow *ev_window)
{
gboolean visible;
-
visible = gtk_widget_get_visible (GTK_WIDGET (find_bar));
if (ev_window->priv->document &&
EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
- ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), visible);
- ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
+
+ if (!ev_window->priv->document->iswebdocument) {
+ ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), visible);
+ ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
+ }
+ else {
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ ev_web_view_find_set_highlight_search(EV_WEB_VIEW(ev_window->priv->webview),visible);
+#endif
+ ev_web_view_find_search_changed(EV_WEB_VIEW(ev_window->priv->webview));
+ ev_web_view_set_handler(EV_WEB_VIEW(ev_window->priv->webview),visible);
+ }
+
ev_window_update_actions (ev_window);
if (visible)
@@ -5050,6 +5243,7 @@ find_bar_scroll (EggFindBar *find_bar,
GtkScrollType scroll,
EvWindow *ev_window)
{
+ if (ev_window->priv->document->iswebdocument == TRUE ) return ;
ev_view_scroll (EV_VIEW (ev_window->priv->view), scroll, FALSE);
}
@@ -5296,7 +5490,7 @@ ev_window_dispose (GObject *object)
}
if (priv->view) {
- g_object_unref (priv->view);
+ g_object_unref (priv->view);
priv->view = NULL;
}
@@ -5422,13 +5616,13 @@ ev_window_key_press_event (GtkWidget *widget,
* It's needed to be able to type in
* annot popups windows
*/
- if (priv->view) {
+ if ( priv->view) {
g_object_ref (priv->view);
if (gtk_widget_is_sensitive (priv->view))
handled = gtk_widget_event (priv->view, (GdkEvent*) event);
g_object_unref (priv->view);
}
-
+
if (!handled && !EV_WINDOW_IS_PRESENTATION (ev_window)) {
guint modifier = event->state & gtk_accelerator_get_default_mod_mask ();
@@ -5689,19 +5883,35 @@ static const GtkActionEntry attachment_popup_entries [] = {
static void
sidebar_links_link_activated_cb (EvSidebarLinks *sidebar_links, EvLink *link, EvWindow *window)
{
- ev_view_handle_link (EV_VIEW (window->priv->view), link);
+ if (window->priv->document->iswebdocument == FALSE ) {
+ ev_view_handle_link (EV_VIEW (window->priv->view), link);
+ }
+ else {
+ ev_web_view_handle_link(EV_WEB_VIEW(window->priv->webview), link);
+ }
}
static void
activate_link_cb (EvPageAction *page_action, EvLink *link, EvWindow *window)
{
- ev_view_handle_link (EV_VIEW (window->priv->view), link);
- gtk_widget_grab_focus (window->priv->view);
+ if (window->priv->view) {
+ ev_view_handle_link (EV_VIEW (window->priv->view), link);
+ gtk_widget_grab_focus (window->priv->view);
+ }
+ else {
+ ev_web_view_handle_link (EV_WEB_VIEW (window->priv->webview), link);
+ gtk_widget_grab_focus (window->priv->webview);
+ }
}
static void
navigation_action_activate_link_cb (EvNavigationAction *action, EvLink *link, EvWindow *window)
{
+ if (window->priv->document->iswebdocument == TRUE ) {
+ ev_web_view_handle_link(EV_WEB_VIEW(window->priv->webview),link);
+ gtk_widget_grab_focus (window->priv->webview);
+ return;
+ }
ev_view_handle_link (EV_VIEW (window->priv->view), link);
gtk_widget_grab_focus (window->priv->view);
@@ -5711,7 +5921,13 @@ static void
sidebar_layers_visibility_changed (EvSidebarLayers *layers,
EvWindow *window)
{
- ev_view_reload (EV_VIEW (window->priv->view));
+ if (window->priv->document->iswebdocument == FALSE ) {
+ ev_view_reload (EV_VIEW (window->priv->view));
+ }
+ else
+ {
+ ev_web_view_reload(EV_WEB_VIEW(window->priv->webview));
+ }
}
static void
@@ -5719,6 +5935,7 @@ sidebar_annots_annot_activated_cb (EvSidebarAnnotations *sidebar_annots,
EvMapping *annot_mapping,
EvWindow *window)
{
+ if (window->priv->document->iswebdocument == TRUE ) return;
ev_view_focus_annotation (EV_VIEW (window->priv->view), annot_mapping);
}
@@ -5727,6 +5944,7 @@ sidebar_annots_begin_annot_add (EvSidebarAnnotations *sidebar_annots,
EvAnnotationType annot_type,
EvWindow *window)
{
+ if (window->priv->document->iswebdocument == TRUE ) return;
ev_view_begin_add_annotation (EV_VIEW (window->priv->view), annot_type);
}
@@ -5743,6 +5961,7 @@ static void
sidebar_annots_annot_add_cancelled (EvSidebarAnnotations *sidebar_annots,
EvWindow *window)
{
+ if (window->priv->document->iswebdocument == TRUE ) return;
ev_view_cancel_add_annotation (EV_VIEW (window->priv->view));
}
@@ -6146,6 +6365,7 @@ view_external_link_cb (EvView *view, EvLinkAction *action, EvWindow *window)
static void
ev_view_popup_cmd_open_link (GtkAction *action, EvWindow *window)
{
+ if (window->priv->document->iswebdocument == TRUE ) return;
ev_view_handle_link (EV_VIEW (window->priv->view), window->priv->link);
}
@@ -6170,7 +6390,7 @@ static void
ev_view_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window)
{
EvLinkAction *ev_action;
-
+ if (window->priv->document->iswebdocument == TRUE ) return;
ev_action = ev_link_get_action (window->priv->link);
if (!ev_action)
return;
@@ -6345,6 +6565,8 @@ static void
ev_view_popup_cmd_annot_properties (GtkAction *action,
EvWindow *window)
{
+ if (window->priv->document->iswebdocument == TRUE ) return;
+
const gchar *author;
GdkColor color;
gdouble opacity;
@@ -6730,8 +6952,9 @@ method_call_cb (GDBusConnection *connection,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
- EvWindow *window = EV_WINDOW (user_data);
-
+ EvWindow *window = EV_WINDOW (user_data);
+ if (window->priv->document->iswebdocument == TRUE ) return;
+
if (g_strcmp0 (method_name, "SyncView") != 0)
return;
@@ -7025,6 +7248,16 @@ ev_window_init (EvWindow *ev_window)
gtk_widget_show (ev_window->priv->view_box);
ev_window->priv->view = ev_view_new ();
+
+#ifdef ENABLE_EPUB /*The webview, we won't add it now but it will replace the atril-view if a web(epub) document is encountered.*/
+ ev_window->priv->webview = ev_web_view_new();
+ ev_web_view_set_model(EV_WEB_VIEW(ev_window->priv->webview),ev_window->priv->model);
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_connect_object (ev_window->priv->webview,"selection-changed",
+ G_CALLBACK(web_view_selection_changed_cb),
+ ev_window, 0);
+#endif
+#endif
ev_view_set_page_cache_size (EV_VIEW (ev_window->priv->view), PAGE_CACHE_SIZE);
ev_view_set_model (EV_VIEW (ev_window->priv->view), ev_window->priv->model);
@@ -7071,9 +7304,9 @@ ev_window_init (EvWindow *ev_window)
/* We own a ref on these widgets, as we can swap them in and out */
g_object_ref (ev_window->priv->view);
g_object_ref (ev_window->priv->password_view);
-
+
gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
- ev_window->priv->view);
+ ev_window->priv->view);
/* Connect to model signals */
g_signal_connect_swapped (ev_window->priv->model,