gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r23230 - in Extractor/src: common plugins plugins/testdata


From: gnunet
Subject: [GNUnet-SVN] r23230 - in Extractor/src: common plugins plugins/testdata
Date: Tue, 14 Aug 2012 18:53:21 +0200

Author: grothoff
Date: 2012-08-14 18:53:21 +0200 (Tue, 14 Aug 2012)
New Revision: 23230

Added:
   Extractor/src/plugins/test_deb.c
   Extractor/src/plugins/test_odf.c
   Extractor/src/plugins/test_zip.c
   Extractor/src/plugins/testdata/deb_bzip2.deb
   Extractor/src/plugins/testdata/odf_cg.odt
   Extractor/src/plugins/testdata/zip_test.zip
Modified:
   Extractor/src/common/unzip.c
   Extractor/src/common/unzip.h
   Extractor/src/plugins/Makefile.am
   Extractor/src/plugins/deb_extractor.c
   Extractor/src/plugins/nsf_extractor.c
   Extractor/src/plugins/nsfe_extractor.c
   Extractor/src/plugins/odf_extractor.c
   Extractor/src/plugins/sid_extractor.c
   Extractor/src/plugins/zip_extractor.c
Log:
implemented zip, sid, nsf, nsfe ad odf extractors

Modified: Extractor/src/common/unzip.c
===================================================================
--- Extractor/src/common/unzip.c        2012-08-14 14:25:43 UTC (rev 23229)
+++ Extractor/src/common/unzip.c        2012-08-14 16:53:21 UTC (rev 23230)
@@ -25,6 +25,39 @@
  * This code is based in part on
  * unzip 1.00 Copyright 1998-2003 Gilles Vollant
  * http://www.winimage.com/zLibDll";
+ *
+ *
+ * The filenames for each file in a zipfile are stored in two locations.
+ * There is one at the start of each entry, just before the compressed data,
+ * and another at the end in a 'central directory structure'.
+ *
+ * In order to catch self-extracting executables, we scan backwards from the 
end
+ * of the file looking for the central directory structure. The previous 
version
+ * of this went forewards through the local headers, but that only works for 
plain
+ * vanilla zip's and I don't feel like writing a special case for each of the 
dozen
+ * self-extracting executable stubs.
+ *
+ * This assumes that the zip file is considered to be 
non-corrupt/non-truncated.
+ * If it is truncated then it's not considered to be a zip and skipped.
+ *  
+ * ZIP format description from appnote.iz and appnote.txt (more or less):
+ *
+ *   (this is why you always need to put in the last floppy if you span disks)
+ *
+ *   0- 3  end of central dir signature    4 bytes  (0x06054b50) P K ^E ^F
+ *   4- 5  number of this disk             2 bytes
+ *   6- 7  number of the disk with the
+ *         start of the central directory  2 bytes
+ *   8- 9  total number of entries in
+ *         the central dir on this disk    2 bytes
+ *  10-11  total number of entries in
+ *         the central dir                 2 bytes
+ *  12-15  size of the central directory   4 bytes
+ *  16-19  offset of start of central
+ *         directory with respect to
+ *         the starting disk number        4 bytes
+ *  20-21  zipfile comment length          2 bytes
+ *  22-??  zipfile comment (variable size) max length 65536 bytes
  */
 #include "platform.h"
 #include <ctype.h>
@@ -49,27 +82,27 @@
 /**
  * IO callbacks for access to the ZIP data.
  */
-struct EXTRACTOR_UnzipFileFuncDefs
+struct FileFuncDefs
 {
   /**
    * Callback for reading 'size' bytes from the ZIP archive into buf.
    */
-  uLong  ( *zread_file)  (voidpf opaque, void* buf, uLong size);
+  uLong (*zread_file) (voidpf opaque, void* buf, uLong size);
 
   /**
    * Callback to obtain the current read offset in the ZIP archive.
    */
-  long   ( *ztell_file)  (voidpf opaque);
+  long (*ztell_file) (voidpf opaque);
 
   /**
    * Callback for seeking to a different position in the ZIP archive.
    */
-  long   ( *zseek_file)  (voidpf opaque, uLong offset, int origin);
+  long (*zseek_file) (voidpf opaque, uLong offset, int origin);
 
   /**
    * Opaque argument to pass to all IO functions.
    */
-  voidpf              opaque;
+  voidpf opaque;
 };
 
 
@@ -119,6 +152,11 @@
    * size of the global comment of the zipfile 
    */
   uLong size_comment;         
+
+  /**
+   * offset of the global comment in the zipfile
+   */
+  uLong offset_comment;
 };
 
 
@@ -198,9 +236,9 @@
   uLong rest_read_uncompressed;
   
   /**
-   * IO functions. (FIXME: where is this assigned?)
+   * IO functions.
    */ 
-  struct EXTRACTOR_UnzipFileFuncDefs z_filefunc;
+  struct FileFuncDefs z_filefunc;
 
   /**
    * compression method (0==store) 
@@ -223,7 +261,7 @@
   /**
    * io structore of the zipfile 
    */
-  struct EXTRACTOR_UnzipFileFuncDefs z_filefunc;
+  struct FileFuncDefs z_filefunc;
 
   /**
    * public global information 
@@ -279,7 +317,7 @@
   /**
    * structure about the current file if we are decompressing it
    */
-  struct FileInZipReadInfo* pfile_in_zip_read; 
+  struct FileInZipReadInfo *pfile_in_zip_read; 
 
   /**
    * Is the file encrypted?
@@ -292,33 +330,46 @@
  * 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.
+ *
+ * @param ffd functions for performing IO operations
+ * @param pi where to store the byte that was read
+ * @return EXTRACTOR_UNZIP_OK on success, or EXTRACTOR_UNZIP_EOF
  */
 static int 
-unzlocal_getByte (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def,
-                 int *pi)
+read_byte_from_ffd (const struct FileFuncDefs *ffd,
+                   int *pi)
 {
   unsigned char c;
 
-  if (1 != ZREAD (*pzlib_filefunc_def, &c, 1))
+  if (1 != ZREAD (*ffd, &c, 1))
     return EXTRACTOR_UNZIP_EOF;
   *pi = (int) c;
   return EXTRACTOR_UNZIP_OK;
 }
 
 
+/**
+ * Read a short (2 bytes) 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.
+ *
+ * @param ffd functions for performing IO operations
+ * @param pi where to store the short that was read
+ * @return EXTRACTOR_UNZIP_OK on success, or EXTRACTOR_UNZIP_EOF
+ */
 static int 
-unzlocal_getShort (const struct EXTRACTOR_UnzipFileFuncDefs* 
pzlib_filefunc_def,
-                  uLong *pX)
+read_short_from_ffd (const struct FileFuncDefs *ffd,
+                    uLong *pX)
 {
   uLong x;
   int i;
   int err;
   
   *pX = 0;
-  if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i)))
+  if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
     return err;
   x = (uLong) i;
-  if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i)))
+  if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
     return err;
   x += ((uLong) i) << 8;  
   *pX = x;
@@ -326,25 +377,34 @@
 }
 
 
+/**
+ * Read a 'long' (4 bytes) 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.
+ *
+ * @param ffd functions for performing IO operations
+ * @param pi where to store the long that was read
+ * @return EXTRACTOR_UNZIP_OK on success, or EXTRACTOR_UNZIP_EOF
+ */
 static int 
-unzlocal_getLong (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def,
-                 uLong *pX)
+read_long_from_ffd (const struct FileFuncDefs *ffd,
+                   uLong *pX)
 {
   uLong x;
   int i;
   int err;
   
   *pX = 0;
-  if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i)))
+  if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
     return err;
   x = (uLong) i;
-  if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i)))
+  if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
     return err;
   x += ((uLong) i) << 8;
-  if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i)))
+  if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
     return err;
   x += ((uLong) i) << 16;
-  if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i)))
+  if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
     return err;
   x += ((uLong) i) << 24;
   *pX = x;
@@ -366,7 +426,7 @@
 
 
 /**
- * Compare two filename (fileName1,fileName2).
+ * Compare two filenames (fileName1, fileName2).
  *
  * @param filename1 name of first file
  * @param filename2 name of second file
@@ -394,27 +454,24 @@
 
 
 /**
+ * Locate the central directory in the ZIP file.
  *
+ * @param ffd IO functions
+ * @return offset of central directory, 0 on error
  */
 static uLong 
-unzlocal_SearchCentralDir (const struct EXTRACTOR_UnzipFileFuncDefs* 
pzlib_filefunc_def)
+locate_central_directory (const struct FileFuncDefs *ffd)
 {
-  unsigned char *buf;
+  unsigned char buf[BUFREADCOMMENT + 4];
   uLong uSizeFile;
   uLong uBackRead;
   uLong uMaxBack = 0xffff; /* maximum size of global comment */
-  uLong uPosFound = 0;
   
-  if (0 != ZSEEK (*pzlib_filefunc_def, 0, SEEK_END))
+  if (0 != ZSEEK (*ffd, 0, SEEK_END))
     return 0;
-  uSizeFile = ZTELL (*pzlib_filefunc_def);
-
+  uSizeFile = ZTELL (*ffd);
   if (uMaxBack > uSizeFile)
     uMaxBack = uSizeFile;
-
-  if (NULL == (buf = malloc(BUFREADCOMMENT + 4)))
-    return 0;
-
   uBackRead = 4;
   while (uBackRead < uMaxBack)
     {
@@ -427,156 +484,153 @@
       else
        uBackRead += BUFREADCOMMENT;
       uReadPos = uSizeFile - uBackRead;
-      
       uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) 
        ? (BUFREADCOMMENT + 4) 
        : (uSizeFile - uReadPos);
-      if (0 != ZSEEK (*pzlib_filefunc_def, uReadPos, SEEK_SET))
+      if (0 != ZSEEK (*ffd, uReadPos, SEEK_SET))
        break;
-      
-      if (ZREAD (*pzlib_filefunc_def, buf, uReadSize) != uReadSize)
+      if (ZREAD (*ffd, buf, uReadSize) != uReadSize)
        break;
-      
       i = (int) uReadSize - 3; 
       while (i-- > 0)
        if ( (0x50 == (*(buf+i))) &&
             (0x4b == (*(buf+i+1))) &&
             (0x05 == (*(buf+i+2))) && 
             (0x06 == (*(buf+i+3))) )
-         {
-           uPosFound = uReadPos + i;
-           break;
-         }
-      if (0 != uPosFound)
-       break;
+         return uReadPos + i;
     }
-  free (buf);
-  return uPosFound;
+  return 0;
 }
 
 
 /**
  * Translate date/time from Dos format to struct
  * EXTRACTOR_UnzipDateTimeInfo (readable more easilty)
+ *
+ * @param ulDosDate time in DOS format (input)
+ * @param ptm where to write time in readable format
  */
 static void 
-unzlocal_DosDateToTmuDate (uLong ulDosDate,
+dos_date_to_tmu_date (uLong ulDosDate,
                           struct EXTRACTOR_UnzipDateTimeInfo* ptm)
 {
   uLong uDate;
 
   uDate = (uLong) (ulDosDate >> 16);
   ptm->tm_mday = (uInt) (uDate & 0x1f);
-  ptm->tm_mon =  (uInt) ((((uDate) & 0x1E0) / 0x20) - 1);
+  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));
+  ptm->tm_min  = (uInt) ((ulDosDate & 0x7E0) / 0x20);
+  ptm->tm_sec  = (uInt) (2 * (ulDosDate & 0x1f));
 }
 
 
+/**
+ * Write info about the ZipFile in the *pglobal_info structure.
+ * No preparation of the structure is needed.
+ *
+ * @param file zipfile to manipulate
+ * @param pfile_info file information to initialize
+ * @param pfile_info_internal internal file information to initialize
+ * @param szFileName where to write the name of the current file
+ * @param fileNameBufferSize number of bytes available in szFileName
+ * @param extraField where to write extra data
+ * @param extraFieldBufferSize number of bytes available in extraField 
+ * @param szComment where to write the comment on the current file
+ * @param commentBufferSize number of bytes available in szComment
+ * @return EXTRACTOR_UNZIP_OK if there is no problem.
+ */
 static int 
-unzlocal_GetCurrentFileInfoInternal (struct EXTRACTOR_UnzipFile *s,
-                                    struct EXTRACTOR_UnzipFileInfo *pfile_info,
-                                    struct UnzipFileInfoInternal 
*pfile_info_internal,
-                                    char *szFileName,
-                                    uLong fileNameBufferSize,
-                                    void *extraField,
-                                    uLong extraFieldBufferSize,
-                                    char *szComment,
-                                    uLong commentBufferSize)
+get_current_file_info (struct EXTRACTOR_UnzipFile *file,
+                      struct EXTRACTOR_UnzipFileInfo *pfile_info,
+                      struct UnzipFileInfoInternal *pfile_info_internal,
+                      char *szFileName,
+                      uLong fileNameBufferSize,
+                      void *extraField,
+                      uLong extraFieldBufferSize,
+                      char *szComment,
+                      uLong commentBufferSize)
 {
   struct EXTRACTOR_UnzipFileInfo file_info;
   struct UnzipFileInfoInternal file_info_internal;
-  int err = EXTRACTOR_UNZIP_OK;
   uLong uMagic;
   long lSeek = 0;
     
-  if (s == NULL)
+  if (NULL == file)
     return EXTRACTOR_UNZIP_PARAMERROR;
-  if (0 != ZSEEK (s->z_filefunc,
-                 s->pos_in_central_dir + s->byte_before_the_zipfile,
+  if (0 != ZSEEK (file->z_filefunc,
+                 file->pos_in_central_dir + file->byte_before_the_zipfile,
                  SEEK_SET))
-    err = EXTRACTOR_UNZIP_ERRNO;
+    return EXTRACTOR_UNZIP_ERRNO;
 
   /* we check the magic */
-  if (EXTRACTOR_UNZIP_OK == err) 
-    {
-      if (unzlocal_getLong(&s->z_filefunc, &uMagic) != EXTRACTOR_UNZIP_OK)
-       err=EXTRACTOR_UNZIP_ERRNO;
-      else if (uMagic!=0x02014b50)
-       err=EXTRACTOR_UNZIP_BADZIPFILE;
-    }
-  if (unzlocal_getShort (&s->z_filefunc, &file_info.version) != 
EXTRACTOR_UNZIP_OK)
-    err = EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_long_from_ffd(&file->z_filefunc, &uMagic))
+    return EXTRACTOR_UNZIP_ERRNO;
+  if (0x02014b50 != uMagic)
+    return EXTRACTOR_UNZIP_BADZIPFILE;
 
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.version_needed) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.flag) != EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.compression_method) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getLong(&s->z_filefunc, &file_info.dosDate) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-    
-  unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
-    
-  if (unzlocal_getLong(&s->z_filefunc, &file_info.crc) != EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getLong(&s->z_filefunc, &file_info.compressed_size) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if ( (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd (&file->z_filefunc, &file_info.version)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd (&file->z_filefunc, &file_info.version_needed)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd (&file->z_filefunc, &file_info.flag)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd (&file->z_filefunc, &file_info.compression_method)) 
||
+       (EXTRACTOR_UNZIP_OK !=
+       read_long_from_ffd (&file->z_filefunc, &file_info.dosDate)) )
+    return EXTRACTOR_UNZIP_ERRNO;
+  dos_date_to_tmu_date (file_info.dosDate,
+                       &file_info.tmu_date);
+  if ( (EXTRACTOR_UNZIP_OK !=
+       read_long_from_ffd(&file->z_filefunc, &file_info.crc)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_long_from_ffd(&file->z_filefunc, &file_info.compressed_size)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_long_from_ffd(&file->z_filefunc, &file_info.uncompressed_size)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd(&file->z_filefunc, &file_info.size_filename)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd(&file->z_filefunc, &file_info.size_file_extra)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd(&file->z_filefunc, &file_info.size_file_comment)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd(&file->z_filefunc, &file_info.disk_num_start)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_short_from_ffd(&file->z_filefunc, &file_info.internal_fa)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_long_from_ffd(&file->z_filefunc, &file_info.external_fa)) ||
+       (EXTRACTOR_UNZIP_OK !=
+       read_long_from_ffd (&file->z_filefunc,
+                           &file_info_internal.offset_curfile)) )
+    return EXTRACTOR_UNZIP_ERRNO;
 
-  if (unzlocal_getLong(&s->z_filefunc, &file_info.uncompressed_size) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.size_filename) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.size_file_extra) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.size_file_comment) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.disk_num_start) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-
-  if (unzlocal_getShort(&s->z_filefunc, &file_info.internal_fa) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (unzlocal_getLong(&s->z_filefunc, &file_info.external_fa) != 
EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
-
-  if (unzlocal_getLong (&s->z_filefunc,
-                       &file_info_internal.offset_curfile) != 
EXTRACTOR_UNZIP_OK)
-    err = EXTRACTOR_UNZIP_ERRNO;
-
   lSeek += file_info.size_filename;
-  if ((err==EXTRACTOR_UNZIP_OK) && (szFileName!=NULL))
+  if (NULL != szFileName)
     {
       uLong uSizeRead;
+
       if (file_info.size_filename < fileNameBufferSize)
         {
-         *(szFileName+file_info.size_filename) = '\0';
+         *(szFileName + file_info.size_filename) = '\0';
          uSizeRead = file_info.size_filename;
         }
       else
        uSizeRead = fileNameBufferSize;
       
-      if ((file_info.size_filename > 0) && (fileNameBufferSize > 0))
-       if (ZREAD(s->z_filefunc, szFileName, uSizeRead) != uSizeRead)
-         err = EXTRACTOR_UNZIP_ERRNO;
+      if ( (file_info.size_filename > 0) && 
+          (fileNameBufferSize > 0) )
+       if (ZREAD(file->z_filefunc, szFileName, uSizeRead) != uSizeRead)
+         return EXTRACTOR_UNZIP_ERRNO;
       lSeek -= uSizeRead;
     }
   
-  
-  if ((err==EXTRACTOR_UNZIP_OK) && (extraField!=NULL))
+  if (NULL != extraField)
     {
       uLong uSizeRead;
+
       if (file_info.size_file_extra<extraFieldBufferSize)
        uSizeRead = file_info.size_file_extra;
       else
@@ -584,53 +638,55 @@
       
       if (0 != lSeek) 
        {
-         if (0 == ZSEEK (s->z_filefunc, lSeek, SEEK_CUR))
+         if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR))
            lSeek = 0;
          else
-           err = EXTRACTOR_UNZIP_ERRNO;
+           return EXTRACTOR_UNZIP_ERRNO;
        }
-      if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
-       if (ZREAD(s->z_filefunc, extraField,uSizeRead)!=uSizeRead)
-         err=EXTRACTOR_UNZIP_ERRNO;
+      if ( (file_info.size_file_extra > 0) &&
+          (extraFieldBufferSize > 0) && 
+          (ZREAD (file->z_filefunc, 
+                  extraField,
+                  uSizeRead) != uSizeRead) )
+       return EXTRACTOR_UNZIP_ERRNO;
       lSeek += file_info.size_file_extra - uSizeRead;
     }
   else
