diff options
Diffstat (limited to 'backend/epub')
| -rw-r--r-- | backend/epub/Makefile.am | 37 | ||||
| -rw-r--r-- | backend/epub/epub-document.c | 1391 | ||||
| -rw-r--r-- | backend/epub/epub-document.h | 21 | ||||
| -rw-r--r-- | backend/epub/epubdocument.atril-backend.in | 4 | ||||
| -rw-r--r-- | backend/epub/minizip/Makefile.am | 14 | ||||
| -rw-r--r-- | backend/epub/minizip/ioapi.c | 247 | ||||
| -rw-r--r-- | backend/epub/minizip/ioapi.h | 208 | ||||
| -rw-r--r-- | backend/epub/minizip/unzip.c | 2125 | ||||
| -rw-r--r-- | backend/epub/minizip/unzip.h | 437 | 
9 files changed, 4484 insertions, 0 deletions
| 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 */ | 
