Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Diff of /cbrpager-maemo/branches/MAEMO_0_9_20/src/garchivereaderunzip.c [000000] .. [r4] Maximize Restore

  Switch to side-by-side view

--- a
+++ b/cbrpager-maemo/branches/MAEMO_0_9_20/src/garchivereaderunzip.c
@@ -0,0 +1,316 @@
+/*
+ * garchivereaderunzip.c - routines to manipulate archive files
+ * using libunzip code.
+ *
+ * Copyright (C) 2008 Benoit Goudreault-Emond (bgoudreaultemond@gmail.com).
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "unzip.h"
+#include "garchivereaderunzip.h"
+
+extern int debug;
+
+static gint
+compare_pages(gconstpointer s1, gconstpointer s2)
+{
+    return strcmp((const char*)s1, (const char*)s2);
+}
+
+static gboolean extension_handled(const char* filename)
+{
+    static const char* extensions[] = {
+	".jpg", ".jpeg", ".png", ".gif",
+	".JPG", ".JPEG", ".PNG", ".GIF"
+    };
+    static const int nr_extensions = 8;
+    
+    int i;
+    for(i = 0; i < nr_extensions; ++i)
+    {
+	if(strstr(filename, extensions[i]) != NULL)
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+static void set_last_error(GArchiveReaderUnzip* reader, gchar* data)
+{
+    if(reader->last_error)
+	g_free(reader->last_error);
+    reader->last_error = data;
+}
+
+static void free_string(gpointer data, gpointer user_data)
+{
+    g_free(data);
+}
+
+static void
+free_page_list(GArchiveReaderUnzip* reader)
+{
+    if(!reader->page_list)
+	return;
+
+    g_list_foreach(reader->page_list, free_string, NULL);
+    g_list_free(reader->page_list);
+    reader->page_list = NULL;
+}
+
+static int
+register_path(GArchiveReader* reader_iface,
+	      const gchar* path)
+{
+    unzFile file;
+    GArchiveReaderUnzip* reader = G_ARCHIVE_READER_UNZIP(reader_iface);
+    int check_result = g_archive_reader_check_magic(path, &reader->magic);
+    if(debug)
+	printf(_("Check result for type %s -> %d\n"), reader->magic.sign, check_result);
+    if(check_result <= 0)
+	return check_result;
+
+    file = unzOpen(path);
+    if(!file)
+	return -1;
+    if(reader->current_file)
+    {
+	unzClose(reader->current_file);
+	free_page_list(reader);
+    } 
+    reader->current_file = file;
+    return 1;
+}
+
+#define BUFSIZE 2049
+
+static GList*
+get_file_list(GArchiveReader* reader_iface)
+{
+    GArchiveReaderUnzip* reader = G_ARCHIVE_READER_UNZIP(reader_iface);
+    static char filename[BUFSIZE]; /* should be enough */
+
+    if(reader->page_list)
+	return reader->page_list;
+    
+    if(!reader->current_file)
+	return NULL;
+    
+    unzGoToFirstFile(reader->current_file);
+    do
+    {
+	unz_file_info file_info;
+	unzGetCurrentFileInfo(reader->current_file,
+			      &file_info,
+			      filename,
+			      BUFSIZE - 1,
+			      NULL,
+			      0,
+			      NULL,
+			      0);
+	/* terminate with NUL just in case */
+	filename[file_info.size_filename] = '\0';
+	if(extension_handled(filename))
+	{
+	    reader->page_list = g_list_append(reader->page_list, g_strdup(filename));
+	}
+    } while(unzGoToNextFile(reader->current_file) == UNZ_OK);
+
+    if(!reader->page_list)
+    {
+	set_last_error(reader, g_strdup(_("No pages in archive")));
+    }
+    else
+    {
+	reader->page_list = g_list_sort(reader->page_list, compare_pages);
+    }
+    return reader->page_list;
+}
+
+static GdkPixbuf*
+get_page(GArchiveReader* reader_iface, 
+	 int page_number,
+	 gdouble* w,
+	 gdouble* h)
+{
+    GdkPixbuf* retval = NULL;
+    GArchiveReaderUnzip* reader = G_ARCHIVE_READER_UNZIP(reader_iface);    
+    const gchar* filename;
+    GdkPixbufLoader* loader;
+    unz_file_info file_info;
+    void* buffer;
+    gboolean result;
+    int sz;
+    FILE* tmpfile;
+
+    if(w)
+	*w = 0;
+    if(h)
+	*h = 0;
+    filename = (const gchar*)g_list_nth_data(get_file_list(reader_iface), page_number);
+    if(!filename)
+    {
+	set_last_error(reader, g_strdup_printf(_("Page number %d out of range"), page_number));
+	return NULL;
+    }
+    
+    if(unzLocateFile(reader->current_file, (const char*)filename, 1) != UNZ_OK)
+    {
+	set_last_error(reader, g_strdup_printf(_("File %s not found in archive"), filename));
+	return NULL;
+    }
+
+    unzGetCurrentFileInfo(reader->current_file,
+			  &file_info,
+			  NULL,
+			  0,
+			  NULL,
+			  0,
+			  NULL,
+			  0);
+    if(unzOpenCurrentFile(reader->current_file) != UNZ_OK)
+    {
+	set_last_error(reader, g_strdup_printf(_("Error reading %s from archive"), filename));
+	return NULL;
+    }
+    buffer = g_try_malloc(file_info.uncompressed_size);
+    sz = unzReadCurrentFile(reader->current_file,
+			    buffer,
+			    file_info.uncompressed_size);
+    unzCloseCurrentFile(reader->current_file);
+    if(sz != file_info.uncompressed_size)
+    {
+	g_free(buffer);
+	set_last_error(reader, g_strdup_printf(_("Error reading %s from archive"), filename));
+	return NULL;
+    }
+
+    /* dump to the file */
+    if(!(tmpfile = fopen(reader->tmpf, "wb")))
+    {
+	g_free(buffer);
+	set_last_error(reader, g_strdup_printf(_("Unable to open temp file %s"), reader->tmpf));
+	return NULL;
+    }
+    sz = fwrite(buffer, 1, file_info.uncompressed_size, tmpfile);
+    g_free(buffer);
+    if(fclose(tmpfile) == EOF || sz != file_info.uncompressed_size)
+    {
+	set_last_error(reader, g_strdup(_("Out of disk space!")));
+	return NULL;
+    }
+
+    retval = gdk_pixbuf_new_from_file(reader->tmpf, NULL);
+    if(retval)
+    {
+	if(w)
+	    *w = gdk_pixbuf_get_width(retval);
+	if(h)
+	    *h = gdk_pixbuf_get_height(retval);
+    }
+    else
+    {
+	set_last_error(reader, g_strdup_printf(_("Unable to load page %d"), page_number));
+    }
+    return retval;
+}
+
+static gchar*
+get_last_error(GArchiveReader* reader_iface)
+{
+    GArchiveReaderUnzip* reader = G_ARCHIVE_READER_UNZIP(reader_iface);
+    gchar* last_error = reader->last_error;
+    reader->last_error = NULL;
+    return last_error;
+}
+
+/* class instance housekeeping stuff */
+
+static void
+g_archive_reader_unzip_interface_init(gpointer g_iface,
+				      gpointer iface_data)
+{
+    GArchiveReaderClass* klass = (GArchiveReaderClass*)g_iface;
+    klass->register_path = register_path;
+    klass->get_file_list = get_file_list;
+    klass->get_page = get_page;
+    klass->get_last_error = get_last_error;
+}
+
+static void
+g_archive_reader_unzip_init(GArchiveReaderUnzip* reader)
+{
+    reader->magic.offs = 0;
+    reader->magic.len = 0;
+    reader->magic.fn_offs = 0;
+    reader->magic.sign = NULL;
+    reader->tmpf = NULL;
+    reader->current_file = NULL;
+    reader->last_error = NULL;
+    reader->page_list = NULL;
+}
+
+G_DEFINE_TYPE_EXTENDED(GArchiveReaderUnzip,
+		       g_archive_reader_unzip,
+		       G_TYPE_OBJECT,
+		       0,
+		       G_IMPLEMENT_INTERFACE(G_TYPE_ARCHIVE_READER,
+					     g_archive_reader_unzip_interface_init));
+
+static void
+g_archive_reader_unzip_finalize (GObject* object)
+{
+    GArchiveReaderUnzip* reader = G_ARCHIVE_READER_UNZIP(object);
+    g_free(reader->tmpf);
+    if(reader->current_file)
+	unzClose(reader->current_file);
+    if(reader->last_error)
+	g_free(reader->last_error);
+    free_page_list(reader);
+}
+
+static void
+g_archive_reader_unzip_class_init(GArchiveReaderUnzipClass* klass)
+{
+    GObjectClass* object_class = (GObjectClass*)klass;
+    object_class->finalize = g_archive_reader_unzip_finalize;
+}
+
+/* public interface implementation */
+GArchiveReader* g_archive_reader_unzip_new(const gchar* tmpfile,
+					   magic_sign magic)
+{
+    gpointer data = NULL;
+    GArchiveReaderUnzip* reader = NULL;
+
+    /* copy properties from the parameters */
+    data = g_object_new(G_TYPE_ARCHIVE_READER_UNZIP, NULL);
+    reader = G_ARCHIVE_READER_UNZIP(data);
+    
+    reader->magic = magic;
+    reader->current_file = NULL;
+    reader->last_error = NULL;
+    reader->page_list = NULL;
+
+    /* figure out tmp file */
+    reader->tmpf = g_strdup(tmpfile);
+
+    return G_ARCHIVE_READER(data);
+}