-    lSeek+=file_info.size_file_extra;
+    lSeek += file_info.size_file_extra;
   
-  
-  if ((err==EXTRACTOR_UNZIP_OK) && (szComment!=NULL))
+  if (NULL != szComment)
     {
-      uLong uSizeRead ;
-      if (file_info.size_file_comment<commentBufferSize)
+      uLong uSizeRead;
+
+      if (file_info.size_file_comment < commentBufferSize)
         {
-         *(szComment+file_info.size_file_comment)='\0';
+         *(szComment+file_info.size_file_comment) = '\0';
          uSizeRead = file_info.size_file_comment;
         }
       else
        uSizeRead = commentBufferSize;
-
-      if (lSeek!=0) 
+      
+      if (0 != lSeek) 
        {
-         if (ZSEEK(s->z_filefunc, lSeek, SEEK_CUR)==0)
-           lSeek=0;
+         if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR))
+           lSeek = 0;
          else
-           err=EXTRACTOR_UNZIP_ERRNO;
+           return EXTRACTOR_UNZIP_ERRNO;
        }
-      if ((file_info.size_file_comment>0) && (commentBufferSize>0))
-       if (ZREAD(s->z_filefunc, szComment,uSizeRead)!=uSizeRead)
-         err=EXTRACTOR_UNZIP_ERRNO;
-      lSeek+=file_info.size_file_comment - uSizeRead;
+      if ( (file_info.size_file_comment > 0) &&
+          (commentBufferSize > 0) &&
+          (ZREAD (file->z_filefunc, szComment, uSizeRead) != uSizeRead) )
+       return EXTRACTOR_UNZIP_ERRNO;
+      lSeek += file_info.size_file_comment - uSizeRead;
     }
   else
-    lSeek+=file_info.size_file_comment;
+    lSeek += file_info.size_file_comment;
   
-  if ((err==EXTRACTOR_UNZIP_OK) && (pfile_info!=NULL))
-    *pfile_info=file_info;
-  
-  if ((err==EXTRACTOR_UNZIP_OK) && (pfile_info_internal!=NULL))
-    *pfile_info_internal=file_info_internal;
-  
-  return err;
+  if (NULL != pfile_info)
+    *pfile_info = file_info;
+  if (NULL != pfile_info_internal)
+    *pfile_info_internal = file_info_internal;
+  return EXTRACTOR_UNZIP_OK;
 }
 
 
@@ -649,11 +705,11 @@
     return EXTRACTOR_UNZIP_PARAMERROR;
   file->pos_in_central_dir = file->offset_central_dir;
   file->num_file = 0;
-  err = unzlocal_GetCurrentFileInfoInternal (file,
-                                            &file->cur_file_info,
-                                             &file->cur_file_info_internal,
-                                             NULL, 0, NULL, 0, NULL, 0);
-  file->current_file_ok = (err == EXTRACTOR_UNZIP_OK);
+  err = get_current_file_info (file,
+                              &file->cur_file_info,
+                              &file->cur_file_info_internal,
+                              NULL, 0, NULL, 0, NULL, 0);
+  file->current_file_ok = (EXTRACTOR_UNZIP_OK == err);
   return err;
 }
 
@@ -661,14 +717,14 @@
 /**
  * Open a Zip file.
  *
- * @param pzlib_filefunc_def IO functions
+ * @param ffd IO functions
  * @return NULL on error
  */
 static struct EXTRACTOR_UnzipFile * 
-EXTRACTOR_common_unzip_open2 (struct EXTRACTOR_UnzipFileFuncDefs 
*pzlib_filefunc_def)
+unzip_open_using_ffd (struct FileFuncDefs *ffd)
 {
   struct EXTRACTOR_UnzipFile us;
-  struct EXTRACTOR_UnzipFile *s;
+  struct EXTRACTOR_UnzipFile *file;
   uLong central_pos;
   uLong uL;
   uLong number_disk;          /* number of the current dist, used for
@@ -678,78 +734,76 @@
   uLong number_entry_CD;      /* total number of entries in
                                 the central dir
                                 (same than number_entry on nospan) */
-  
-  int err = EXTRACTOR_UNZIP_OK;
 
   memset (&us, 0, sizeof(us)); 
-  us.z_filefunc = *pzlib_filefunc_def;
+  us.z_filefunc = *ffd;
+  central_pos = locate_central_directory (&us.z_filefunc);
+  if (0 == central_pos)
+    return NULL;
+  if (0 != ZSEEK (us.z_filefunc, 
+                 central_pos, SEEK_SET))
+    return NULL;
   
-  central_pos = unzlocal_SearchCentralDir (&us.z_filefunc);
-  if (central_pos==0)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
-  if (ZSEEK(us.z_filefunc, 
-           central_pos, SEEK_SET)!=0)
-    err=EXTRACTOR_UNZIP_ERRNO;
-  
   /* the signature, already checked */
-  if (unzlocal_getLong(&us.z_filefunc, &uL)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK != 
+      read_long_from_ffd (&us.z_filefunc, &uL))
+    return NULL;
   
   /* number of this disk */
-  if (unzlocal_getShort(&us.z_filefunc, &number_disk)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_short_from_ffd (&us.z_filefunc, &number_disk))
+    return NULL;
   
   /* number of the disk with the start of the central directory */
-  if (unzlocal_getShort(&us.z_filefunc, 
&number_disk_with_CD)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_short_from_ffd (&us.z_filefunc, &number_disk_with_CD))
+    return NULL;
   
   /* total number of entries in the central dir on this disk */
-  if (unzlocal_getShort(&us.z_filefunc, 
&us.gi.number_entry)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_short_from_ffd (&us.z_filefunc, &us.gi.number_entry))
+    return NULL;
   
   /* total number of entries in the central dir */
-  if (unzlocal_getShort(&us.z_filefunc, &number_entry_CD)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_short_from_ffd (&us.z_filefunc, &number_entry_CD))
+    return NULL;
   
-  if ((number_entry_CD!=us.gi.number_entry) ||
-      (number_disk_with_CD!=0) ||
-      (number_disk!=0))
-    err=EXTRACTOR_UNZIP_BADZIPFILE;
+  if ( (number_entry_CD != us.gi.number_entry) ||
+       (0 != number_disk_with_CD) ||
+       (0 != number_disk) )
+    return NULL;
   
   /* size of the central directory */
-  if (unzlocal_getLong(&us.z_filefunc, 
&us.size_central_dir)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_long_from_ffd (&us.z_filefunc, &us.size_central_dir))
+    return NULL;
   
   /* offset of start of central directory with respect to the
      starting disk number */
-  if (unzlocal_getLong(&us.z_filefunc, 
&us.offset_central_dir)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_long_from_ffd (&us.z_filefunc, &us.offset_central_dir))
+    return NULL;
   
   /* zipfile comment length */
-  if (unzlocal_getShort(&us.z_filefunc, 
&us.gi.size_comment)!=EXTRACTOR_UNZIP_OK)
-    err=EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK !=
+      read_short_from_ffd (&us.z_filefunc, &us.gi.size_comment))
+    return NULL;
+  us.gi.offset_comment = ZTELL (us.z_filefunc);
+  if ((central_pos < us.offset_central_dir + us.size_central_dir))
+    return NULL;
   
-  if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
-      (err==EXTRACTOR_UNZIP_OK))
-    err=EXTRACTOR_UNZIP_BADZIPFILE;
-  
-  if (err!=EXTRACTOR_UNZIP_OK)
-    {
-      return NULL;
-    }
-
   us.byte_before_the_zipfile = central_pos -
-    (us.offset_central_dir+us.size_central_dir);
+    (us.offset_central_dir + us.size_central_dir);
   us.central_pos = central_pos;
   us.pfile_in_zip_read = NULL;
   us.encrypted = 0;
   
-  if (NULL == (s = malloc (sizeof(struct EXTRACTOR_UnzipFile))))
+  if (NULL == (file = malloc (sizeof(struct EXTRACTOR_UnzipFile))))
     return NULL;
-  *s=us;
-  EXTRACTOR_common_unzip_go_to_first_file(s);
-  return s;
+  *file = us;
+  EXTRACTOR_common_unzip_go_to_first_file (file);
+  return file;
 }
 
 
@@ -759,48 +813,32 @@
  * @return EXTRACTOR_UNZIP_CRCERROR if all the file was read but the CRC is 
not good
  */
 int 
-EXTRACTOR_common_unzip_close_current_file (struct EXTRACTOR_UnzipFile * file)
+EXTRACTOR_common_unzip_close_current_file (struct EXTRACTOR_UnzipFile *file)
 {
-    int err=EXTRACTOR_UNZIP_OK;
-
-    struct EXTRACTOR_UnzipFile* s;
-    struct FileInZipReadInfo* pfile_in_zip_read_info;
-    if (file==NULL)
-        return EXTRACTOR_UNZIP_PARAMERROR;
-    s=(struct EXTRACTOR_UnzipFile*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-    if (pfile_in_zip_read_info==NULL)
-        return EXTRACTOR_UNZIP_PARAMERROR;
-
-
-    if (pfile_in_zip_read_info->rest_read_uncompressed == 0) 
-    {
-        if (pfile_in_zip_read_info->crc32 != 
pfile_in_zip_read_info->crc32_wait)
-                     err=EXTRACTOR_UNZIP_CRCERROR;
-    }
-
-
-    if (NULL != pfile_in_zip_read_info->read_buffer)
-      free(pfile_in_zip_read_info->read_buffer);
-    pfile_in_zip_read_info->read_buffer = NULL;
-    if (pfile_in_zip_read_info->stream_initialised)
-        inflateEnd(&pfile_in_zip_read_info->stream);
-
-    pfile_in_zip_read_info->stream_initialised = 0;
-    free(pfile_in_zip_read_info);
-
-    s->pfile_in_zip_read=NULL;
-
-    return err;
+  struct FileInZipReadInfo* pfile_in_zip_read_info;
+  int err = EXTRACTOR_UNZIP_OK;
+  
+  if (NULL == file)
+    return EXTRACTOR_UNZIP_PARAMERROR;
+  if (NULL == (pfile_in_zip_read_info = file->pfile_in_zip_read))
+    return EXTRACTOR_UNZIP_PARAMERROR;
+  if ( (0 == pfile_in_zip_read_info->rest_read_uncompressed) &&
+       (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) )
+    err = EXTRACTOR_UNZIP_CRCERROR;
+  if (NULL != pfile_in_zip_read_info->read_buffer)
+    free (pfile_in_zip_read_info->read_buffer);
+  pfile_in_zip_read_info->read_buffer = NULL;
+  if (pfile_in_zip_read_info->stream_initialised)
+    inflateEnd (&pfile_in_zip_read_info->stream);
+  pfile_in_zip_read_info->stream_initialised = 0;
+  free (pfile_in_zip_read_info);
+  file->pfile_in_zip_read = NULL;
+  return err;
 }
 
 
 /**
- * Close a ZipFile.  If there is files inside the .Zip opened with
- * EXTRACTOR_common_unzip_open_current_file, these files MUST be
- * closed with EXTRACTOR_common_unzip_close_current_file before
- * calling EXTRACTOR_common_unzip_close.
+ * Close a ZipFile.
  *
  * @param file zip file to close
  * @return EXTRACTOR_UNZIP_OK if there is no problem. 
@@ -808,17 +846,40 @@
 int 
 EXTRACTOR_common_unzip_close (struct EXTRACTOR_UnzipFile *file)
 {
-  struct EXTRACTOR_UnzipFile* s;
-  
-  if (file==NULL)
+  if (NULL == file)
     return EXTRACTOR_UNZIP_PARAMERROR;
-  s=(struct EXTRACTOR_UnzipFile*)file;
-  
-    if (s->pfile_in_zip_read!=NULL)
-        EXTRACTOR_common_unzip_close_current_file(file);
+  if (NULL != file->pfile_in_zip_read)
+    EXTRACTOR_common_unzip_close_current_file (file);
+  free (file);
+  return EXTRACTOR_UNZIP_OK;
+}
 
-    free(s);
-    return EXTRACTOR_UNZIP_OK;
+
+/**
+ * Obtain the global comment from a ZIP file.
+ *
+ * @param file unzip file to inspect
+ * @param comment where to copy the comment
+ * @param comment_len maximum number of bytes available in comment
+ * @return EXTRACTOR_UNZIP_OK on success
+ */
+int
+EXTRACTOR_common_unzip_get_global_comment (struct EXTRACTOR_UnzipFile *file,
+                                          char *comment,
+                                          size_t comment_len)
+{
+  if (NULL == file)
+    return EXTRACTOR_UNZIP_PARAMERROR;
+  if (comment_len > file->gi.size_comment)
+    comment_len = file->gi.size_comment + 1;
+  if (0 !=
+      ZSEEK (file->z_filefunc, file->gi.offset_comment, SEEK_SET))
+    return EXTRACTOR_UNZIP_ERRNO;
+  if (comment_len - 1 !=
+      ZREAD (file->z_filefunc, comment, comment_len - 1))
+    return EXTRACTOR_UNZIP_ERRNO;
+  comment[comment_len - 1] = '\0';
+  return EXTRACTOR_UNZIP_OK;
 }
 
 
@@ -827,6 +888,7 @@
  * No preparation of the structure is needed.
  *
  * @param file zipfile to manipulate
+ * @param pfile_info file information to initialize
  * @param szFileName where to write the name of the current file
  * @param fileNameBufferSize number of bytes available in szFileName
  * @param extraField where to write extra data
@@ -845,10 +907,10 @@
                                              char *szComment,
                                              uLong commentBufferSize)
 {
-  return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
-                                            szFileName,fileNameBufferSize,
-                                            extraField,extraFieldBufferSize,
-                                            szComment,commentBufferSize);
+  return get_current_file_info (file, pfile_info, NULL,
+                               szFileName, fileNameBufferSize,
+                               extraField, extraFieldBufferSize,
+                               szComment, commentBufferSize);
 }
 
 
@@ -860,27 +922,25 @@
  *         EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE if the actual file was the 
latest.
  */
 int 
-EXTRACTOR_common_unzip_go_to_next_file (struct EXTRACTOR_UnzipFile * file)
+EXTRACTOR_common_unzip_go_to_next_file (struct EXTRACTOR_UnzipFile *file)
 {
-    struct EXTRACTOR_UnzipFile* s;
-    int err;
-
-    if (file==NULL)
-        return EXTRACTOR_UNZIP_PARAMERROR;
-    s=(struct EXTRACTOR_UnzipFile*)file;
-    if (!s->current_file_ok)
-        return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE;
-    if (s->num_file+1==s->gi.number_entry)
-        return EXTRACTOR_UNZIP_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 = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-                                               &s->cur_file_info_internal,
-                                               NULL,0,NULL,0,NULL,0);
-    s->current_file_ok = (err == EXTRACTOR_UNZIP_OK);
-    return err;
+  int err;
+  
+  if (NULL == file)
+    return EXTRACTOR_UNZIP_PARAMERROR;
+  if (! file->current_file_ok)
+    return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE;
+  if (file->num_file + 1 == file->gi.number_entry)
+    return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE;
+  file->pos_in_central_dir += SIZECENTRALDIRITEM + 
file->cur_file_info.size_filename +
+    file->cur_file_info.size_file_extra + 
file->cur_file_info.size_file_comment;
+  file->num_file++;
+  err = get_current_file_info (file, 
+                              &file->cur_file_info,
+                              &file->cur_file_info_internal,
+                              NULL, 0, NULL, 0, NULL, 0);
+  file->current_file_ok = (EXTRACTOR_UNZIP_OK == err);
+  return err;
 }
 
 
@@ -925,20 +985,20 @@
   
   while (EXTRACTOR_UNZIP_OK == err)
     {
-      char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+      char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
 
-      err = EXTRACTOR_common_unzip_get_current_file_info (file, NULL,
-                                                         szCurrentFileName, 
sizeof (szCurrentFileName) - 1,
-                                                         NULL, 0, NULL, 0);
-      if (EXTRACTOR_UNZIP_OK == err)
-        {
-         if (0 ==
-             EXTRACTOR_common_unzip_string_file_name_compare 
(szCurrentFileName,
-                                                              szFileName,
-                                                              
iCaseSensitivity))
-           return EXTRACTOR_UNZIP_OK;
-         err = EXTRACTOR_common_unzip_go_to_next_file (file);
-        }
+      if (EXTRACTOR_UNZIP_OK !=
+         (err = EXTRACTOR_common_unzip_get_current_file_info (file, NULL,
+                                                              
szCurrentFileName, 
+                                                              sizeof 
(szCurrentFileName) - 1,
+                                                              NULL, 0, NULL, 
0)))
+       break;
+      if (0 ==
+         EXTRACTOR_common_unzip_string_file_name_compare (szCurrentFileName,
+                                                          szFileName,
+                                                          iCaseSensitivity))
+       return EXTRACTOR_UNZIP_OK;
+      err = EXTRACTOR_common_unzip_go_to_next_file (file);
     }
   
   /* We failed, so restore the state of the 'current file' to where we
@@ -969,7 +1029,7 @@
 {
   int err = EXTRACTOR_UNZIP_OK;
   uInt iRead = 0;
-  struct FileInZipReadInfo* pfile_in_zip_read_info;
+  struct FileInZipReadInfo *pfile_in_zip_read_info;
 
   if (NULL == file)
     return EXTRACTOR_UNZIP_PARAMERROR;
@@ -980,7 +1040,7 @@
   if (0 == len)
     return 0;
 
-  pfile_in_zip_read_info->stream.next_out = (Bytef*) buf;
+  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->stream.avail_out =
@@ -989,14 +1049,14 @@
   while (pfile_in_zip_read_info->stream.avail_out > 0)
     {
       if ( (0 == pfile_in_zip_read_info->stream.avail_in) &&
-          (pfile_in_zip_read_info->rest_read_compressed>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 (0 == uReadThis)
            return EXTRACTOR_UNZIP_EOF;
-         if (0  != 
+         if (0 != 
              ZSEEK (pfile_in_zip_read_info->z_filefunc,
                     pfile_in_zip_read_info->pos_in_zipfile +
                     pfile_in_zip_read_info->byte_before_the_zipfile,
@@ -1008,78 +1068,75 @@
            return EXTRACTOR_UNZIP_ERRNO;
          
          pfile_in_zip_read_info->pos_in_zipfile += uReadThis;    
-         pfile_in_zip_read_info->rest_read_compressed-=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;
+           (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)
-         {
-            uInt uDoCopy;
-           uInt i;
-           
-            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
-                (pfile_in_zip_read_info->rest_read_compressed == 0))
-                return (iRead==0) ? EXTRACTOR_UNZIP_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->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
-         {
-            uLong uTotalOutBefore;
-           uLong uTotalOutAfter;
-            const Bytef *bufBefore;
-            uLong 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);
-           
-            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
-            uOutThis = uTotalOutAfter-uTotalOutBefore;
-           
-            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 (Z_STREAM_END == err)
-             return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead;
-            if (Z_OK != err)
-             break;
-         }
+      if (0 == pfile_in_zip_read_info->compression_method)
+       {
+         uInt uDoCopy;
+         
+         if ( (0 == pfile_in_zip_read_info->stream.avail_in) &&
+              (0 == pfile_in_zip_read_info->rest_read_compressed) )
+           return (0 == iRead) ? EXTRACTOR_UNZIP_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;
+         memcpy (pfile_in_zip_read_info->stream.next_out,
+                 pfile_in_zip_read_info->stream.next_in,
+                 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
+       {
+         uLong uTotalOutBefore;
+         uLong uTotalOutAfter;
+         const Bytef *bufBefore;
+         uLong 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);
+         
+         uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+         uOutThis = uTotalOutAfter-uTotalOutBefore;
+         
+         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 (Z_STREAM_END == err)
+           return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead;
+         if (Z_OK != err)
+           break;
+       }
     }
   
   if (Z_OK == err)
@@ -1089,24 +1146,28 @@
 
 
 /**
- * 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)
+ * 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)
+ *
+ * @param file zipfile to process
+ * @param piSizeVar where to store the size of the extra info
+ * @param poffset_local_extrafield where to store the offset of the local 
extrafield
+ * @param psoze_local_extrafield where to store the size of the local 
extrafield
+ * @return EXTRACTOR_UNZIP_OK on success
  */
 static int 
-unzlocal_CheckCurrentFileCoherencyHeader (struct EXTRACTOR_UnzipFile *file,
-                                         uInt *piSizeVar,
-                                         uLong *poffset_local_extrafield,
-                                         uInt *psize_local_extrafield)
+parse_current_file_coherency_header (struct EXTRACTOR_UnzipFile *file,
+                                    uInt *piSizeVar,
+                                    uLong *poffset_local_extrafield,
+                                    uInt *psize_local_extrafield)
 {
   uLong uMagic;
   uLong uData;
   uLong uFlags;
   uLong size_filename;
   uLong size_extra_field;
-  int err = EXTRACTOR_UNZIP_OK;
 
   *piSizeVar = 0;
   *poffset_local_extrafield = 0;
@@ -1118,76 +1179,61 @@
                  SEEK_SET))
     return EXTRACTOR_UNZIP_ERRNO;
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_getLong (&file->z_filefunc,
-                       &uMagic))
-    err = EXTRACTOR_UNZIP_ERRNO;
-  else if (0x04034b50 != uMagic)
-    err = EXTRACTOR_UNZIP_BADZIPFILE;   
+      read_long_from_ffd (&file->z_filefunc,
+                         &uMagic))
+    return EXTRACTOR_UNZIP_ERRNO;
+  if (0x04034b50 != uMagic)
+    return EXTRACTOR_UNZIP_BADZIPFILE;   
   if ( (EXTRACTOR_UNZIP_OK !=
-       unzlocal_getShort (&file->z_filefunc, &uData)) ||
+       read_short_from_ffd (&file->z_filefunc, &uData)) ||
        (EXTRACTOR_UNZIP_OK !=
-       unzlocal_getShort (&file->z_filefunc, &uFlags)) )
-    err = EXTRACTOR_UNZIP_ERRNO;
-  
-  if (EXTRACTOR_UNZIP_OK != unzlocal_getShort (&file->z_filefunc, &uData))
-    err = EXTRACTOR_UNZIP_ERRNO;
-  else if ((EXTRACTOR_UNZIP_OK == err) && 
-          (uData != file->cur_file_info.compression_method))
-    err = EXTRACTOR_UNZIP_BADZIPFILE;
-
-  if ( (EXTRACTOR_UNZIP_OK == err) &&
-       (0 != file->cur_file_info.compression_method) &&
+       read_short_from_ffd (&file->z_filefunc, &uFlags)) )
+    return EXTRACTOR_UNZIP_ERRNO;
+  if (EXTRACTOR_UNZIP_OK != read_short_from_ffd (&file->z_filefunc, &uData))
+    return EXTRACTOR_UNZIP_ERRNO;
+  if (uData != file->cur_file_info.compression_method)
+    return EXTRACTOR_UNZIP_BADZIPFILE;
+  if ( (0 != file->cur_file_info.compression_method) &&
        (Z_DEFLATED != file->cur_file_info.compression_method) )
-    err = EXTRACTOR_UNZIP_BADZIPFILE;
-  
+    return EXTRACTOR_UNZIP_BADZIPFILE;  
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_getLong (&file->z_filefunc, &uData)) /* date/time */
-    err = EXTRACTOR_UNZIP_ERRNO;
-
+      read_long_from_ffd (&file->z_filefunc, &uData)) /* date/time */
+    return EXTRACTOR_UNZIP_ERRNO;
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_getLong (&file->z_filefunc, &uData)) /* crc */
-    err = EXTRACTOR_UNZIP_ERRNO;
-  else if ( (EXTRACTOR_UNZIP_OK == err) &&
-           (uData != file->cur_file_info.crc) &&
-           (0 == (uFlags & 8)) )
-    err = EXTRACTOR_UNZIP_BADZIPFILE;
-  
+      read_long_from_ffd (&file->z_filefunc, &uData)) /* crc */
+    return EXTRACTOR_UNZIP_ERRNO;
+  if ( (uData != file->cur_file_info.crc) &&
+       (0 == (uFlags & 8)) )
+    return EXTRACTOR_UNZIP_BADZIPFILE;
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_getLong(&file->z_filefunc, &uData)) /* size compr */
-    err = EXTRACTOR_UNZIP_ERRNO;
-  else if ( (EXTRACTOR_UNZIP_OK == err) && 
-           (uData != file->cur_file_info.compressed_size) &&
-           (0 == (uFlags & 8)) )
-    err = EXTRACTOR_UNZIP_BADZIPFILE;
-  
+      read_long_from_ffd(&file->z_filefunc, &uData)) /* size compr */
+    return EXTRACTOR_UNZIP_ERRNO;
+  if ( (uData != file->cur_file_info.compressed_size) &&
+       (0 == (uFlags & 8)) )
+    return EXTRACTOR_UNZIP_BADZIPFILE;
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_getLong (&file->z_filefunc,
-                       &uData)) /* size uncompr */
-    err = EXTRACTOR_UNZIP_ERRNO;
-  else if ( (EXTRACTOR_UNZIP_OK == err) && 
-           (uData != file->cur_file_info.uncompressed_size) &&
-           (0 == (uFlags & 8)))
-    err = EXTRACTOR_UNZIP_BADZIPFILE;
- 
+      read_long_from_ffd (&file->z_filefunc,
+                         &uData)) /* size uncompr */
+    return EXTRACTOR_UNZIP_ERRNO;
+  if ( (uData != file->cur_file_info.uncompressed_size) &&
+       (0 == (uFlags & 8)))
+    return EXTRACTOR_UNZIP_BADZIPFILE;
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_getShort (&file->z_filefunc, &size_filename))
-    err = EXTRACTOR_UNZIP_ERRNO;
-  else if ( (EXTRACTOR_UNZIP_OK == err) && 
-           (size_filename != file->cur_file_info.size_filename) )
-    err = EXTRACTOR_UNZIP_BADZIPFILE;
-  
+      read_short_from_ffd (&file->z_filefunc, &size_filename))
+    return EXTRACTOR_UNZIP_ERRNO;
+  if (size_filename != file->cur_file_info.size_filename)
+    return EXTRACTOR_UNZIP_BADZIPFILE;  
   *piSizeVar += (uInt) size_filename;
-  
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_getShort (&file->z_filefunc,
-                        &size_extra_field))
-    err = EXTRACTOR_UNZIP_ERRNO;
+      read_short_from_ffd (&file->z_filefunc,
+                          &size_extra_field))
+    return EXTRACTOR_UNZIP_ERRNO;
   *poffset_local_extrafield = file->cur_file_info_internal.offset_curfile +
     SIZEZIPLOCALHEADER + size_filename;
   *psize_local_extrafield = (uInt) size_extra_field;
   *piSizeVar += (uInt)size_extra_field;
   
-  return err;
+  return EXTRACTOR_UNZIP_OK;
 }
 
 
@@ -1200,7 +1246,7 @@
 int 
 EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file)
 {
-  int err = EXTRACTOR_UNZIP_OK;
+  int err;
   uInt iSizeVar;
   struct FileInZipReadInfo *pfile_in_zip_read_info;
   uLong offset_local_extrafield;  /* offset of the local extra field */
@@ -1213,14 +1259,14 @@
   if (NULL != file->pfile_in_zip_read)
     EXTRACTOR_common_unzip_close_current_file (file);
   if (EXTRACTOR_UNZIP_OK !=
-      unzlocal_CheckCurrentFileCoherencyHeader (file, 
-                                               &iSizeVar,
-                                               &offset_local_extrafield,
-                                               &size_local_extrafield))
+      parse_current_file_coherency_header (file, 
+                                          &iSizeVar,
+                                          &offset_local_extrafield,
+                                          &size_local_extrafield))
     return EXTRACTOR_UNZIP_BADZIPFILE;
-  if (NULL == (pfile_in_zip_read_info = malloc(sizeof(struct 
FileInZipReadInfo))))
+  if (NULL == (pfile_in_zip_read_info = malloc (sizeof(struct 
FileInZipReadInfo))))
     return EXTRACTOR_UNZIP_INTERNALERROR;
-  if (NULL == (pfile_in_zip_read_info->read_buffer = malloc(UNZ_BUFSIZE)))
+  if (NULL == (pfile_in_zip_read_info->read_buffer = malloc (UNZ_BUFSIZE)))
     {
       free (pfile_in_zip_read_info);
       return EXTRACTOR_UNZIP_INTERNALERROR;
@@ -1232,7 +1278,11 @@
 
   if ( (0 != file->cur_file_info.compression_method) &&
        (Z_DEFLATED != file->cur_file_info.compression_method) )
-    err = EXTRACTOR_UNZIP_BADZIPFILE;
+    {
+      // err = EXTRACTOR_UNZIP_BADZIPFILE;
+      // FIXME: we don't do anything with this 'err' code.
+      // Can this happen? Should we abort in this case?
+    }
   
   pfile_in_zip_read_info->crc32_wait = file->cur_file_info.crc;
   pfile_in_zip_read_info->crc32 = 0;
@@ -1240,8 +1290,7 @@
   pfile_in_zip_read_info->z_filefunc = file->z_filefunc;
   pfile_in_zip_read_info->byte_before_the_zipfile = 
file->byte_before_the_zipfile;
   pfile_in_zip_read_info->stream.total_out = 0;
-
-  if (file->cur_file_info.compression_method==Z_DEFLATED)
+  if (Z_DEFLATED == file->cur_file_info.compression_method)
     {
       pfile_in_zip_read_info->stream.zalloc = (alloc_func) NULL;
       pfile_in_zip_read_info->stream.zfree = (free_func) NULL;
@@ -1270,11 +1319,19 @@
     iSizeVar;
   pfile_in_zip_read_info->stream.avail_in = 0;
   file->pfile_in_zip_read = pfile_in_zip_read_info;
-  
   return EXTRACTOR_UNZIP_OK;
 }
 
 
+/**
+ * Callback to perform read operation using LE API.
+ * Note that partial reads are not allowed.
+ *
+ * @param opaque the 'struct EXTRACTOR_ExtractContext'
+ * @param buf where to write bytes read
+ * @param size number of bytes desired
+ * @return number of bytes copied to buf
+ */
 static uLong 
 ec_read_file_func (voidpf opaque,
                   void* buf,
@@ -1283,17 +1340,29 @@
   struct EXTRACTOR_ExtractContext *ec = opaque;
   void *ptr;
   ssize_t ret;
+  uLong done;
   
-  ret = ec->read (ec->cls,
-                 &ptr,
-                 size);
-  if (ret > 0)
-    memcpy (buf, ptr, ret);
-  // FIXME: partial reads are not allowed, need to possibly read more
-  return ret;
+  done = 0;
+  while (done < size)
+    {
+      ret = ec->read (ec->cls,
+                     &ptr,
+                     size);
+      if (ret <= 0)
+       return done;
+      memcpy (buf + done, ptr, ret);
+      done += ret;
+    }
+  return done;
 }
 
 
+/**
+ * Callback to obtain current offset in file using LE API.
+ *
+ * @param opaque the 'struct EXTRACTOR_ExtractContext'
+ * @return current offset in file, -1 on error
+ */
 static long 
 ec_tell_file_func (voidpf opaque)
 {
@@ -1303,6 +1372,14 @@
 }
 
 
+/**
+ * Callback to perform seek operation using LE API.
+ *
+ * @param opaque the 'struct EXTRACTOR_ExtractContext'
+ * @param offset where to seek
+ * @param origin relative to where should we seek
+ * @return EXTRACTOR_UNZIP_OK on success
+ */
 static long 
 ec_seek_file_func (voidpf opaque,                                         
                   uLong offset,
@@ -1326,14 +1403,14 @@
 struct EXTRACTOR_UnzipFile * 
 EXTRACTOR_common_unzip_open (struct EXTRACTOR_ExtractContext *ec)
 {
-  struct EXTRACTOR_UnzipFileFuncDefs io;
+  struct FileFuncDefs ffd;
 
-  io.zread_file = &ec_read_file_func;
-  io.ztell_file = &ec_tell_file_func;
-  io.zseek_file = &ec_seek_file_func;
-  io.opaque = ec;
+  ffd.zread_file = &ec_read_file_func;
+  ffd.ztell_file = &ec_tell_file_func;
+  ffd.zseek_file = &ec_seek_file_func;
+  ffd.opaque = ec;
 
-  return EXTRACTOR_common_unzip_open2 (&io);
+  return unzip_open_using_ffd (&ffd);
 }
 
 /* end of unzip.c */

Modified: Extractor/src/common/unzip.h
===================================================================
--- Extractor/src/common/unzip.h        2012-08-14 14:25:43 UTC (rev 23229)
+++ Extractor/src/common/unzip.h        2012-08-14 16:53:21 UTC (rev 23230)
@@ -208,11 +208,22 @@
 
 
 /**
- * Close a ZipFile.  If there is files inside the .Zip opened with
- * EXTRACTOR_common_unzip_open_current_file, these files MUST be
- * closed with EXTRACTOR_common_unzip_close_current_file before
- * calling EXTRACTOR_common_unzip_close.
+ * Obtain the global comment from a ZIP file.
  *
+ * @param file unzip file to inspect
+ * @param comment where to copy the comment
+ * @param comment_len maximum number of bytes available in comment
+ * @return EXTRACTOR_UNZIP_OK on success
+ */
+int
+EXTRACTOR_common_unzip_get_global_comment (struct EXTRACTOR_UnzipFile *file,
+                                          char *comment,
+                                          size_t comment_len);
+
+
+/**
+ * Close a ZipFile.
+ *
  * @param file zip file to close
  * @return EXTRACTOR_UNZIP_OK if there is no problem. 
  */
@@ -263,6 +274,7 @@
  * No preparation of the structure is needed.
  *
  * @param file zipfile to manipulate
+ * @param pfile_info file information to initialize
  * @param szFileName where to write the name of the current file
  * @param fileNameBufferSize number of bytes available in szFileName
  * @param extraField where to write extra data

Modified: Extractor/src/plugins/Makefile.am
===================================================================
--- Extractor/src/plugins/Makefile.am   2012-08-14 14:25:43 UTC (rev 23229)
+++ Extractor/src/plugins/Makefile.am   2012-08-14 16:53:21 UTC (rev 23230)
@@ -30,7 +30,9 @@
   testdata/ole2_starwriter40.sdw \
   testdata/ole2_blair.doc \
   testdata/ole2_excel.xls \
-  testdata/png_image.png
+  testdata/png_image.png \
+  testdata/odf_cg.odt \
+  testdata/deb_bzip2.deb
 
 if HAVE_VORBISFILE
 PLUGIN_OGG=libextractor_ogg.la
@@ -77,13 +79,23 @@
 TEST_GSF=test_ole2
 endif
 
+if HAVE_ZLIB
+PLUGIN_ZLIB=libextractor_deb.la
+TEST_ZLIB=test_deb
+endif
 
 plugin_LTLIBRARIES = \
   libextractor_it.la \
+  libextractor_nsf.la \
+  libextractor_nsfe.la \
+  libextractor_odf.la \
   libextractor_png.la \
   libextractor_xm.la \
   libextractor_s3m.la \
+  libextractor_sid.la \
   libextractor_wav.la \
+  libextractor_zip.la \
+  $(PLUGIN_ZLIB) \
   $(PLUGIN_OGG) \
   $(PLUGIN_MIME) \
   $(PLUGIN_GIF) \
@@ -103,6 +115,9 @@
   test_it \
   test_s3m \
   test_png \
+  test_odf \
+  test_zip \
+  $(TEST_ZLIB) \
   $(TEST_OGG) \
   $(TEST_MIME) \
   $(TEST_GIF) \
@@ -133,6 +148,55 @@
   $(PLUGINFLAGS)
 
 
+libextractor_deb_la_SOURCES = \
+  deb_extractor.c
+libextractor_deb_la_LDFLAGS = \
+  $(PLUGINFLAGS) -lz
+
+test_deb_SOURCES = \
+  test_deb.c
+test_deb_LDADD = \
+  $(top_builddir)/src/plugins/libtest.la
+
+
+libextractor_nsf_la_SOURCES = \
+  nsf_extractor.c
+libextractor_nsf_la_LDFLAGS = \
+  $(PLUGINFLAGS)
+
+
+libextractor_nsfe_la_SOURCES = \
+  nsfe_extractor.c
+libextractor_nsfe_la_LDFLAGS = \
+  $(PLUGINFLAGS)
+
+
+libextractor_odf_la_SOURCES = \
+  odf_extractor.c
+libextractor_odf_la_LDFLAGS = \
+  $(PLUGINFLAGS)
+libextractor_odf_la_LIBADD = \
+  $(top_builddir)/src/common/libextractor_common.la 
+
+test_odf_SOURCES = \
+  test_odf.c
+test_odf_LDADD = \
+  $(top_builddir)/src/plugins/libtest.la
+
+
+libextractor_zip_la_SOURCES = \
+  zip_extractor.c
+libextractor_zip_la_LDFLAGS = \
+  $(PLUGINFLAGS)
+libextractor_zip_la_LIBADD = \
+  $(top_builddir)/src/common/libextractor_common.la 
+
+test_zip_SOURCES = \
+  test_zip.c
+test_zip_LDADD = \
+  $(top_builddir)/src/plugins/libtest.la
+
+
 libextractor_png_la_SOURCES = \
   png_extractor.c
 libextractor_png_la_LDFLAGS = \
@@ -157,6 +221,11 @@
   $(top_builddir)/src/plugins/libtest.la
 
 
+libextractor_sid_la_SOURCES = \
+  sid_extractor.c
+libextractor_sid_la_LDFLAGS = \
+  $(PLUGINFLAGS)
+
 libextractor_s3m_la_SOURCES = \
   s3m_extractor.c
 libextractor_s3m_la_LDFLAGS = \

Modified: Extractor/src/plugins/deb_extractor.c
===================================================================
--- Extractor/src/plugins/deb_extractor.c       2012-08-14 14:25:43 UTC (rev 
23229)
+++ Extractor/src/plugins/deb_extractor.c       2012-08-14 16:53:21 UTC (rev 
23230)
@@ -1,10 +1,10 @@
 /*
      This file is part of libextractor.
-     (C) 2002, 2003, 2004 Vidyut Samanta and Christian Grothoff
+     (C) 2002, 2003, 2004, 2012 Vidyut Samanta and Christian Grothoff
 
      libextractor is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      libextractor is distributed in the hope that it will be useful, but
@@ -17,12 +17,11 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
-
-#include "platform.h"
-#include "extractor.h"
-#include <zlib.h>
-
-/*
+/**
+ * @file plugins/deb_extractor.c
+ * @brief plugin to support Debian archives 
+ * @author Christian Grothoff
+ *
  * The .deb is an ar-chive file.  It contains a tar.gz file
  * named "control.tar.gz" which then contains a file 'control'
  * that has the meta-data.  And which variant of the various
@@ -33,14 +32,33 @@
  * http://lists.debian.org/debian-policy/2003/12/msg00000.html
  * http://www.opengroup.org/onlinepubs/009695399/utilities/ar.html
  */
+#include "platform.h"
+#include "extractor.h"
+#include <zlib.h>
 
 
+/**
+ * Maximum file size we allow for control.tar.gz files.
+ * This is a sanity check to avoid allocating huge amounts
+ * of memory.
+ */
+#define MAX_CONTROL_SIZE (1024 * 1024)
+
+
+/**
+ * Re-implementation of 'strndup'.
+ *
+ * @param str string to duplicate
+ * @param n maximum number of bytes to copy
+ * @return NULL on error, otherwise 0-terminated copy of 'str'
+ *         with at most n characters
+ */
 static char *
 stndup (const char *str, size_t n)
 {
   char *tmp;
-  tmp = malloc (n + 1);
-  if (tmp == NULL)
+
+  if (NULL == (tmp = malloc (n + 1)))
     return NULL;
   tmp[n] = '\0';
   memcpy (tmp, str, n);
@@ -48,15 +66,29 @@
 }
 
 
-
-typedef struct
+/**
+ * Entry in the mapping from control data to LE types.
+ */
+struct Matches
 {
+  /**
+   * Key in the Debian control file.
+   */
   const char *text;
+
+  /**
+   * Corresponding type in LE.
+   */
   enum EXTRACTOR_MetaType type;
-} Matches;
+};
 
-/* see also: "man 5 deb-control" */
-static Matches tmap[] = {
+
+/**
+ * Map from deb-control entries to LE types.
+ *
+ * see also: "man 5 deb-control" 
+ */
+static struct Matches tmap[] = {
   {"Package: ",       EXTRACTOR_METATYPE_PACKAGE_NAME},
   {"Version: ",       EXTRACTOR_METATYPE_PACKAGE_VERSION},
   {"Section: ",       EXTRACTOR_METATYPE_SECTION},
@@ -79,7 +111,13 @@
 
 
 /**
- * Process the control file.
+ * Process the "control" file from the control.tar.gz
+ *
+ * @param data decompressed control data
+ * @param size number of bytes in data
+ * @param proc function to call with meta data
+ * @param proc_cls closure for 'proc'
+ * @return 0 to continue extracting, 1 if we are done
  */
 static int
 processControl (const char *data,
@@ -90,62 +128,52 @@
   size_t pos;
   char *key;
   char *val;
-
+  size_t colon;
+  size_t eol;
+  unsigned int i;
+  
   pos = 0;
   while (pos < size)
     {
-      size_t colon;
-      size_t eol;
-      int i;
-
-      colon = pos;
-      while (data[colon] != ':')
-        {
-          if ((colon > size) || (data[colon] == '\n'))
-            return 0;
-          colon++;
-        }
+      for (colon = pos; ':' != data[colon]; colon++)
+       if ((colon > size) || ('\n' == data[colon]))
+         return 0;
       colon++;
       while ((colon < size) && (isspace ((unsigned char) data[colon])))
         colon++;
       eol = colon;
       while ((eol < size) &&
-             ((data[eol] != '\n') ||
-              ((eol + 1 < size) && (data[eol + 1] == ' '))))
+             (('\n' != data[eol]) ||
+              ((eol + 1 < size) && (' '  == data[eol + 1]))))
         eol++;
       if ((eol == colon) || (eol > size))
         return 0;
-      key = stndup (&data[pos], colon - pos);
-      if (key == NULL)
+      if (NULL == (key = stndup (&data[pos], colon - pos)))
        return 0;
-      i = 0;
-      while (tmap[i].text != NULL)
+      for (i = 0; NULL != tmap[i].text; i++)
         {
-          if (0 == strcmp (key, tmap[i].text))
-            {
-              val = stndup (&data[colon], eol - colon);
-             if (val == NULL)
-               {
-                 free (key);
-                 return 0;
-               }
-             if (0 != proc (proc_cls, 
-                            "deb",
-                            tmap[i].type,
-                            EXTRACTOR_METAFORMAT_UTF8,
-                            "text/plain",
-                            val,
-                            strlen(val) + 1))
-               {
-                 free (val);
-                 free (key);
-                 return 1;
-               }
+          if (0 != strcmp (key, tmap[i].text))
+           continue;
+         if (NULL == (val = stndup (&data[colon], eol - colon)))
+           {
+             free (key);
+             return 0;
+           }
+         if (0 != proc (proc_cls, 
+                        "deb",
+                        tmap[i].type,
+                        EXTRACTOR_METAFORMAT_UTF8,
+                        "text/plain",
+                        val,
+                        strlen(val) + 1))
+           {
              free (val);
-              break;
-            }
-          i++;
-        }
+             free (key);
+             return 1;
+           }
+         free (val);
+         break;
+       }
       free (key);
       pos = eol + 1;
     }
@@ -153,62 +181,142 @@
 }
 
 
-typedef struct
+/**
+ * Header of an entry in a TAR file.
+ */
+struct TarHeader
 {
+  /**
+   * Filename.
+   */
   char name[100];
+ 
+  /**
+   * File access modes.
+   */
   char mode[8];
+
+  /**
+   * Owner of the file.
+   */
   char userId[8];
+
+  /**
+   * Group of the file.
+   */
   char groupId[8];
+
+  /**
+   * Size of the file, in octal.
+   */
   char filesize[12];
+  
+  /**
+   * Last modification time.
+   */
   char lastModTime[12];
+
+  /**
+   * Checksum of the file.
+   */
   char chksum[8];
+
+  /**
+   * Is the file a link?
+   */
   char link;
+
+  /**
+   * Destination of the link.
+   */
   char linkName[100];
-} TarHeader;
+};
 
-typedef struct
+
+/**
+ * Extended TAR header for USTar format.
+ */
+struct USTarHeader
 {
-  TarHeader tar;
+  /**
+   * Original TAR header.
+   */
+  struct TarHeader tar;
+
+  /**
+   * Additinal magic for USTar.
+   */
   char magic[6];
+
+  /**
+   * Format version.
+   */
   char version[2];
+
+  /**
+   * User name.
+   */
   char uname[32];
+
+  /**
+   * Group name.
+   */
   char gname[32];
+
+  /**
+   * Device major number.
+   */
   char devmajor[8];
+
+  /**
+   * Device minor number.
+   */
   char devminor[8];
+
+  /**
+   * Unknown (padding?).
+   */
   char prefix[155];
-} USTarHeader;
+};
 
+
 /**
  * Process the control.tar file.
+ *
+ * @param data the deflated control.tar file data
+ * @param size number of bytes in data
+ * @param proc function to call with meta data
+ * @param proc_cls closure for 'proc'
+ * @return 0 to continue extracting, 1 if we are done
  */
 static int
 processControlTar (const char *data,
-                   const size_t size,
+                  size_t size,
                   EXTRACTOR_MetaDataProcessor proc,
                   void *proc_cls)
 {
-  TarHeader *tar;
-  USTarHeader *ustar;
+  struct TarHeader *tar;
+  struct USTarHeader *ustar;
   size_t pos;
 
   pos = 0;
-  while (pos + sizeof (TarHeader) < size)
+  while (pos + sizeof (struct TarHeader) < size)
     {
       unsigned long long fsize;
       char buf[13];
 
-      tar = (TarHeader *) & data[pos];
-      if (pos + sizeof (USTarHeader) < size)
+      tar = (struct TarHeader *) & data[pos];
+      if (pos + sizeof (struct USTarHeader) < size)
         {
-          ustar = (USTarHeader *) & data[pos];
+          ustar = (struct USTarHeader *) & data[pos];
           if (0 == strncmp ("ustar", &ustar->magic[0], strlen ("ustar")))
-            pos += 512;         /* sizeof(USTarHeader); */
+            pos += 512;         /* sizeof (struct USTarHeader); */
           else
-            pos += 257;         /* sizeof(TarHeader); minus gcc alignment... */
+            pos += 257;         /* sizeof (struct TarHeader); minus gcc 
alignment... */
         }
       else
         {
-          pos += 257;           /* sizeof(TarHeader); minus gcc alignment... */
+          pos += 257;           /* sizeof (struct TarHeader); minus gcc 
alignment... */
         }
 
       memcpy (buf, &tar->filesize[0], 12);
@@ -220,9 +328,10 @@
 
       if (0 == strncmp (&tar->name[0], "./control", strlen ("./control")))
         {
+         /* found the 'control' file we were looking for */
           return processControl (&data[pos], fsize, proc, proc_cls);
         }
-      if ((fsize & 511) != 0)
+      if (0 != (fsize & 511))
         fsize = (fsize | 511) + 1;      /* round up! */
       if (pos + fsize < pos)
         return 0;
@@ -231,137 +340,184 @@
   return 0;
 }
 
-#define MAX_CONTROL_SIZE (1024 * 1024)
 
-static voidpf
-Emalloc (voidpf opaque, uInt items, uInt size)
-{
-  if (SIZE_MAX / size <= items)
-    return NULL;
-  return malloc (size * items);
-}
-
-static void
-Efree (voidpf opaque, voidpf ptr)
-{
-  free (ptr);
-}
-
 /**
  * Process the control.tar.gz file.
+ *
+ * @param ec extractor context with control.tar.gz at current read position
+ * @param size number of bytes in the control file
+ * @return 0 to continue extracting, 1 if we are done
  */
 static int
-processControlTGZ (const unsigned char *data,
-                   size_t size, 
-                  EXTRACTOR_MetaDataProcessor proc,
-                  void *proc_cls)
+processControlTGZ (struct EXTRACTOR_ExtractContext *ec,
+                   unsigned long long size)
 {
   uint32_t bufSize;
   char *buf;
+  void *data;
+  unsigned char *cdata;
   z_stream strm;
   int ret;
+  ssize_t sret;
+  unsigned long long off;
 
-  bufSize = data[size - 4] + (data[size - 3] << 8) + (data[size - 2] << 16) + 
(data[size - 1] << 24);
+  if (size > MAX_CONTROL_SIZE)
+    return 0;
+  if (NULL == (cdata = malloc (size)))
+    return 0;
+  off = 0;
+  while (off < size)
+    {
+      if (0 >= (sret = ec->read (ec->cls, &data, size - off)))
+       {
+         free (cdata);
+         return 0;
+       }
+      memcpy (&cdata[off], data, sret);
+      off += sret;
+    }
+  bufSize = cdata[size - 4] + (cdata[size - 3] << 8) + (cdata[size - 2] << 16) 
+ (cdata[size - 1] << 24);
   if (bufSize > MAX_CONTROL_SIZE)
-    return 0;
+    {
+      free (cdata);
+      return 0;
+    }
+  if (NULL == (buf = malloc (bufSize)))
+    {
+      free (cdata);
+      return 0;
+    }
+  ret = 0;
   memset (&strm, 0, sizeof (z_stream));
   strm.next_in = (Bytef *) data;
   strm.avail_in = size;
-  strm.total_in = 0;
-  strm.zalloc = &Emalloc;
-  strm.zfree = &Efree;
-  strm.opaque = NULL;
-
   if (Z_OK == inflateInit2 (&strm, 15 + 32))
-    {
-      buf = malloc (bufSize);
-      if (buf == NULL)
-        {
-          inflateEnd (&strm);
-          return 0;
-        }
+    {  
       strm.next_out = (Bytef *) buf;
       strm.avail_out = bufSize;
       inflate (&strm, Z_FINISH);
       if (strm.total_out > 0)
-        {
-          ret = processControlTar (buf, strm.total_out, proc, proc_cls);
-          inflateEnd (&strm);
-          free (buf);
-          return ret;
-        }
-      free (buf);
+       ret = processControlTar (buf, strm.total_out, 
+                                ec->proc, ec->cls);
       inflateEnd (&strm);
     }
-  return 0;
+  free (buf);
+  free (cdata);
+  return ret;
 }
 
-typedef struct
+
+/**
+ * Header of an object in an "AR"chive file.
+ */
+struct ObjectHeader
 {
+  /**
+   * Name of the file.
+   */
   char name[16];
+
+  /**
+   * Last modification time for the file.
+   */
   char lastModTime[12];
+
+  /**
+   * User ID of the owner.
+   */
   char userId[6];
+
+  /**
+   * Group ID of the owner.
+   */
   char groupId[6];
+
+  /**
+   * File access modes.
+   */
   char modeInOctal[8];
+
+  /**
+   * Size of the file (as decimal string)
+   */
   char filesize[10];
+
+  /**
+   * Tailer of the object header ("`\n")
+   */
   char trailer[2];
-} ObjectHeader;
+};
 
 
-int 
-EXTRACTOR_deb_extract (const char *data,
-                      size_t size,
-                      EXTRACTOR_MetaDataProcessor proc,
-                      void *proc_cls,
-                      const char *options)
+/**
+ * Main entry method for the DEB extraction plugin.  
+ *
+ * @param ec extraction context provided to the plugin
+ */
+void 
+EXTRACTOR_deb_extract_method (struct EXTRACTOR_ExtractContext *ec)
 {
-  size_t pos;
+  uint64_t pos;
   int done = 0;
-  ObjectHeader *hdr;
-  unsigned long long fsize;
+  const struct ObjectHeader *hdr;
+  uint64_t fsize;
+  unsigned long long csize;
   char buf[11];
+  void *data;
 
-  if (size < 128)
-    return 0;
-  if (0 != strncmp ("!<arch>\n", data, strlen ("!<arch>\n")))
-    return 0;
-  pos = strlen ("!<arch>\n");
-  while (pos + sizeof (ObjectHeader) < size)
+  fsize = ec->get_size (ec->cls);
+  if (fsize < 128)
+    return;
+  if (8 !=
+      ec->read (ec->cls, &data, 8))
+    return;
+  if (0 != strncmp ("!<arch>\n", data, 8))
+    return;
+  pos = 8;
+  while (pos + sizeof (struct ObjectHeader) < fsize)
     {
-      hdr = (ObjectHeader *) & data[pos];
+      if (pos !=
+         ec->seek (ec->cls, pos, SEEK_SET))
+       return;
+      if (sizeof (struct ObjectHeader) !=
+         ec->read (ec->cls, &data, sizeof (struct ObjectHeader)))
+       return;
+      hdr = data;
       if (0 != strncmp (&hdr->trailer[0], "`\n", 2))
-        return 0;
+        return;
       memcpy (buf, &hdr->filesize[0], 10);
       buf[10] = '\0';
-      if (1 != sscanf (buf, "%10llu", &fsize))
-        return 0;
-      pos += sizeof (ObjectHeader);
-      if ((pos + fsize > size) || (fsize > size) || (pos + fsize < pos))
-        return 0;
+      if (1 != sscanf (buf, "%10llu", &csize))
+        return;
+      pos += sizeof (struct ObjectHeader);
+      if ((pos + csize > fsize) || (csize > fsize) || (pos + csize < pos))
+        return;
       if (0 == strncmp (&hdr->name[0],
-                        "control.tar.gz", strlen ("control.tar.gz")))
+                        "control.tar.gz", 
+                       strlen ("control.tar.gz")))
         {
-          if (0 != processControlTGZ ((const unsigned char *) &data[pos],
-                                     fsize, proc, proc_cls))
-           return 1;
+         if (0 != processControlTGZ (ec,
+                                     csize))
+           return;
           done++;
         }
       if (0 == strncmp (&hdr->name[0],
                         "debian-binary", strlen ("debian-binary")))
         {
-         if (0 != proc (proc_cls, 
-                        "deb",
-                        EXTRACTOR_METATYPE_MIMETYPE,
-                        EXTRACTOR_METAFORMAT_UTF8,
-                        "text/plain",
-                        "application/x-debian-package",
-                        strlen ("application/x-debian-package")+1))
-           return 1;
+         if (0 != ec->proc (ec->cls, 
+                            "deb",
+                            EXTRACTOR_METATYPE_MIMETYPE,
+                            EXTRACTOR_METAFORMAT_UTF8,
+                            "text/plain",
+                            "application/x-debian-package",
+                            strlen ("application/x-debian-package")+1))
+           return;
           done++;
         }
-      pos += fsize;
-      if (done == 2)
+      pos += csize;
+      if (2 == done)
         break;                  /* no need to process the rest of the archive 
*/
     }
-  return 0;
 }
+
+/* end of deb_extractor.c */

Modified: Extractor/src/plugins/nsf_extractor.c
===================================================================
--- Extractor/src/plugins/nsf_extractor.c       2012-08-14 14:25:43 UTC (rev 
23229)
+++ Extractor/src/plugins/nsf_extractor.c       2012-08-14 16:53:21 UTC (rev 
23230)
@@ -1,10 +1,10 @@
 /*
  * This file is part of libextractor.
- * (C) 2006, 2009 Toni Ruottu
+ * (C) 2006, 2009, 2012 Toni Ruottu and Christian Grothoff
  *
  * libextractor is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
+ * by the Free Software Foundation; either version 3, or (at your
  * option) any later version.
  *
  * libextractor is distributed in the hope that it will be useful, but
@@ -18,21 +18,22 @@
  * Boston, MA 02111-1307, USA.
  *
  */
-
+/**
+ * @file plugins/nsf_extractor.c
+ * @brief plugin to support Nes Sound Format files
+ * @author Toni Ruottu
+ * @author Christian Grothoff
+ */
 #include "platform.h"
 #include "extractor.h"
-#include "convert.h"
 
 
-#define HEADER_SIZE  0x80
 
 /* television system flags */
-
 #define PAL_FLAG     0x01
 #define DUAL_FLAG    0x02
 
 /* sound chip flags */
-
 #define VRCVI_FLAG   0x01
 #define VRCVII_FLAG  0x02
 #define FDS_FLAG     0x04
@@ -40,43 +41,108 @@
 #define NAMCO_FLAG   0x10
 #define SUNSOFT_FLAG 0x20
 
-#define UINT16 unsigned short
 
+/**
+ * Header of an NSF file.
+ */
 struct header
 {
+  /**
+   * Magic code.
+   */
   char magicid[5];
+  
+  /**
+   * NSF version number.
+   */
   char nsfversion;
-  char songs;
-  char firstsong;
-  UINT16 loadaddr;
-  UINT16 initaddr;
-  UINT16 playaddr;
+
+  /**
+   * Number of songs.
+   */
+  unsigned char songs;
+
+  /**
+   * Starting song.
+   */
+  unsigned char firstsong;
+
+  /**
+   * Unknown.
+   */
+  uint16_t loadaddr;
+
+  /**
+   * Unknown.
+   */
+  uint16_t initaddr;
+
+  /**
+   * Unknown.
+   */
+  uint16_t playaddr;
+
+  /**
+   * Album title.
+   */
   char title[32];
+  
+  /**
+   * Artist name. 
+   */
   char artist[32];
+
+  /**
+   * Copyright information.
+   */
   char copyright[32];
-  UINT16 ntscspeed;
+
+  /**
+   * Unknown.
+   */
+  uint16_t ntscspeed;
+
+  /**
+   * Unknown.
+   */
   char bankswitch[8];
-  UINT16 palspeed;
+
+  /**
+   * Unknown.
+   */
+  uint16_t palspeed;
+
+  /**
+   * Flags for TV encoding.
+   */
   char tvflags;
+
+  /**
+   * Flags about the decoder chip.
+   */
   char chipflags;
 };
 
-#define ADD(s,t) do { if (0 != proc (proc_cls, "nsf", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) return 1; } while (0)
 
+/**
+ * Give metadata to LE; return if 'proc' returns non-zero.
+ *
+ * @param s metadata value as UTF8
+ * @param t metadata type to use
+ */
+#define ADD(s,t) do { if (0 != ec->proc (ec->cls, "nsf", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return; } while (0)
 
-/* "extract" keyword from a Nes Sound Format file
+
+/**
+ * "extract" meta data from a Nes Sound Format file
  *
- * NSF specification version 1.61 was used,
- * while this piece of software was originally
- * written.
+ * NSF specification version 1.61 was used, while this piece of
+ * software was originally written.
  *
+ * @param ec extraction context
  */
-int 
-EXTRACTOR_nsf_extract (const unsigned char *data,
-                      size_t size,
-                      EXTRACTOR_MetaDataProcessor proc,
-                      void *proc_cls,
-                      const char *options)
+void
+EXTRACTOR_nsf_extract_method (struct EXTRACTOR_ExtractContext *ec)
 {
   char album[33];
   char artist[33];
@@ -85,12 +151,18 @@
   char startingsong[32];
   char nsfversion[32];
   const struct header *head;
-  
-  if (size < HEADER_SIZE)    
-    return 0;    
-  head = (const struct header *) data;
+  void *data;
+
+  if (sizeof (struct header) >
+      ec->read (ec->cls,
+               &data,
+               sizeof (struct header)))
+    return;
+  head = data; 
+
+  /* Check "magic" id bytes */
   if (memcmp (head->magicid, "NESM\x1a", 5))
-    return 0;
+    return;
   ADD ("audio/x-nsf", EXTRACTOR_METATYPE_MIMETYPE);
   snprintf (nsfversion,
            sizeof(nsfversion),
@@ -100,50 +172,48 @@
   snprintf (songs, 
            sizeof(songs),
            "%d",
-           head->songs);
+           (int) head->songs);
   ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT);
   snprintf (startingsong, 
            sizeof(startingsong),
            "%d", 
-           head->firstsong);
+           (int) head->firstsong);
   ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG);
-
   memcpy (&album, head->title, 32);
   album[32] = '\0';
   ADD (album, EXTRACTOR_METATYPE_ALBUM);
-
   memcpy (&artist, head->artist, 32);
   artist[32] = '\0';
   ADD (artist, EXTRACTOR_METATYPE_ARTIST);
-
   memcpy (&copyright, head->copyright, 32);
   copyright[32] = '\0';
   ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT);
 
-  if (head->tvflags & DUAL_FLAG)
+  if (0 != (head->tvflags & DUAL_FLAG))
     {
       ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
     }
   else
     {
-      if (head->tvflags & PAL_FLAG)
+      if (0 != (head->tvflags & PAL_FLAG))
        ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);        
       else
         ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);        
     }
 
   /* Detect Extra Sound Chips needed to play the files */
-  if (head->chipflags & VRCVI_FLAG)    
+  if (0 != (head->chipflags & VRCVI_FLAG))
     ADD ("VRCVI", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);    
-  if (head->chipflags & VRCVII_FLAG)
+  if (0 != (head->chipflags & VRCVII_FLAG))
     ADD ("VRCVII", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  if (head->chipflags & FDS_FLAG)
+  if (0 != (head->chipflags & FDS_FLAG))
     ADD ("FDS Sound", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  if (head->chipflags & MMC5_FLAG)
+  if (0 != (head->chipflags & MMC5_FLAG))
     ADD ("MMC5 audio", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  if (head->chipflags & NAMCO_FLAG)
+  if (0 != (head->chipflags & NAMCO_FLAG))
     ADD ("Namco 106", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  if (head->chipflags & SUNSOFT_FLAG)
+  if (0 != (head->chipflags & SUNSOFT_FLAG))
     ADD ("Sunsoft FME-07", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  return 0;
 }
+
+/* end of nsf_extractor.c */

Modified: Extractor/src/plugins/nsfe_extractor.c
===================================================================
--- Extractor/src/plugins/nsfe_extractor.c      2012-08-14 14:25:43 UTC (rev 
23229)
+++ Extractor/src/plugins/nsfe_extractor.c      2012-08-14 16:53:21 UTC (rev 
23230)
@@ -1,10 +1,10 @@
 /*
  * This file is part of libextractor.
- * (C) 2007, 2009 Toni Ruottu
+ * (C) 2007, 2009, 2012 Toni Ruottu and Christian Grothoff
  * 
  * libextractor is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
+ * by the Free Software Foundation; either version 3, or (at your
  * option) any later version.
  * 
  * libextractor is distributed in the hope that it will be useful, but
@@ -18,20 +18,22 @@
  * Boston, MA 02111-1307, USA.
  *
  */
-
+/**
+ * @file plugins/nsfe_extractor.c
+ * @brief plugin to support Nes Sound Format files
+ * @author Toni Ruottu
+ * @author Christian Grothoff
+ */
 #include "platform.h"
 #include "extractor.h"
 #include "convert.h"
 
-#define HEADER_SIZE  0x04
 
 /* television system flags */
-
 #define PAL_FLAG     0x01
 #define DUAL_FLAG    0x02
 
 /* sound chip flags */
-
 #define VRCVI_FLAG   0x01
 #define VRCVII_FLAG  0x02
 #define FDS_FLAG     0x04
@@ -39,29 +41,26 @@
 #define NAMCO_FLAG   0x10
 #define SUNSOFT_FLAG 0x20
 
-#define UINT16 unsigned short
-
+/**
+ * "Header" of an NSFE file.
+ */
 struct header
 {
   char magicid[4];
 };
 
-struct infochunk
-{
-  UINT16 loadaddr;
-  UINT16 initaddr;
-  UINT16 playaddr;
-  char tvflags;
-  char chipflags;
-  char songs;
-  char firstsong;
-};
 
-static int
+/**
+ * Read an unsigned integer at the current offset.
+ * 
+ * @param data input data to parse
+ * @return parsed integer
+ */ 
+static uint32_t
 nsfeuint (const char *data)
 {
   int i;
-  int value = 0;
+  uint32_t value = 0;
 
   for (i = 3; i > 0; i--)
     {
@@ -73,8 +72,17 @@
 }
 
 
+/**
+ * Copy string starting at 'data' with at most
+ * 'size' bytes. (strndup).
+ *
+ * @param data input data to copy
+ * @param size number of bytes in 'data'
+ * @return copy of the string at data
+ */
 static char *
-nsfestring (const char *data, size_t size)
+nsfestring (const char *data, 
+           size_t size)
 {
   char *s;
   size_t length;
@@ -83,105 +91,210 @@
   while ( (length < size) &&
          (data[length] != '\0') )
     length++;
-  s = malloc (length + 1);
-  if (s == NULL)
+  if (NULL == (s = malloc (length + 1)))
     return NULL;
-  strncpy (s, data, length);
-  s[strlen (data)] = '\0';
+  memcpy (s, data, length);
+  s[length] = '\0';
   return s;
 }
 
-#define ADD(s,t) do { if (0 != proc (proc_cls, "nsfe", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) return 1; } while (0)
 
-#define ADDF(s,t) do { if (0 != proc (proc_cls, "nsfe", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) { free(s); return 1; 
} free (s); } while (0)
+/**
+ * Give metadata to LE; return if 'proc' returns non-zero.
+ *
+ * @param s metadata value as UTF8
+ * @param t metadata type to use
+ */
+#define ADD(s,t) do { if (0 != ec->proc (ec->cls, "nsfe", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return  1; } while 
(0)
 
+
+/**
+ * Give metadata to LE; return if 'proc' returns non-zero.
+ *
+ * @param s metadata value as UTF8, free at the end
+ * @param t metadata type to use
+ */
+#define ADDF(s,t) do { if (0 != ec->proc (ec->cls, "nsfe", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) { free (s); return 
1; } free (s); } while (0)
+
+
+/**
+ * Format of an 'INFO' chunk.  Last two bytes are optional.
+ */
+struct infochunk
+{
+  /**
+   * Unknown.
+   */
+  uint16_t loadaddr;
+
+  /**
+   * Unknown.
+   */
+  uint16_t initaddr;
+
+  /**
+   * Unknown.
+   */
+  uint16_t playaddr;
+
+  /**
+   * TV encoding flags.
+   */
+  char tvflags;
+
+  /**
+   * Chipset encoding flags.
+   */
+  char chipflags;
+
+  /**
+   * Number of songs.
+   */
+  unsigned char songs;
+
+  /**
+   * Starting song.
+   */
+  unsigned char firstsong;
+};
+
+
+/**
+ * Extract data from the INFO chunk.
+ *
+ * @param ec extraction context
+ * @param size number of bytes in INFO chunk
+ * @return 0 to continue extrating
+ */
 static int
-libextractor_nsfe_info_extract(const char *data, 
-                              size_t size, 
-                              EXTRACTOR_MetaDataProcessor proc,
-                              void *proc_cls)
+info_extract (struct EXTRACTOR_ExtractContext *ec,
+             uint32_t size)
 {
+  void *data;
   const struct infochunk *ichunk;
   char songs[32];
 
-  if (size < 8)    
+  if (size < 8)
     return 0;
-  ichunk = (const struct infochunk *) data;
-  if (ichunk->tvflags & DUAL_FLAG)
+  if (size >
+      ec->read (ec->cls,
+               &data,
+               size))
+    return 1;
+  ichunk = data; 
+
+  if (0 != (ichunk->tvflags & DUAL_FLAG))
     {
       ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
     }
   else
     {
-      if (ichunk->tvflags & PAL_FLAG)
+      if (0 != (ichunk->tvflags & PAL_FLAG))
         ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
       else
         ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);        
     }
 
-  if (ichunk->chipflags & VRCVI_FLAG)
+  if (0 != (ichunk->chipflags & VRCVI_FLAG))
     ADD ("VRCVI", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  if (ichunk->chipflags & VRCVII_FLAG)
+  if (0 != (ichunk->chipflags & VRCVII_FLAG))
     ADD ("VRCVII", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  if (ichunk->chipflags & FDS_FLAG)
+  if (0 != (ichunk->chipflags & FDS_FLAG))
     ADD ("FDS Sound", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);    
-  if (ichunk->chipflags & MMC5_FLAG)
+  if (0 != (ichunk->chipflags & MMC5_FLAG))
     ADD ("MMC5 audio", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);    
-  if (ichunk->chipflags & NAMCO_FLAG)
+  if (0 != (ichunk->chipflags & NAMCO_FLAG))
     ADD ("Namco 106", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
-  if (ichunk->chipflags & SUNSOFT_FLAG)
+  if (0 != (ichunk->chipflags & SUNSOFT_FLAG))
     ADD ("Sunsoft FME-07", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);    
-  if (size < 9)
+
+  if (size < sizeof (struct infochunk))
     {
       ADD ("1", EXTRACTOR_METATYPE_SONG_COUNT);
       return 0;
     }
   snprintf (songs, 
-           sizeof(songs),
+           sizeof (songs),
            "%d",
            ichunk->songs);
   ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT);
+  snprintf (songs, 
+           sizeof (songs),
+           "%d",
+           ichunk->firstsong);
+  ADD (songs, EXTRACTOR_METATYPE_STARTING_SONG);
   return 0;
 }
 
 
+/**
+ * Extract data from the TLBL chunk.
+ *
+ * @param ec extraction context
+ * @param size number of bytes in TLBL chunk
+ * @return 0 to continue extrating
+ */
 static int
-libextractor_nsfe_tlbl_extract(const char *data, 
-                              size_t size,
-                              EXTRACTOR_MetaDataProcessor proc,
-                              void *proc_cls)
-
+tlbl_extract (struct EXTRACTOR_ExtractContext *ec,
+             uint32_t size)
 {
   char *title;
   ssize_t left;
   size_t length;
+  void *data;
+  const char *cdata;
 
-  for (left = size; left > 0; left -= length)
+  if (size >
+      ec->read (ec->cls,
+               &data,
+               size))
+    return 1;
+  cdata = data; 
+
+  left = size; 
+  while (left > 0)
     {
-      title = nsfestring (&data[size - left], left);
-      if (title == NULL)
-       return 0;       
+      title = nsfestring (&cdata[size - left], left);
+      if (NULL == title)
+       return 0; 
       length = strlen (title) + 1;
       ADDF (title, EXTRACTOR_METATYPE_TITLE);
+      left -= length;
     }
   return 0;
 }
 
+
+/**
+ * Extract data from the AUTH chunk.
+ *
+ * @param ec extraction context
+ * @param size number of bytes in AUTH chunk
+ * @return 0 to continue extrating
+ */
 static int
-libextractor_nsfe_auth_extract (const char *data, size_t size, 
-                               EXTRACTOR_MetaDataProcessor proc,
-                               void *proc_cls)
+auth_extract (struct EXTRACTOR_ExtractContext *ec,
+             uint32_t size)
 {
   char *album;
   char *artist;
   char *copyright;
   char *ripper;
-  int left = size;
+  uint32_t left = size;
+  void *data;
+  const char *cdata;
 
   if (left < 1)
     return 0;
-  album = nsfestring (&data[size - left], left);
-  if (album != NULL)
+  if (size >
+      ec->read (ec->cls,
+               &data,
+               size))
+    return 1;
+  cdata = data; 
+
+  album = nsfestring (&cdata[size - left], left);
+  if (NULL != album)
     {
       left -= (strlen (album) + 1);
       ADDF (album, EXTRACTOR_METATYPE_ALBUM);
@@ -189,8 +302,8 @@
        return 0;    
     }
 
-  artist = nsfestring (&data[size - left], left);
-  if (artist != NULL)
+  artist = nsfestring (&cdata[size - left], left);
+  if (NULL != artist)
     {
       left -= (strlen (artist) + 1);
       ADDF (artist, EXTRACTOR_METATYPE_ARTIST);
@@ -198,67 +311,78 @@
        return 0;
     }
 
-  copyright = nsfestring (&data[size - left], left);
-  if (copyright != NULL)
+  copyright = nsfestring (&cdata[size - left], left);
+  if (NULL != copyright)
     {
       left -= (strlen (copyright) + 1);
       ADDF (copyright, EXTRACTOR_METATYPE_COPYRIGHT);
       if (left < 1)
        return 0;
     }
-  ripper = nsfestring (&data[size - left], left);
-  if (ripper != NULL)
+  ripper = nsfestring (&cdata[size - left], left);
+  if (NULL != ripper)
     ADDF (ripper, EXTRACTOR_METATYPE_RIPPER);
   return 0;
 }
 
 
-/* "extract" keyword from an Extended Nintendo Sound Format file
+/**
+ * "extract" meta data from an Extended Nintendo Sound Format file
  *
- * NSFE specification revision 2 (Sep. 3, 2003)
- * was used, while this piece of software was
- * originally written.
+ * NSFE specification revision 2 (Sep. 3, 2003) was used, while this
+ * piece of software was originally written.
  *
+ * @param ec extraction context
  */
-int 
-EXTRACTOR_nsfe_extract (const char *data,
-                       size_t size,
-                       EXTRACTOR_MetaDataProcessor proc,
-                       void *proc_cls,
-                       const char *options)
+void
+EXTRACTOR_nsfe_extract_method (struct EXTRACTOR_ExtractContext *ec)
 {
   const struct header *head;
-  int i;
-  char chunkid[5] = "     ";
+  void *data;
+  uint64_t off;
+  uint32_t chunksize;
   int ret;
+  
+  if (sizeof (struct header) >
+      ec->read (ec->cls,
+               &data,
+               sizeof (struct header)))
+    return;
+  head = data; 
+  if (0 != memcmp (head->magicid, "NSFE", 4))
+    return;
 
-  if (size < HEADER_SIZE)    
-    return 0;
-  head = (const struct header *) data;
-  if (memcmp (head->magicid, "NSFE", 4))    
-    return 0;
-  ADD ("audio/x-nsfe", EXTRACTOR_METATYPE_MIMETYPE);
-  i = 4;                        /* Jump over magic id */
+  if (0 != ec->proc (ec->cls, 
+                    "nsfe",
+                    EXTRACTOR_METATYPE_MIMETYPE,
+                    EXTRACTOR_METAFORMAT_UTF8, 
+                    "text/plain", 
+                    "audio/x-nsfe", 
+                    strlen ("audio/x-nsfe") + 1))
+    return; 
+  off = sizeof (struct header);
   ret = 0;
-  while (i + 7 < size && strncmp (chunkid, "NEND", 4))  /* CHECK */
+  while (0 == ret)
     {
-      unsigned int chunksize = nsfeuint (&data[i]);
-
-      i += 4;                   /* Jump over chunk size */
-      memcpy (&chunkid, data + i, 4);
-      chunkid[4] = '\0';
-
-      i += 4;                   /* Jump over chunk id */
-      if (!strncmp (chunkid, "INFO", 4))
-        ret = libextractor_nsfe_info_extract (data + i, chunksize, proc, 
proc_cls);        
-      else if (!strncmp (chunkid, "auth", 4))
-       ret = libextractor_nsfe_auth_extract (data + i, chunksize, proc, 
proc_cls);        
-      else if (!strncmp (chunkid, "tlbl", 4))
-       ret = libextractor_nsfe_tlbl_extract (data + i, chunksize, proc, 
proc_cls);
+      if (off != ec->seek (ec->cls,
+                          off,
+                          SEEK_SET))
+       break;
+      if (8 >
+         ec->read (ec->cls,
+                   &data,
+                   sizeof (struct header)))
+       break;
+      chunksize = nsfeuint (data);
+      off += 4 + chunksize;
+      if (0 == memcmp (data + 4, "INFO", 4))
+        ret = info_extract (ec, chunksize);        
+      else if (0 == memcmp (data + 4, "auth", 4))
+       ret = auth_extract (ec, chunksize);        
+      else if (0 == memcmp (data + 4, "tlbl", 4))
+       ret = tlbl_extract (ec, chunksize);
       /* Ignored chunks: DATA, NEND, plst, time, fade, BANK */
-      i += chunksize;
-      if (ret != 0)
-       break;
     }
-  return ret;
 }
+
+/* end of nsfe_extractor.c */

Modified: Extractor/src/plugins/odf_extractor.c
===================================================================
--- Extractor/src/plugins/odf_extractor.c       2012-08-14 14:25:43 UTC (rev 
23229)
+++ Extractor/src/plugins/odf_extractor.c       2012-08-14 16:53:21 UTC (rev 
23230)
@@ -28,11 +28,6 @@
 #include "unzip.h"
 
 /**
- * Should filenames be treated as case sensitive?
- */
-#define CASESENSITIVITY 0
-
-/**
  * Maximum length of a filename allowed inside the ZIP archive.
  */
 #define MAXFILENAME 256
@@ -90,17 +85,17 @@
  * @return NULL if no mimetype could be found, otherwise the mime type
  */
 static char *
-libextractor_oo_getmimetype (EXTRACTOR_unzip_file uf) 
+libextractor_oo_getmimetype (struct EXTRACTOR_UnzipFile * uf) 
 {
   char filename_inzip[MAXFILENAME];
-  EXTRACTOR_unzip_file_info file_info;
+  struct EXTRACTOR_UnzipFileInfo file_info;
   char *buf;
   size_t buf_size;
 
   if (EXTRACTOR_UNZIP_OK !=
-      EXTRACTOR_common_unzip_local_file (uf,
-                                        "mimetype",
-                                        CASESENSITIVITY))
+      EXTRACTOR_common_unzip_go_find_local_file (uf,
+                                                "mimetype",
+                                                2))
     return NULL;
   if (EXTRACTOR_UNZIP_OK != 
       EXTRACTOR_common_unzip_get_current_file_info (uf,
@@ -113,11 +108,8 @@
                                                    0))
     return NULL;
   if (EXTRACTOR_UNZIP_OK != 
-      EXTRACTOR_common_unzip_open_current_file3 (uf, NULL, NULL, 0))
-    {
-      EXTRACTOR_common_unzip_close_current_file (uf);  
-      return NULL;
-    }
+      EXTRACTOR_common_unzip_open_current_file (uf))
+    return NULL;
   buf_size = file_info.uncompressed_size;    
   if (buf_size > 1024) 
     {
@@ -164,40 +156,25 @@
 EXTRACTOR_odf_extract_method (struct EXTRACTOR_ExtractContext *ec)
 {
   char filename_inzip[MAXFILENAME];
-  EXTRACTOR_unzip_file uf;
-  EXTRACTOR_unzip_file_info file_info;
+  struct EXTRACTOR_UnzipFile *uf;
+  struct EXTRACTOR_UnzipFileInfo file_info;
   char *buf;
   char *pbuf;
   size_t buf_size;
   unsigned int i;
-  EXTRACTOR_unzip_filefunc_def io;
   char *mimetype;
 
-  if (size < 100)
-    return 0;
-  if ( !( ('P'==data[0]) && ('K'==data[1]) && (0x03==data[2]) && 
(0x04==data[3])) )
-    return 0;
-
-  io.zopen_file = &EXTRACTOR_common_unzip_zlib_open_file_func;
-  io.zread_file = &EXTRACTOR_common_unzip_zlib_read_file_func;
-  io.zwrite_file = NULL;
-  io.ztell_file = &EXTRACTOR_common_unzip_zlib_tell_file_func;
-  io.zseek_file = &EXTRACTOR_common_unzip_zlib_seek_file_func;
-  io.zclose_file = &EXTRACTOR_common_unzip_zlib_close_file_func;
-  io.zerror_file = &EXTRACTOR_common_unzip_zlib_testerror_file_func;
-  io.opaque = ec;
-  
-  if (NULL == (uf = EXTRACTOR_common_unzip_open2 ("ERROR", &io)))
+  if (NULL == (uf = EXTRACTOR_common_unzip_open (ec)))
     return;
   if (NULL != (mimetype = libextractor_oo_getmimetype (uf)))
     {
-      if (0 != proc (proc_cls, 
-                    "deb",
-                    EXTRACTOR_METATYPE_MIMETYPE,
-                    EXTRACTOR_METAFORMAT_UTF8,
-                    "text/plain",
-                    mimetype,
-                    strlen (mimetype) + 1))
+      if (0 != ec->proc (ec->cls, 
+                        "odf",
+                        EXTRACTOR_METATYPE_MIMETYPE,
+                        EXTRACTOR_METAFORMAT_UTF8,
+                        "text/plain",
+                        mimetype,
+                        strlen (mimetype) + 1))
        {
          EXTRACTOR_common_unzip_close (uf);
          free (mimetype);
@@ -206,9 +183,9 @@
       free (mimetype);
     }
   if (EXTRACTOR_UNZIP_OK !=
-      EXTRACTOR_common_unzip_local_file (uf,
-                                        METAFILE,
-                                        CASESENSITIVITY)) 
+      EXTRACTOR_common_unzip_go_find_local_file (uf,
+                                                METAFILE,
+                                                2)) 
     {
       /* metafile not found */
       EXTRACTOR_common_unzip_close (uf);
@@ -219,14 +196,14 @@
                                                    &file_info,
                                                    filename_inzip,
                                                    sizeof (filename_inzip),
-                                                   NULL,0,NULL,0)) 
+                                                   NULL, 0, NULL, 0)) 
     {
       /* problems accessing metafile */
       EXTRACTOR_common_unzip_close (uf);
       return;
     }
   if (EXTRACTOR_UNZIP_OK != 
-      EXTRACTOR_common_unzip_open_current_file3 (uf, NULL, NULL, 0)) 
+      EXTRACTOR_common_unzip_open_current_file (uf)) 
     {
       /* problems with unzip */
       EXTRACTOR_common_unzip_close (uf);
@@ -320,16 +297,14 @@
                  
                  memcpy(key, spos, epos-spos);
                  key[epos-spos] = '\0';
-                 if (0 != proc (proc_cls, 
-                                "odf",
-                                tmap[i].type,
-                                EXTRACTOR_METAFORMAT_UTF8,
-                                "text/plain",
-                                key,
-                                epos - spos + 1))
-                   {
-                     goto CLEANUP;
-                   }     
+                 if (0 != ec->proc (ec->cls, 
+                                    "odf",
+                                    tmap[i].type,
+                                    EXTRACTOR_METAFORMAT_UTF8,
+                                    "text/plain",
+                                    key,
+                                    epos - spos + 1))
+                   goto CLEANUP;                         
                  pbuf = epos;
                } 
              else

Modified: Extractor/src/plugins/sid_extractor.c
===================================================================
--- Extractor/src/plugins/sid_extractor.c       2012-08-14 14:25:43 UTC (rev 
23229)
+++ Extractor/src/plugins/sid_extractor.c       2012-08-14 16:53:21 UTC (rev 
23230)
@@ -1,10 +1,10 @@
 /*
  * This file is part of libextractor.
- * (C) 2006, 2007 Toni Ruottu
+ * (C) 2006, 2007, 2012 Vidyut Samanta and Christian Grothoff
  *
  * libextractor is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
+ * by the Free Software Foundation; either version 3, or (at your
  * option) any later version.
  *
  * libextractor is distributed in the hope that it will be useful, but
@@ -18,15 +18,17 @@
  * Boston, MA 02111-1307, USA.
  *
  */
+/**
+ * @file plugins/sid_extractor.c
+ * @brief plugin to support Scream Tracker (S3M) files
+ * @author Toni Ruottu
+ * @author Christian Grothoff
+ */
 #include "platform.h"
 #include "extractor.h"
 
 
-#define SID1_HEADER_SIZE 0x76
-#define SID2_HEADER_SIZE 0x7c
-
-/* flags */
-
+/* SID flags */
 #define MUSPLAYER_FLAG   0x01
 #define PLAYSID_FLAG     0x02
 #define PAL_FLAG         0x04
@@ -34,51 +36,134 @@
 #define MOS6581_FLAG     0x10
 #define MOS8580_FLAG     0x20
 
+/**
+ * A "SID word".
+ */
 typedef char sidwrd[2];
+
+/**
+ * A "SID long".
+ */
 typedef char sidlongwrd[4];
 
+/**
+ * Header of a SID file.
+ */
 struct header
 {
+  /**
+   * Magic string.
+   */
   char magicid[4];
+
+  /**
+   * Version number.
+   */
   sidwrd sidversion;
+
+  /**
+   * Unknown.
+   */
   sidwrd dataoffset;
+
+  /**
+   * Unknown.
+   */
   sidwrd loadaddr;
+
+  /**
+   * Unknown.
+   */
   sidwrd initaddr;
+
+  /**
+   * Unknown.
+   */
   sidwrd playaddr;
+
+  /**
+   * Number of songs in file.
+   */
   sidwrd songs;
+
+  /**
+   * Starting song.
+   */
   sidwrd firstsong;
+
+  /**
+   * Unknown.
+   */
   sidlongwrd speed;
+
+  /**
+   * Title of the album.
+   */
   char title[32];
+
+  /**
+   * Name of the artist.
+   */
   char artist[32];
+
+  /**
+   * Copyright information.
+   */
   char copyright[32];
-  sidwrd flags;                 /* version 2 specific fields start */
+
+  /* version 2 specific fields start */
+
+  /**
+   * Flags
+   */
+  sidwrd flags;                 
+
+  /**
+   * Unknown.
+   */
   char startpage;
+
+  /**
+   * Unknown.
+   */
   char pagelength;
+
+  /**
+   * Unknown.
+   */
   sidwrd reserved;
 };
 
+
+/**
+ * Convert a 'sidword' to an integer.
+ *
+ * @param data the sidword
+ * @return corresponding integer value
+ */
 static int
 sidword (const sidwrd data)
 {
-  int value = (unsigned char) data[0] * 0x100 + (unsigned char) data[1];
-  return value;
-
+  return (unsigned char) data[0] * 0x100 + (unsigned char) data[1];
 }
 
-#define ADD(s,t) do { if (0 != proc (proc_cls, "sid", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) return 1; } while (0)
 
-/* "extract" keyword from a SID file
+/**
+ * Give metadata to LE; return if 'proc' returns non-zero.
  *
- *  This plugin is based on the nsf extractor
+ * @param s metadata value as UTF8
+ * @param t metadata type to use
+ */
+#define ADD(s,t) do { if (0 != ec->proc (ec->cls, "sid", t, 
EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return; } while (0)
+
+
+/**
+ * Extract metadata from SID files.
  *
+ * @param ec extraction context
  */
-
-int 
-EXTRACTOR_sid_extract (const char *data,
-                      size_t size,
-                      EXTRACTOR_MetaDataProcessor proc,
-                      void *proc_cls,
-                      const char *options)
+void
+EXTRACTOR_sid_extract_method (struct EXTRACTOR_ExtractContext *ec)
 {
   unsigned int flags;
   int version;
@@ -89,17 +174,19 @@
   char startingsong[32];
   char sidversion[32];
   const struct header *head;
+  void *data;
 
-  /* Check header size */
+  if (sizeof (struct header) >
+      ec->read (ec->cls,
+               &data,
+               sizeof (struct header)))
+    return;
+  head = data;
 
-  if (size < SID1_HEADER_SIZE)
-    return 0;
-  head = (const struct header *) data;
-
   /* Check "magic" id bytes */
-  if (memcmp (head->magicid, "PSID", 4) &&
-      memcmp (head->magicid, "RSID", 4))
-    return 0;
+  if ( (0 != memcmp (head->magicid, "PSID", 4)) &&
+       (0 != memcmp (head->magicid, "RSID", 4)) )
+    return;
 
   /* Mime-type */
   ADD ("audio/prs.sid", EXTRACTOR_METATYPE_MIMETYPE);
@@ -107,25 +194,24 @@
   /* Version of SID format */
   version = sidword (head->sidversion);
   snprintf (sidversion, 
-           sizeof(sidversion),
+           sizeof (sidversion),
            "%d",
            version);
   ADD (sidversion, EXTRACTOR_METATYPE_FORMAT_VERSION);
 
   /* Get song count */
   snprintf (songs,
-           sizeof(songs),
+           sizeof (songs),
            "%d", sidword (head->songs));
   ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT);
 
   /* Get number of the first song to be played */
   snprintf (startingsong,
-           sizeof(startingsong),
+           sizeof (startingsong),
            "%d", 
            sidword (head->firstsong));
   ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG);
 
-
   /* name, artist, copyright fields */
   memcpy (&album, head->title, 32);
   album[32] = '\0';
@@ -139,10 +225,9 @@
   copyright[32] = '\0';
   ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT);
 
+  if (version < 2)
+    return;
 
-  if ( (version < 2) || (size < SID2_HEADER_SIZE))
-    return 0;
-
   /* Version 2 specific options follow
    *
    * Note: Had some troubles understanding specification
@@ -150,42 +235,25 @@
    */
   flags = sidword (head->flags);
   /* MUS data */
-  if (flags & MUSPLAYER_FLAG)    
+  if (0 != (flags & MUSPLAYER_FLAG))
     ADD ("Compute!'s Sidplayer", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE);    
 
   /* PlaySID data */
-  if (flags & PLAYSID_FLAG)    
+  if (0 != (flags & PLAYSID_FLAG))
     ADD ("PlaySID", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE);    
 
 
   /* PAL or NTSC */
+  if (0 != (flags & NTSC_FLAG))
+    ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);        
+  else if (0 != (flags & PAL_FLAG))
+    ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);        
 
-  if (flags & PAL_FLAG)
-    {
-      if (flags & NTSC_FLAG)
-       ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);       
 
-      else        
-       ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);        
-    }
-  else
-    {
-      if (flags & NTSC_FLAG)
-       ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);        
-    }
-
   /* Detect SID Chips suitable for play the files */
-  if (flags & MOS6581_FLAG)
-    {
-      if (flags & MOS8580_FLAG)
-       ADD ("MOS6581/MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);        
-      else
-       ADD ("MOS6581", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);        
-    }
-  else
-    {
-      if (flags & MOS8580_FLAG)
-       ADD ("MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);        
-    }
+  if (0 != (flags & MOS8580_FLAG))
+    ADD ("MOS6581/MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);        
+  else if (0 != (flags & MOS6581_FLAG))
+    ADD ("MOS6581", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);        
+}
 
-  return 0;
-}
+/* end of sid_extractor.c */

Added: Extractor/src/plugins/test_deb.c
===================================================================
--- Extractor/src/plugins/test_deb.c                            (rev 0)
+++ Extractor/src/plugins/test_deb.c    2012-08-14 16:53:21 UTC (rev 23230)
@@ -0,0 +1,150 @@
+/*
+     This file is part of libextractor.
+     (C) 2012 Vidyut Samanta and Christian Grothoff
+
+     libextractor 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 3, or (at your
+     option) any later version.
+
+     libextractor 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 libextractor; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file plugins/test_deb.c
+ * @brief testcase for deb plugin
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "test_lib.h"
+
+
+/**
+ * Main function for the DEB testcase.
+ *
+ * @param argc number of arguments (ignored)
+ * @param argv arguments (ignored)
+ * @return 0 on success
+ */
+int
+main (int argc, char *argv[])
+{
+  struct SolutionData deb_bzip2_sol[] =
+    {
+      { 
+       EXTRACTOR_METATYPE_MIMETYPE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "application/x-debian-package",
+       strlen ("application/x-debian-package") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PACKAGE_NAME,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "bzip2",
+       strlen ("bzip2") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PACKAGE_VERSION,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "1.0.6-4",
+       strlen ("1.0.6-4") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_TARGET_ARCHITECTURE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "i386",
+       strlen ("i386") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PACKAGE_MAINTAINER,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "Anibal Monsalve Salazar <address@hidden>",
+       strlen ("Anibal Monsalve Salazar <address@hidden>") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PACKAGE_INSTALLED_SIZE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "113", /* FIXME: should this be 'kb'? */
+       strlen ("113") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PACKAGE_DEPENDENCY,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "libbz2-1.0 (= 1.0.6-4), libc6 (>= 2.4)",
+       strlen ("libbz2-1.0 (= 1.0.6-4), libc6 (>= 2.4)") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PACKAGE_SUGGESTS,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "bzip2-doc",
+       strlen ("bzip2-doc") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PACKAGE_REPLACES,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "libbz2 (<< 0.9.5d-3)",
+       strlen ("libbz2 (<< 0.9.5d-3)") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_SECTION,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "utils",
+       strlen ("utils") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_UPLOAD_PRIORITY,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "standard",
+       strlen ("standard") + 1,
+       0 
+      },
+#if 0
+      { 
+       EXTRACTOR_METATYPE_DESCRIPTION,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "",
+       strlen ("") + 1,
+       0 
+      },
+#endif
+      { 0, 0, NULL, NULL, 0, -1 }
+    };
+  struct ProblemSet ps[] =
+    {
+      { "testdata/deb_bzip2.deb",
+       deb_bzip2_sol },
+      { NULL, NULL }
+    };
+  return ET_main ("deb", ps);
+}
+
+/* end of test_deb.c */

Added: Extractor/src/plugins/test_odf.c
===================================================================
--- Extractor/src/plugins/test_odf.c                            (rev 0)
+++ Extractor/src/plugins/test_odf.c    2012-08-14 16:53:21 UTC (rev 23230)
@@ -0,0 +1,100 @@
+/*
+     This file is part of libextractor.
+     (C) 2012 Vidyut Samanta and Christian Grothoff
+
+     libextractor 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 3, or (at your
+     option) any later version.
+
+     libextractor 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 libextractor; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file plugins/test_odf.c
+ * @brief testcase for odf plugin
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "test_lib.h"
+
+
+/**
+ * Main function for the ODF testcase.
+ *
+ * @param argc number of arguments (ignored)
+ * @param argv arguments (ignored)
+ * @return 0 on success
+ */
+int
+main (int argc, char *argv[])
+{
+  struct SolutionData odf_cg_sol[] =
+    {
+      { 
+       EXTRACTOR_METATYPE_MIMETYPE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "application/vnd.oasis.opendocument.text",
+       strlen ("application/vnd.oasis.opendocument.text") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "OpenOffice.org/3.2$Unix OpenOffice.org_project/320m12$Build-9483",
+       strlen ("OpenOffice.org/3.2$Unix 
OpenOffice.org_project/320m12$Build-9483") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_PAGE_COUNT,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "1",
+       strlen ("1") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_CREATION_DATE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "2005-11-22T11:44:00",
+       strlen ("2005-11-22T11:44:00") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_UNKNOWN_DATE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "2010-06-09T13:09:34",
+       strlen ("2010-06-09T13:09:34") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_TITLE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "Anhang 1: Profile der beteiligten Wissenschaftler",
+       strlen ("Anhang 1: Profile der beteiligten Wissenschaftler") + 1,
+       0  
+      },
+      { 0, 0, NULL, NULL, 0, -1 }
+    };
+  struct ProblemSet ps[] =
+    {
+      { "testdata/odf_cg.odt",
+       odf_cg_sol },
+      { NULL, NULL }
+    };
+  return ET_main ("odf", ps);
+}
+
+/* end of test_odf.c */

Copied: Extractor/src/plugins/test_zip.c (from rev 23208, 
Extractor/src/plugins/test_jpeg.c)
===================================================================
--- Extractor/src/plugins/test_zip.c                            (rev 0)
+++ Extractor/src/plugins/test_zip.c    2012-08-14 16:53:21 UTC (rev 23230)
@@ -0,0 +1,108 @@
+/*
+     This file is part of libextractor.
+     (C) 2012 Vidyut Samanta and Christian Grothoff
+
+     libextractor 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 3, or (at your
+     option) any later version.
+
+     libextractor 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 libextractor; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file plugins/test_zip.c
+ * @brief testcase for zip plugin
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "test_lib.h"
+
+
+/**
+ * Main function for the ZIP testcase.
+ *
+ * @param argc number of arguments (ignored)
+ * @param argv arguments (ignored)
+ * @return 0 on success
+ */
+int
+main (int argc, char *argv[])
+{
+  struct SolutionData zip_test_sol[] =
+    {
+      { 
+       EXTRACTOR_METATYPE_MIMETYPE,
+       EXTRACTOR_METAFORMAT_UTF8,
+       "text/plain",
+       "application/zip",
+       strlen ("application/zip") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_COMMENT,
+       EXTRACTOR_METAFORMAT_C_STRING,
+       "text/plain",
+       "global zipfile comment",
+       strlen ("global zipfile comment") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_FILENAME,
+       EXTRACTOR_METAFORMAT_C_STRING,
+       "text/plain",
+       "ChangeLog",
+       strlen ("ChangeLog") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_FILENAME,
+       EXTRACTOR_METAFORMAT_C_STRING,
+       "text/plain",
+       "test.png",
+       strlen ("test.png") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_COMMENT,
+       EXTRACTOR_METAFORMAT_C_STRING,
+       "text/plain",
+       "comment for test.png",
+       strlen ("comment for test.png") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_FILENAME,
+       EXTRACTOR_METAFORMAT_C_STRING,
+       "text/plain",
+       "test.jpg",
+       strlen ("test.jpg") + 1,
+       0 
+      },
+      { 
+       EXTRACTOR_METATYPE_COMMENT,
+       EXTRACTOR_METAFORMAT_C_STRING,
+       "text/plain",
+       "comment for test.jpg",
+       strlen ("comment for test.jpg") + 1,
+       0 
+      },
+      { 0, 0, NULL, NULL, 0, -1 }
+    };
+  struct ProblemSet ps[] =
+    {
+      { "testdata/zip_test.zip",
+       zip_test_sol },
+      { NULL, NULL }
+    };
+  return ET_main ("zip", ps);
+}
+
+/* end of test_zip.c */

Added: Extractor/src/plugins/testdata/deb_bzip2.deb
===================================================================
(Binary files differ)


Property changes on: Extractor/src/plugins/testdata/deb_bzip2.deb
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: Extractor/src/plugins/testdata/odf_cg.odt
===================================================================
(Binary files differ)


Property changes on: Extractor/src/plugins/testdata/odf_cg.odt
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Copied: Extractor/src/plugins/testdata/zip_test.zip (from rev 23208, 
Extractor/test/test.zip)
===================================================================
(Binary files differ)

Modified: Extractor/src/plugins/zip_extractor.c
===================================================================
--- Extractor/src/plugins/zip_extractor.c       2012-08-14 14:25:43 UTC (rev 
23229)
+++ Extractor/src/plugins/zip_extractor.c       2012-08-14 16:53:21 UTC (rev 
23230)
@@ -1,50 +1,10 @@
-/** 
-     zipextractor.c  version 0.0.2
-
-     Changes from 0.0.1 to 0.0.2 
-     -> Searches for central dir struct from end of file if this is a 
self-extracting executable
-
-
-     This file was based on mp3extractor.c  (0.1.2)
-
-     Currently, this only returns a list of the filenames within a zipfile
-     and any comments on each file or the whole file itself. File sizes, 
-     modification times, and crc's are currently ignored.
-
-     TODO: Break the comments up into small, atomically, searchable chunks 
(keywords)
-         - might need some knowledge of English?
-
-     It returns:
-
-     one      EXTRACTOR_MIMETYPE
-     multiple EXTRACTOR_FILENAME
-     multiple EXTRACTOR_COMMENT
-     
-     ... from a .ZIP file
-
-     TODO: EXTRACTOR_DATE, EXTRACTOR_DESCRIPTION, EXTRACTOR_KEYWORDS, others?
-
-     Does NOT test data integrity (CRCs etc.)
-
-     This version is not recursive (i.e. doesn't look inside zip 
-     files within zip files)
-     
-     TODO: Run extract on files inside of archive (?) (i.e. gif, mp3, etc.)
-     
-     The current .ZIP format description:
-     ftp://ftp.pkware.com/appnote.zip
-
-     No Copyright 2003 Julia Wolf
-
- */  
-  
 /*
  * This file is part of libextractor.
- * (C) 2002, 2003, 2009 Vidyut Samanta and Christian Grothoff
+ * (C) 2012 Vidyut Samanta and Christian Grothoff
  *
  * libextractor is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
+ * by the Free Software Foundation; either version 3, or (at your
  * option) any later version.
  * 
  * libextractor is distributed in the hope that it will be useful, but
@@ -57,354 +17,113 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */ 
-  
+/**
+ * @file plugins/zip_extractor.c
+ * @brief plugin to support ZIP files
+ * @author Christian Grothoff
+ */
 #include "platform.h"
+#include <ctype.h>
 #include "extractor.h"
+#include "unzip.h"
+
   
-#define DEBUG_EXTRACT_ZIP 0
-  
-/* In a zipfile there are two kinds of comments. One is a big one for the
-   entire .zip, it's usually a BBS ad. The other is a small comment on each
-   individual file; most people don't use this.
- */ 
-  
-/* TODO: zip_entry linked list is handeled kinda messily, should clean up 
(maybe) */ 
-  typedef struct
+/**
+ * Main entry method for the 'application/zip' extraction plugin.  
+ *
+ * @param ec extraction context provided to the plugin
+ */
+void
+EXTRACTOR_zip_extract_method (struct EXTRACTOR_ExtractContext *ec)
 {
-  char *filename;
-   char *comment;
-   void *next;
- } zip_entry;
+  struct EXTRACTOR_UnzipFile *uf;
+  struct EXTRACTOR_UnzipFileInfo fi;
+  char fname[256];
+  char fcomment[256];
 
-/* mimetype = application/zip */ 
-int 
-EXTRACTOR_zip_extract (const unsigned char *data,
-                      size_t size,
-                      EXTRACTOR_MetaDataProcessor proc,
-                      void *proc_cls,
-                      const char *options)
-{
-  int ret;
-  void *tmp;
-  zip_entry * info;
-  zip_entry * start;
-  char *filecomment;
-  const unsigned char *pos;
-  unsigned int offset, stop;
-  unsigned int name_length;
-  unsigned int extra_length;
-  unsigned int comment_length;
-  unsigned int filecomment_length;
-  unsigned int entry_count;
-#if DEBUG_EXTRACT_ZIP 
-  unsigned int entry_total;
-#endif
-
-  /* I think the smallest zipfile you can have is about 120 bytes */ 
-  if ((NULL == data) || (size < 100))
-    return 0;
-  if (! (('P' == data[0]) && ('K' == data[1]) && (0x03 == data[2])
-         && (0x04 == data[3])))
-    return 0;
-  
-    /* The filenames for each file in a zipfile are stored in two locations.
-     * There is one at the start of each entry, just before the compressed 
data,
-     * and another at the end in a 'central directory structure'.
-     *
-     * In order to catch self-extracting executables, we scan backwards from 
the end
-     * of the file looking for the central directory structure. The previous 
version
-     * of this went forewards through the local headers, but that only works 
for plain
-     * vanilla zip's and I don't feel like writing a special case for each of 
the dozen
-     * self-extracting executable stubs.
-     *
-     * This assumes that the zip file is considered to be 
non-corrupt/non-truncated.
-     * If it is truncated then it's not considered to be a zip and skipped.
-     *
-     */ 
-    
-    /* From appnote.iz and appnote.txt (more or less)
-     *
-     *   (this is why you always need to put in the last floppy if you span 
disks)
-     *
-     *   0- 3  end of central dir signature    4 bytes  (0x06054b50) P K ^E ^F
-     *   4- 5  number of this disk             2 bytes
-     *   6- 7  number of the disk with the
-     *         start of the central directory  2 bytes
-     *   8- 9  total number of entries in
-     *         the central dir on this disk    2 bytes
-     *  10-11  total number of entries in
-     *         the central dir                 2 bytes
-     *  12-15  size of the central directory   4 bytes
-     *  16-19  offset of start of central
-     *         directory with respect to
-     *         the starting disk number        4 bytes
-     *  20-21  zipfile comment length          2 bytes
-     *  22-??  zipfile comment (variable size) max length 65536 bytes
-     */ 
-    
-    /*  the signature can't be more than 22 bytes from the end */ 
-  offset = size - 22;
-  pos = &data[offset];
-  stop = 0;
-  if (((signed int) size - 65556) > 0)
-    stop = size - 65556;
-  
-    /* not using int 0x06054b50 so that we don't have to deal with endianess 
issues.
-       break out if we go more than 64K backwards and havn't found it, or if 
we hit the
-       begining of the file. */ 
-    while ((!(('P' == pos[0]) && ('K' == pos[1]) && (0x05 == pos[2])
-              && (0x06 == pos[3]))) && (offset > stop))
-    pos = &data[offset--];
-  if (offset == stop)
+  if (NULL == (uf = EXTRACTOR_common_unzip_open (ec)))
+    return;
+  if ( (EXTRACTOR_UNZIP_OK ==
+       EXTRACTOR_common_unzip_go_find_local_file (uf,
+                                                  "meta.xml",
+                                                  2)) ||
+       (EXTRACTOR_UNZIP_OK ==
+       EXTRACTOR_common_unzip_go_find_local_file (uf,
+                                                  "META-INF/MANIFEST.MF",
+                                                  2)) )
     {
-#if DEBUG_EXTRACT_ZIP
-      fprintf (stderr,
-                 "Did not find end of central directory structure signature. 
offset: %i\n",
-                 offset);
-      
-#endif
-      return 0;
+      /* not a normal zip, might be odf, jar, etc. */
+      goto CLEANUP;
     }
-  
-    /* offset should now point to the start of the end-of-central directory 
structure */ 
-    /* and pos[0] should be pointing there too */ 
-    /* so slurp down filecomment while here... */ 
-    filecomment_length = pos[20] + (pos[21] << 8);
-  if (filecomment_length + offset + 22 > size)
+  if (EXTRACTOR_UNZIP_OK !=
+      EXTRACTOR_common_unzip_go_to_first_file (uf))
+    { 
+      /* zip malformed? */
+      goto CLEANUP;
+   }
+  if (0 !=
+      ec->proc (ec->cls, 
+               "zip",
+               EXTRACTOR_METATYPE_MIMETYPE,
+               EXTRACTOR_METAFORMAT_UTF8,
+               "text/plain",
+               "application/zip",
+               strlen ("application/zip") + 1))
+    goto CLEANUP;
+  if (EXTRACTOR_UNZIP_OK ==
+      EXTRACTOR_common_unzip_get_global_comment (uf,
+                                                fcomment,
+                                                sizeof (fcomment)))
     {
-      return 0;             /* invalid zip file format! */
+      if ( (0 != strlen (fcomment)) &&
+          (0 !=
+           ec->proc (ec->cls, 
+                     "zip",
+                     EXTRACTOR_METATYPE_COMMENT,
+                     EXTRACTOR_METAFORMAT_C_STRING,
+                     "text/plain",
+                     fcomment,
+                     strlen (fcomment) + 1)))
+       goto CLEANUP;
     }
-  filecomment = NULL;
-  if (filecomment_length > 0)
-    {
-      filecomment = malloc (filecomment_length + 1);
-      if (filecomment != NULL)
-       {
-         memcpy (filecomment, &pos[22], filecomment_length);
-         filecomment[filecomment_length] = '\0';
-       }
-    }
-
-#if DEBUG_EXTRACT_ZIP
-  if ((0 != pos[4]) && (0 != pos[5]))
-    fprintf (stderr,
-            "WARNING: This seems to be the last disk in a multi-volume"
-            " ZIP archive, and so this might not work.\n");          
-#endif
-      
-#if DEBUG_EXTRACT_ZIP
-  if ((pos[8] != pos[10]) && (pos[9] != pos[11]))
-    fprintf (stderr,
-            "WARNING: May not be able to find all the files in this" 
-            " ZIP archive (no multi-volume support right now).\n");  
- entry_total = pos[10] + (pos[11] << 8);
-#endif
-  entry_count = 0;
-  
-    /* jump to start of central directory, ASSUMING that the starting disk 
that it's on is disk 0 */ 
-    /* starting disk would otherwise be pos[6]+pos[7]<<8 */ 
-    offset = pos[16] + (pos[17] << 8) + (pos[18] << 16) + (pos[19] << 24);     
/* offset of cent-dir from start of disk 0 */
-  
-    /* stop   = pos[12] + (pos[13]<<8) + (pos[14]<<16) + (pos[15]<<24); *//* 
length of central dir */ 
-    if (offset + 46 > size)
-    {
-      
-        /* not a zip */ 
-      if (filecomment != NULL)
-        free (filecomment);
-      return 0;
-    }
-  pos = &data[offset];         /* jump */
-  
-    /* we should now be at the begining of the central directory structure */ 
-    
-    /* from appnote.txt and appnote.iz (mostly)
-     *
-     *   0- 3  central file header signature   4 bytes  (0x02014b50)
-     *   4- 5  version made by                 2 bytes
-     *   6- 7  version needed to extract       2 bytes
-     *   8- 9  general purpose bit flag        2 bytes
-     *  10-11  compression method              2 bytes
-     *  12-13  last mod file time              2 bytes
-     *  14-15  last mod file date              2 bytes
-     *  16-19  crc-32                          4 bytes
-     *  20-23  compressed size                 4 bytes
-     *  24-27  uncompressed size               4 bytes
-     *  28-29  filename length                 2 bytes
-     *  30-31  extra field length              2 bytes
-     *  32-33  file comment length             2 bytes
-     *  34-35  disk number start               2 bytes
-     *  36-37  internal file attributes        2 bytes
-     *  38-41  external file attributes        4 bytes
-     *  42-45  relative offset of local header 4 bytes
-     *
-     *  46-??  filename (variable size)
-     *   ?- ?  extra field (variable size)
-     *   ?- ?  file comment (variable size)
-     */ 
-    if (!(('P' == pos[0]) && ('K' == pos[1]) && (0x01 == pos[2])
-          && (0x02 == pos[3])))
-      {      
-#if DEBUG_EXTRACT_ZIP
-        fprintf (stderr,
-                 "Did not find central directory structure signature. offset: 
%i\n",
-                 offset);
-       
-#endif
-        if (filecomment != NULL)
-         free (filecomment);
-       return 0;
-      }
-  start = NULL;
-  info = NULL;
-  
   do
-    {                           /* while ( (0x01==pos[2])&&(0x02==pos[3]) ) */
-      entry_count++;           /* check to make sure we found everything at 
the end */
-      name_length = pos[28] + (pos[29] << 8);
-      extra_length = pos[30] + (pos[31] << 8);
-      comment_length = pos[32] + (pos[33] << 8);
-      if (name_length + extra_length + comment_length + offset + 46 > size)
-        {
-          
-            /* ok, invalid, abort! */ 
-            break;
-        }
-      
-#if DEBUG_EXTRACT_ZIP
-        fprintf (stderr, "Found filename length %i  Comment length: %i\n",
-                 name_length, comment_length);
-      
-#endif        
-        /* yay, finally get filenames */ 
-        if (start == NULL)
-        {
-          start = malloc (sizeof (zip_entry));
-         if (start == NULL)
-           break;
-          start->next = NULL;
-          info = start;
-        }
-      else
-        {
-          info->next = malloc (sizeof (zip_entry));
-         if (info->next == NULL)
-           break;
-          info = info->next;
-          info->next = NULL;
-        }
-      info->filename = malloc (name_length + 1);
-      info->comment = malloc (comment_length + 1);
-      
-        /* (strings in zip files are not null terminated) */ 
-      if (info->filename != NULL)
-       {
-         memcpy (info->filename, &pos[46], name_length);
-         info->filename[name_length] = '\0';
-       }
-      if (info->comment != NULL)
-       {
-         memcpy (info->comment, &pos[46 + name_length + extra_length],
-                 comment_length);
-         info->comment[comment_length] = '\0';
-       }
-      offset += 46 + name_length + extra_length + comment_length;
-      pos = &data[offset];      
-      /* check for next header entry (0x02014b50) or (0x06054b50) if at end */ 
-      if (('P' != pos[0]) && ('K' != pos[1]))
-        {         
-#if DEBUG_EXTRACT_ZIP
-         fprintf (stderr,
-                  "Did not find next header in central directory.\n");
-          
-#endif
-         info = start;
-          while (info != NULL)
-            {
-              start = info->next;
-             if (info->filename != NULL)
-               free (info->filename);
-             if (info->comment != NULL)
-               free (info->comment);
-              free (info);
-              info = start;
-            }
-          if (filecomment != NULL)
-            free (filecomment);
-          return 0;
-        }
-    }
-  while ((0x01 == pos[2]) && (0x02 == pos[3]));
-  
-    /* end list */ 
-    
-    /* TODO: should this return an error? indicates corrupt zipfile (or
-       disk missing in middle of multi-disk)? */ 
-#if DEBUG_EXTRACT_ZIP
-  if (entry_count != entry_total)
-    fprintf (stderr,
-            "WARNING: Did not find all of the zipfile entries that we should 
have.\n");    
-#endif
-  
-  ret = proc (proc_cls,
-             "zip",
-             EXTRACTOR_METATYPE_MIMETYPE,
-             EXTRACTOR_METAFORMAT_UTF8,
-             "text/plain",
-             "application/zip",
-             strlen ("application/zip")+1);
-  if ( (filecomment != NULL) && (ret != 0) )
     {
-      ret = proc (proc_cls,
-                 "zip",
-                 EXTRACTOR_METATYPE_MIMETYPE,
-                 EXTRACTOR_METAFORMAT_UTF8,
-                 "text/plain",
-                 filecomment,
-                 strlen (filecomment)+1);
-    }
-  if (filecomment != NULL)
-    free (filecomment);
-
-  
-  /* if we've gotten to here then there is at least one zip entry (see 
get_zipinfo call above) */ 
-  /* note: this free()'s the info list as it goes */ 
-  info = start;
-  while (NULL != info)
-    {
-      if (info->filename != NULL)
-        {
-          if ( (ret == 0) && (strlen (info->filename)) )
-            {
-             ret = proc (proc_cls,
+      if (EXTRACTOR_UNZIP_OK ==
+         EXTRACTOR_common_unzip_get_current_file_info (uf,
+                                                       &fi,
+                                                       fname,
+                                                       sizeof (fname),
+                                                       NULL, 0,
+                                                       fcomment,
+                                                       sizeof (fcomment)))
+       {
+         if ( (0 != strlen (fname)) &&
+              (0 !=
+               ec->proc (ec->cls, 
                          "zip",
                          EXTRACTOR_METATYPE_FILENAME,
-                         EXTRACTOR_METAFORMAT_UTF8,
+                         EXTRACTOR_METAFORMAT_C_STRING,
                          "text/plain",
-                         info->filename,
-                         strlen (info->filename)+1);
-            }
-          free (info->filename);
-        }
-      if (info->comment != NULL)
-       {
-         if ( (ret == 0) && (strlen (info->comment) > 0) )
-           {
-             ret = proc (proc_cls,
+                         fname,
+                         strlen (fname) + 1)))
+           goto CLEANUP;
+         if ( (0 != strlen (fcomment)) &&
+              (0 !=
+               ec->proc (ec->cls, 
                          "zip",
-                         EXTRACTOR_METATYPE_FILENAME,
-                         EXTRACTOR_METAFORMAT_UTF8,
+                         EXTRACTOR_METATYPE_COMMENT,
+                         EXTRACTOR_METAFORMAT_C_STRING,
                          "text/plain",
-                         info->comment,
-                         strlen (info->comment)+1);
-           }
-         free (info->comment);
-       }
-      tmp = info;
-      info = info->next;
-      free (tmp);
+                         fcomment,
+                         strlen (fcomment) + 1)))
+           goto CLEANUP;
+       }                                                   
     }
-  return ret;
+  while (EXTRACTOR_UNZIP_OK ==
+        EXTRACTOR_common_unzip_go_to_next_file (uf));
+  
+CLEANUP:
+  (void) EXTRACTOR_common_unzip_close (uf);
 }
 
-
+/* end of zip_extractor.c */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]