zip.cpp

Go to the documentation of this file.
00001 /* zip.c -- IO on .zip files using zlib
00002    Version 1.01, May 8th, 2004
00003 
00004    Copyright (C) 1998-2004 Gilles Vollant
00005    Small modifications (C) 2005 The Pentagram Team
00006    Converted to more modern C/C++ by the Pentagram team.
00007 
00008    Read zip.h for more info
00009 */
00010 
00011 #include "pent_include.h"
00012 #define NOCRYPT
00013 #define NO_ADDFILEINEXISTINGZIP
00014 
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <time.h>
00019 #include "zlib.h"
00020 #include "zip.h"
00021 
00022 #ifdef STDC
00023 #  include <stddef.h>
00024 #  include <string.h>
00025 #  include <stdlib.h>
00026 #endif
00027 #ifdef NO_ERRNO_H
00028     extern int errno;
00029 #else
00030 #   include <errno.h>
00031 #endif
00032 
00033 
00034 #ifndef local
00035 #  define local static
00036 #endif
00037 /* compile with -Dlocal if your debugger can't find static symbols */
00038 
00039 #ifndef VERSIONMADEBY
00040 # define VERSIONMADEBY   (0x0) /* platform depedent */
00041 #endif
00042 
00043 #ifndef Z_BUFSIZE
00044 #define Z_BUFSIZE (16384)
00045 #endif
00046 
00047 #ifndef Z_MAXFILENAMEINZIP
00048 #define Z_MAXFILENAMEINZIP (256)
00049 #endif
00050 
00051 #ifndef ALLOC
00052 # define ALLOC(size) (malloc(size))
00053 #endif
00054 #ifndef TRYFREE
00055 # define TRYFREE(p) {if (p) free(p);}
00056 #endif
00057 
00058 /*
00059 #define SIZECENTRALDIRITEM (0x2e)
00060 #define SIZEZIPLOCALHEADER (0x1e)
00061 */
00062 
00063 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
00064 
00065 #ifndef SEEK_CUR
00066 #define SEEK_CUR    1
00067 #endif
00068 
00069 #ifndef SEEK_END
00070 #define SEEK_END    2
00071 #endif
00072 
00073 #ifndef SEEK_SET
00074 #define SEEK_SET    0
00075 #endif
00076 
00077 #ifndef DEF_MEM_LEVEL
00078 #if MAX_MEM_LEVEL >= 8
00079 #  define DEF_MEM_LEVEL 8
00080 #else
00081 #  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
00082 #endif
00083 #endif
00084 
00085 namespace PentZip {
00086 
00087 const char zip_copyright[] =
00088    " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
00089 
00090 
00091 #define SIZEDATA_INDATABLOCK (4096-(4*4))
00092 
00093 #define LOCALHEADERMAGIC    (0x04034b50)
00094 #define CENTRALHEADERMAGIC  (0x02014b50)
00095 #define ENDHEADERMAGIC      (0x06054b50)
00096 
00097 #define FLAG_LOCALHEADER_OFFSET (0x06)
00098 #define CRC_LOCALHEADER_OFFSET  (0x0e)
00099 
00100 #define SIZECENTRALHEADER (0x2e) /* 46 */
00101 
00102 typedef struct linkedlist_datablock_internal_s
00103 {
00104   struct linkedlist_datablock_internal_s* next_datablock;
00105   uLong  avail_in_this_block;
00106   uLong  filled_in_this_block;
00107   uLong  unused; /* for future use and alignement */
00108   unsigned char data[SIZEDATA_INDATABLOCK];
00109 } linkedlist_datablock_internal;
00110 
00111 typedef struct linkedlist_data_s
00112 {
00113     linkedlist_datablock_internal* first_block;
00114     linkedlist_datablock_internal* last_block;
00115 } linkedlist_data;
00116 
00117 
00118 typedef struct
00119 {
00120     z_stream stream;            /* zLib stream structure for inflate */
00121     int  stream_initialised;    /* 1 is stream is initialised */
00122     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
00123 
00124     uLong pos_local_header;     /* offset of the local header of the file
00125                                      currenty writing */
00126     char* central_header;       /* central header data for the current file */
00127     uLong size_centralheader;   /* size of the central header for cur file */
00128     uLong flag;                 /* flag of the file currently writing */
00129 
00130     int  method;                /* compression method of file currenty wr.*/
00131     int  raw;                   /* 1 for directly writing raw data */
00132     Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
00133     uLong dosDate;
00134     uLong crc32;
00135     int  encrypt;
00136 #ifndef NOCRYPT
00137     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
00138     const unsigned long* pcrc_32_tab;
00139     int crypt_header_size;
00140 #endif
00141 } curfile_info;
00142 
00143 typedef struct
00144 {
00145     zlib_filefunc_def z_filefunc;
00146     voidpf filestream;        /* io structore of the zipfile */
00147     linkedlist_data central_dir;/* datablock with central dir in construction*/
00148     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
00149     curfile_info ci;            /* info on the file curretly writing */
00150 
00151     uLong begin_pos;            /* position of the beginning of the zipfile */
00152     uLong add_position_when_writting_offset;
00153     uLong number_entry;
00154 } zip_internal;
00155 
00156 
00157 
00158 #ifndef NOCRYPT
00159 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
00160 #include "crypt.h"
00161 #endif
00162 
00163 local linkedlist_datablock_internal* allocate_new_datablock()
00164 {
00165     linkedlist_datablock_internal* ldi;
00166     ldi = (linkedlist_datablock_internal*)
00167                  ALLOC(sizeof(linkedlist_datablock_internal));
00168     if (ldi!=NULL)
00169     {
00170         ldi->next_datablock = NULL ;
00171         ldi->filled_in_this_block = 0 ;
00172         ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
00173     }
00174     return ldi;
00175 }
00176 
00177 local void free_datablock(linkedlist_datablock_internal* ldi)
00178 {
00179     while (ldi!=NULL)
00180     {
00181         linkedlist_datablock_internal* ldinext = ldi->next_datablock;
00182         TRYFREE(ldi);
00183         ldi = ldinext;
00184     }
00185 }
00186 
00187 local void init_linkedlist(linkedlist_data* ll)
00188 {
00189     ll->first_block = ll->last_block = NULL;
00190 }
00191 
00192 local void free_linkedlist(linkedlist_data* ll)
00193 {
00194     free_datablock(ll->first_block);
00195     ll->first_block = ll->last_block = NULL;
00196 }
00197 
00198 
00199 local int add_data_in_datablock(linkedlist_data* ll, const void* buf,
00200                                                                 uLong len)
00201 {
00202     linkedlist_datablock_internal* ldi;
00203     const unsigned char* from_copy;
00204 
00205     if (ll==NULL)
00206         return ZIP_INTERNALERROR;
00207 
00208     if (ll->last_block == NULL)
00209     {
00210         ll->first_block = ll->last_block = allocate_new_datablock();
00211         if (ll->first_block == NULL)
00212             return ZIP_INTERNALERROR;
00213     }
00214 
00215     ldi = ll->last_block;
00216     from_copy = (unsigned char*)buf;
00217 
00218     while (len>0)
00219     {
00220         uInt copy_this;
00221         uInt i;
00222         unsigned char* to_copy;
00223 
00224         if (ldi->avail_in_this_block==0)
00225         {
00226             ldi->next_datablock = allocate_new_datablock();
00227             if (ldi->next_datablock == NULL)
00228                 return ZIP_INTERNALERROR;
00229             ldi = ldi->next_datablock ;
00230             ll->last_block = ldi;
00231         }
00232 
00233         if (ldi->avail_in_this_block < len)
00234             copy_this = (uInt)ldi->avail_in_this_block;
00235         else
00236             copy_this = (uInt)len;
00237 
00238         to_copy = &(ldi->data[ldi->filled_in_this_block]);
00239 
00240         for (i=0;i<copy_this;i++)
00241             *(to_copy+i)=*(from_copy+i);
00242 
00243         ldi->filled_in_this_block += copy_this;
00244         ldi->avail_in_this_block -= copy_this;
00245         from_copy += copy_this ;
00246         len -= copy_this;
00247     }
00248     return ZIP_OK;
00249 }
00250 
00251 
00252 
00253 /****************************************************************************/
00254 
00255 /* ===========================================================================
00256    Inputs a long in LSB order to the given file
00257    nbByte == 1, 2 or 4 (byte, short or long)
00258 */
00259 
00260 local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
00261                                 voidpf filestream, uLong x, int nbByte));
00262 local int ziplocal_putValue (const zlib_filefunc_def* pzlib_filefunc_def,
00263                                                          voidpf filestream, uLong x, int nbByte)
00264 {
00265     unsigned char buf[4];
00266     int n;
00267     for (n = 0; n < nbByte; n++)
00268     {
00269         buf[n] = (unsigned char)(x & 0xff);
00270         x >>= 8;
00271     }
00272     if (x != 0)
00273       {     /* data overflow - hack for ZIP64 (X Roche) */
00274       for (n = 0; n < nbByte; n++)
00275         {
00276           buf[n] = 0xff;
00277         }
00278       }
00279 
00280     if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
00281         return ZIP_ERRNO;
00282     else
00283         return ZIP_OK;
00284 }
00285 
00286 local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
00287 local void ziplocal_putValue_inmemory (void* dest, uLong x, int nbByte)
00288 {
00289     unsigned char* buf=(unsigned char*)dest;
00290     int n;
00291     for (n = 0; n < nbByte; n++) {
00292         buf[n] = (unsigned char)(x & 0xff);
00293         x >>= 8;
00294     }
00295 
00296     if (x != 0)
00297     {     /* data overflow - hack for ZIP64 */
00298        for (n = 0; n < nbByte; n++)
00299        {
00300           buf[n] = 0xff;
00301        }
00302     }
00303 }
00304 
00305 /****************************************************************************/
00306 
00307 
00308 local uLong ziplocal_TmzDateToDosDate(const tm_zip* ptm, uLong dosDate)
00309 {
00310     uLong year = (uLong)ptm->tm_year;
00311     if (year>1980)
00312         year-=1980;
00313     else if (year>80)
00314         year-=80;
00315     return
00316       (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
00317         ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
00318 }
00319 
00320 
00321 /****************************************************************************/
00322 #ifndef NO_ADDFILEINEXISTINGZIP
00323 
00324 local int ziplocal_getByte OF((
00325     const zlib_filefunc_def* pzlib_filefunc_def,
00326     voidpf filestream,
00327     int *pi));
00328 
00329 local int ziplocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def,
00330                                                    voidpf filestream, int *pi)
00331 {
00332     unsigned char c;
00333     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
00334     if (err==1)
00335     {
00336         *pi = (int)c;
00337         return ZIP_OK;
00338     }
00339     else
00340     {
00341         if (ZERROR(*pzlib_filefunc_def,filestream))
00342             return ZIP_ERRNO;
00343         else
00344             return ZIP_EOF;
00345     }
00346 }
00347 
00348 
00349 /* ===========================================================================
00350    Reads a long in LSB order from the given gz_stream. Sets
00351 */
00352 local int ziplocal_getShort OF((
00353     const zlib_filefunc_def* pzlib_filefunc_def,
00354     voidpf filestream,
00355     uLong *pX));
00356 
00357 local int ziplocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
00358                                                          voidpf filestream, uLong *pX)
00359 {
00360     uLong x ;
00361     int i;
00362     int err;
00363 
00364     err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
00365     x = (uLong)i;
00366 
00367     if (err==ZIP_OK)
00368         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
00369     x += ((uLong)i)<<8;
00370 
00371     if (err==ZIP_OK)
00372         *pX = x;
00373     else
00374         *pX = 0;
00375     return err;
00376 }
00377 
00378 local int ziplocal_getLong OF((
00379     const zlib_filefunc_def* pzlib_filefunc_def,
00380     voidpf filestream,
00381     uLong *pX));
00382 
00383 local int ziplocal_getLong (const zlib_filefunc_def* pzlib_filefunc_def,
00384                                                         voidpf filestream, uLong *pX)
00385 {
00386     uLong x ;
00387     int i;
00388     int err;
00389 
00390     err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
00391     x = (uLong)i;
00392 
00393     if (err==ZIP_OK)
00394         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
00395     x += ((uLong)i)<<8;
00396 
00397     if (err==ZIP_OK)
00398         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
00399     x += ((uLong)i)<<16;
00400 
00401     if (err==ZIP_OK)
00402         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
00403     x += ((uLong)i)<<24;
00404 
00405     if (err==ZIP_OK)
00406         *pX = x;
00407     else
00408         *pX = 0;
00409     return err;
00410 }
00411 
00412 #ifndef BUFREADCOMMENT
00413 #define BUFREADCOMMENT (0x400)
00414 #endif
00415 /*
00416   Locate the Central directory of a zipfile (at the end, just before
00417     the global comment)
00418 */
00419 local uLong ziplocal_SearchCentralDir OF((
00420     const zlib_filefunc_def* pzlib_filefunc_def,
00421     voidpf filestream));
00422 
00423 local uLong ziplocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream)
00424 {
00425     unsigned char* buf;
00426     uLong uSizeFile;
00427     uLong uBackRead;
00428     uLong uMaxBack=0xffff; /* maximum size of global comment */
00429     uLong uPosFound=0;
00430 
00431     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
00432         return 0;
00433 
00434 
00435     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
00436 
00437     if (uMaxBack>uSizeFile)
00438         uMaxBack = uSizeFile;
00439 
00440     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
00441     if (buf==NULL)
00442         return 0;
00443 
00444     uBackRead = 4;
00445     while (uBackRead<uMaxBack)
00446     {
00447         uLong uReadSize,uReadPos ;
00448         int i;
00449         if (uBackRead+BUFREADCOMMENT>uMaxBack)
00450             uBackRead = uMaxBack;
00451         else
00452             uBackRead+=BUFREADCOMMENT;
00453         uReadPos = uSizeFile-uBackRead ;
00454 
00455         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
00456                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
00457         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
00458             break;
00459 
00460         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
00461             break;
00462 
00463         for (i=(int)uReadSize-3; (i--)>0;)
00464             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
00465                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
00466             {
00467                 uPosFound = uReadPos+i;
00468                 break;
00469             }
00470 
00471         if (uPosFound!=0)
00472             break;
00473     }
00474     TRYFREE(buf);
00475     return uPosFound;
00476 }
00477 #endif /* !NO_ADDFILEINEXISTINGZIP*/
00478 
00479 /************************************************************/
00480 extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append,
00481                                                                  zipcharpc* globalcomment,
00482                                                                  zlib_filefunc_def* pzlib_filefunc_def)
00483 {
00484     zip_internal ziinit;
00485     zip_internal* zi;
00486     int err=ZIP_OK;
00487 
00488 
00489     if (pzlib_filefunc_def==NULL)
00490         fill_fopen_filefunc(&ziinit.z_filefunc);
00491     else
00492         ziinit.z_filefunc = *pzlib_filefunc_def;
00493 
00494     ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
00495                  (ziinit.z_filefunc.opaque,
00496                   pathname,
00497                   (append == APPEND_STATUS_CREATE) ?
00498                   (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
00499                     (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
00500 
00501     if (ziinit.filestream == NULL)
00502         return NULL;
00503     ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
00504     ziinit.in_opened_file_inzip = 0;
00505     ziinit.ci.stream_initialised = 0;
00506     ziinit.number_entry = 0;
00507     ziinit.add_position_when_writting_offset = 0;
00508     init_linkedlist(&(ziinit.central_dir));
00509 
00510 
00511     zi = (zip_internal*)ALLOC(sizeof(zip_internal));
00512     if (zi==NULL)
00513     {
00514         ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
00515         return NULL;
00516     }
00517 
00518     /* now we add file in a zipfile */
00519 #    ifndef NO_ADDFILEINEXISTINGZIP
00520     if (append == APPEND_STATUS_ADDINZIP)
00521     {
00522         uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
00523 
00524         uLong size_central_dir;     /* size of the central directory  */
00525         uLong offset_central_dir;   /* offset of start of central directory */
00526         uLong central_pos,uL;
00527 
00528         uLong number_disk;          /* number of the current dist, used for
00529                                     spaning ZIP, unsupported, always 0*/
00530         uLong number_disk_with_CD;  /* number the the disk with central dir, used
00531                                     for spaning ZIP, unsupported, always 0*/
00532         uLong number_entry;
00533         uLong number_entry_CD;      /* total number of entries in
00534                                     the central dir
00535                                     (same than number_entry on nospan) */
00536         uLong size_comment;
00537 
00538         central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
00539         if (central_pos==0)
00540             err=ZIP_ERRNO;
00541 
00542         if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
00543                                         central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
00544             err=ZIP_ERRNO;
00545 
00546         /* the signature, already checked */
00547         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
00548             err=ZIP_ERRNO;
00549 
00550         /* number of this disk */
00551         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
00552             err=ZIP_ERRNO;
00553 
00554         /* number of the disk with the start of the central directory */
00555         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
00556             err=ZIP_ERRNO;
00557 
00558         /* total number of entries in the central dir on this disk */
00559         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
00560             err=ZIP_ERRNO;
00561 
00562         /* total number of entries in the central dir */
00563         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
00564             err=ZIP_ERRNO;
00565 
00566         if ((number_entry_CD!=number_entry) ||
00567             (number_disk_with_CD!=0) ||
00568             (number_disk!=0))
00569             err=ZIP_BADZIPFILE;
00570 
00571         /* size of the central directory */
00572         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
00573             err=ZIP_ERRNO;
00574 
00575         /* offset of start of central directory with respect to the
00576             starting disk number */
00577         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
00578             err=ZIP_ERRNO;
00579 
00580         /* zipfile comment length */
00581         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
00582             err=ZIP_ERRNO;
00583 
00584         if ((central_pos<offset_central_dir+size_central_dir) &&
00585             (err==ZIP_OK))
00586             err=ZIP_BADZIPFILE;
00587 
00588         if (err!=ZIP_OK)
00589         {
00590             ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
00591             return NULL;
00592         }
00593 
00594         byte_before_the_zipfile = central_pos -
00595                                 (offset_central_dir+size_central_dir);
00596         ziinit.add_position_when_writting_offset = byte_before_the_zipfile ;
00597 
00598         {
00599             uLong size_central_dir_to_read = size_central_dir;
00600             size_t buf_size = SIZEDATA_INDATABLOCK;
00601             void* buf_read = (void*)ALLOC(buf_size);
00602             if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
00603                   offset_central_dir + byte_before_the_zipfile,
00604                   ZLIB_FILEFUNC_SEEK_SET) != 0)
00605                   err=ZIP_ERRNO;
00606 
00607             while ((size_central_dir_to_read>0) && (err==ZIP_OK))
00608             {
00609                 uLong read_this = SIZEDATA_INDATABLOCK;
00610                 if (read_this > size_central_dir_to_read)
00611                     read_this = size_central_dir_to_read;
00612                 if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
00613                     err=ZIP_ERRNO;
00614 
00615                 if (err==ZIP_OK)
00616                     err = add_data_in_datablock(&ziinit.central_dir,buf_read,
00617                                                 (uLong)read_this);
00618                 size_central_dir_to_read-=read_this;
00619             }
00620             TRYFREE(buf_read);
00621         }
00622         ziinit.begin_pos = byte_before_the_zipfile;
00623         ziinit.number_entry = number_entry_CD;
00624 
00625         if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
00626                   offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
00627             err=ZIP_ERRNO;
00628     }
00629 #    endif /* !NO_ADDFILEINEXISTINGZIP*/
00630 
00631     if (err != ZIP_OK)
00632     {
00633         TRYFREE(zi);
00634         return NULL;
00635     }
00636     else
00637     {
00638         *zi = ziinit;
00639         return (zipFile)zi;
00640     }
00641 }
00642 
00643 extern zipFile ZEXPORT zipOpen (const char *pathname, int append)
00644 {
00645     return zipOpen2(pathname,append,NULL,NULL);
00646 }
00647 
00648 extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename,
00649                                                                                  const zip_fileinfo* zipfi,
00650                                                                                  const void* extrafield_local,
00651                                                                                  uInt size_extrafield_local,
00652                                                                                  const void* extrafield_global,
00653                                                                                  uInt size_extrafield_global,
00654                                                                                  const char* comment,
00655                                                                                  int method, int level, int raw,
00656                                                                                  int windowBits, int memLevel,
00657                                                                                  int strategy, const char* password,
00658                                                                                  uLong crcForCrypting)
00659 {
00660     zip_internal* zi;
00661     uInt size_filename;
00662     uInt size_comment;
00663     uInt i;
00664     int err = ZIP_OK;
00665 
00666 #    ifdef NOCRYPT
00667     if (password != NULL)
00668         return ZIP_PARAMERROR;
00669 #    endif
00670 
00671     if (file == NULL)
00672         return ZIP_PARAMERROR;
00673     if ((method!=0) && (method!=Z_DEFLATED))
00674         return ZIP_PARAMERROR;
00675 
00676     zi = (zip_internal*)file;
00677 
00678     if (zi->in_opened_file_inzip == 1)
00679     {
00680         err = zipCloseFileInZip (file);
00681         if (err != ZIP_OK)
00682             return err;
00683     }
00684 
00685 
00686     if (filename==NULL)
00687         filename="-";
00688 
00689     if (comment==NULL)
00690         size_comment = 0;
00691     else
00692         size_comment = (uInt)strlen(comment);
00693 
00694     size_filename = (uInt)strlen(filename);
00695 
00696     if (zipfi == NULL)
00697         zi->ci.dosDate = 0;
00698     else
00699     {
00700         if (zipfi->dosDate != 0)
00701             zi->ci.dosDate = zipfi->dosDate;
00702         else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
00703     }
00704 
00705     zi->ci.flag = 0;
00706     if ((level==8) || (level==9))
00707       zi->ci.flag |= 2;
00708     if ((level==2))
00709       zi->ci.flag |= 4;
00710     if ((level==1))
00711       zi->ci.flag |= 6;
00712     if (password != NULL)
00713       zi->ci.flag |= 1;
00714 
00715     zi->ci.crc32 = 0;
00716     zi->ci.method = method;
00717     zi->ci.encrypt = 0;
00718     zi->ci.stream_initialised = 0;
00719     zi->ci.pos_in_buffered_data = 0;
00720     zi->ci.raw = raw;
00721     zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
00722     zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
00723                                       size_extrafield_global + size_comment;
00724     zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
00725 
00726     ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
00727     /* version info */
00728     ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
00729     ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
00730     ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
00731     ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
00732     ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
00733     ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
00734     ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
00735     ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
00736     ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
00737     ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
00738     ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
00739     ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
00740 
00741     if (zipfi==NULL)
00742         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
00743     else
00744         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
00745 
00746     if (zipfi==NULL)
00747         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
00748     else
00749         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
00750 
00751     ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
00752 
00753     for (i=0;i<size_filename;i++)
00754         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
00755 
00756     for (i=0;i<size_extrafield_global;i++)
00757         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
00758               *(((const char*)extrafield_global)+i);
00759 
00760     for (i=0;i<size_comment;i++)
00761         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
00762               size_extrafield_global+i) = *(comment+i);
00763     if (zi->ci.central_header == NULL)
00764         return ZIP_INTERNALERROR;
00765 
00766     /* write the local header */
00767     err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
00768 
00769     if (err==ZIP_OK)
00770         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
00771     if (err==ZIP_OK)
00772         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
00773 
00774     if (err==ZIP_OK)
00775         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
00776 
00777     if (err==ZIP_OK)
00778         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
00779 
00780     if (err==ZIP_OK)
00781         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
00782     if (err==ZIP_OK)
00783         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
00784     if (err==ZIP_OK)
00785         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
00786 
00787     if (err==ZIP_OK)
00788         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
00789 
00790     if (err==ZIP_OK)
00791         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
00792 
00793     if ((err==ZIP_OK) && (size_filename>0))
00794         if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
00795                 err = ZIP_ERRNO;
00796 
00797     if ((err==ZIP_OK) && (size_extrafield_local>0))
00798         if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
00799                                                                            !=size_extrafield_local)
00800                 err = ZIP_ERRNO;
00801 
00802     zi->ci.stream.avail_in = (uInt)0;
00803     zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
00804     zi->ci.stream.next_out = zi->ci.buffered_data;
00805     zi->ci.stream.total_in = 0;
00806     zi->ci.stream.total_out = 0;
00807 
00808     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
00809     {
00810         zi->ci.stream.zalloc = (alloc_func)0;
00811         zi->ci.stream.zfree = (free_func)0;
00812         zi->ci.stream.opaque = (voidpf)0;
00813 
00814         if (windowBits>0)
00815             windowBits = -windowBits;
00816 
00817         err = deflateInit2(&zi->ci.stream, level,
00818                Z_DEFLATED, windowBits, memLevel, strategy);
00819 
00820         if (err==Z_OK)
00821             zi->ci.stream_initialised = 1;
00822     }
00823 #    ifndef NOCRYPT
00824     zi->ci.crypt_header_size = 0;
00825     if ((err==Z_OK) && (password != NULL))
00826     {
00827         unsigned char bufHead[RAND_HEAD_LEN];
00828         unsigned int sizeHead;
00829         zi->ci.encrypt = 1;
00830         zi->ci.pcrc_32_tab = get_crc_table();
00831         /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
00832 
00833         sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
00834         zi->ci.crypt_header_size = sizeHead;
00835 
00836         if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
00837                 err = ZIP_ERRNO;
00838     }
00839 #    endif
00840 
00841     if (err==Z_OK)
00842         zi->in_opened_file_inzip = 1;
00843     return err;
00844 }
00845 
00846 extern int ZEXPORT zipOpenNewFileInZip2(zipFile file,
00847                                                                                 const char* filename,
00848                                                                                 const zip_fileinfo* zipfi,
00849                                                                                 const void* extrafield_local,
00850                                                                                 uInt size_extrafield_local,
00851                                                                                 const void* extrafield_global,
00852                                                                                 uInt size_extrafield_global,
00853                                                                                 const char* comment,
00854                                                                                 int method, int level, int raw)
00855 {
00856     return zipOpenNewFileInZip3 (file, filename, zipfi,
00857                                  extrafield_local, size_extrafield_local,
00858                                  extrafield_global, size_extrafield_global,
00859                                  comment, method, level, raw,
00860                                  -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
00861                                  NULL, 0);
00862 }
00863 
00864 extern int ZEXPORT zipOpenNewFileInZip (zipFile file,
00865                                                                                 const char* filename,
00866                                                                                 const zip_fileinfo* zipfi,
00867                                                                                 const void* extrafield_local,
00868                                                                                 uInt size_extrafield_local,
00869                                                                                 const void* extrafield_global,
00870                                                                                 uInt size_extrafield_global,
00871                                                                                 const char* comment,
00872                                                                                 int method, int level)
00873 {
00874     return zipOpenNewFileInZip2 (file, filename, zipfi,
00875                                  extrafield_local, size_extrafield_local,
00876                                  extrafield_global, size_extrafield_global,
00877                                  comment, method, level, 0);
00878 }
00879 
00880 local int zipFlushWriteBuffer(zip_internal* zi)
00881 {
00882     int err=ZIP_OK;
00883 
00884     if (zi->ci.encrypt != 0)
00885     {
00886 #ifndef NOCRYPT
00887         uInt i;
00888         int t;
00889         for (i=0;i<zi->ci.pos_in_buffered_data;i++)
00890             zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
00891                                        zi->ci.buffered_data[i],t);
00892 #endif
00893     }
00894     if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
00895                                                                     !=zi->ci.pos_in_buffered_data)
00896       err = ZIP_ERRNO;
00897     zi->ci.pos_in_buffered_data = 0;
00898     return err;
00899 }
00900 
00901 extern int ZEXPORT zipWriteInFileInZip (zipFile file, const void* buf,
00902                                                                                 unsigned len)
00903 {
00904     zip_internal* zi;
00905     int err=ZIP_OK;
00906 
00907     if (file == NULL)
00908         return ZIP_PARAMERROR;
00909     zi = (zip_internal*)file;
00910 
00911     if (zi->in_opened_file_inzip == 0)
00912         return ZIP_PARAMERROR;
00913 
00914     zi->ci.stream.next_in = (Bytef*)buf;
00915     zi->ci.stream.avail_in = len;
00916     zi->ci.crc32 = crc32(zi->ci.crc32,(const Bytef*)buf,len);
00917 
00918     while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
00919     {
00920         if (zi->ci.stream.avail_out == 0)
00921         {
00922             if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
00923                 err = ZIP_ERRNO;
00924             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
00925             zi->ci.stream.next_out = zi->ci.buffered_data;
00926         }
00927 
00928 
00929         if(err != ZIP_OK)
00930             break;
00931 
00932         if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
00933         {
00934             uLong uTotalOutBefore = zi->ci.stream.total_out;
00935             err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
00936             zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
00937 
00938         }
00939         else
00940         {
00941             uInt copy_this,i;
00942             if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
00943                 copy_this = zi->ci.stream.avail_in;
00944             else
00945                 copy_this = zi->ci.stream.avail_out;
00946             for (i=0;i<copy_this;i++)
00947                 *(((char*)zi->ci.stream.next_out)+i) =
00948                     *(((const char*)zi->ci.stream.next_in)+i);
00949             {
00950                 zi->ci.stream.avail_in -= copy_this;
00951                 zi->ci.stream.avail_out-= copy_this;
00952                 zi->ci.stream.next_in+= copy_this;
00953                 zi->ci.stream.next_out+= copy_this;
00954                 zi->ci.stream.total_in+= copy_this;
00955                 zi->ci.stream.total_out+= copy_this;
00956                 zi->ci.pos_in_buffered_data += copy_this;
00957             }
00958         }
00959     }
00960 
00961     return err;
00962 }
00963 
00964 extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size,
00965                                                                                  uLong crc32)
00966 {
00967     zip_internal* zi;
00968     uLong compressed_size;
00969     int err=ZIP_OK;
00970 
00971     if (file == NULL)
00972         return ZIP_PARAMERROR;
00973     zi = (zip_internal*)file;
00974 
00975     if (zi->in_opened_file_inzip == 0)
00976         return ZIP_PARAMERROR;
00977     zi->ci.stream.avail_in = 0;
00978 
00979     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
00980         while (err==ZIP_OK)
00981     {
00982         uLong uTotalOutBefore;
00983         if (zi->ci.stream.avail_out == 0)
00984         {
00985             if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
00986                 err = ZIP_ERRNO;
00987             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
00988             zi->ci.stream.next_out = zi->ci.buffered_data;
00989         }
00990         uTotalOutBefore = zi->ci.stream.total_out;
00991         err=deflate(&zi->ci.stream,  Z_FINISH);
00992         zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
00993     }
00994 
00995     if (err==Z_STREAM_END)
00996         err=ZIP_OK; /* this is normal */
00997 
00998     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
00999         if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
01000             err = ZIP_ERRNO;
01001 
01002     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
01003     {
01004         err=deflateEnd(&zi->ci.stream);
01005         zi->ci.stream_initialised = 0;
01006     }
01007 
01008     if (!zi->ci.raw)
01009     {
01010         crc32 = (uLong)zi->ci.crc32;
01011         uncompressed_size = (uLong)zi->ci.stream.total_in;
01012     }
01013     compressed_size = (uLong)zi->ci.stream.total_out;
01014 #    ifndef NOCRYPT
01015     compressed_size += zi->ci.crypt_header_size;
01016 #    endif
01017 
01018     ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
01019     ziplocal_putValue_inmemory(zi->ci.central_header+20,
01020                                 compressed_size,4); /*compr size*/
01021     if (zi->ci.stream.data_type == Z_ASCII)
01022         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
01023     ziplocal_putValue_inmemory(zi->ci.central_header+24,
01024                                 uncompressed_size,4); /*uncompr size*/
01025 
01026     if (err==ZIP_OK)
01027         err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
01028                                        (uLong)zi->ci.size_centralheader);
01029     free(zi->ci.central_header);
01030 
01031     if (err==ZIP_OK)
01032     {
01033         long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
01034         if (ZSEEK(zi->z_filefunc,zi->filestream,
01035                   zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
01036             err = ZIP_ERRNO;
01037 
01038         if (err==ZIP_OK)
01039             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
01040 
01041         if (err==ZIP_OK) /* compressed size, unknown */
01042             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
01043 
01044         if (err==ZIP_OK) /* uncompressed size, unknown */
01045             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
01046 
01047         if (ZSEEK(zi->z_filefunc,zi->filestream,
01048                   cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
01049             err = ZIP_ERRNO;
01050     }
01051 
01052     zi->number_entry ++;
01053     zi->in_opened_file_inzip = 0;
01054 
01055     return err;
01056 }
01057 
01058 extern int ZEXPORT zipCloseFileInZip (zipFile file)
01059 {
01060     return zipCloseFileInZipRaw (file,0,0);
01061 }
01062 
01063 extern int ZEXPORT zipClose (zipFile file, const char* global_comment)
01064 {
01065     zip_internal* zi;
01066     int err = 0;
01067     uLong size_centraldir = 0;
01068     uLong centraldir_pos_inzip ;
01069     uInt size_global_comment;
01070     if (file == NULL)
01071         return ZIP_PARAMERROR;
01072     zi = (zip_internal*)file;
01073 
01074     if (zi->in_opened_file_inzip == 1)
01075     {
01076         err = zipCloseFileInZip (file);
01077     }
01078 
01079     if (global_comment==NULL)
01080         size_global_comment = 0;
01081     else
01082         size_global_comment = (uInt)strlen(global_comment);
01083 
01084 
01085     centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
01086     if (err==ZIP_OK)
01087     {
01088         linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
01089         while (ldi!=NULL)
01090         {
01091             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
01092                 if (ZWRITE(zi->z_filefunc,zi->filestream,
01093                            ldi->data,ldi->filled_in_this_block)
01094                               !=ldi->filled_in_this_block )
01095                     err = ZIP_ERRNO;
01096 
01097             size_centraldir += ldi->filled_in_this_block;
01098             ldi = ldi->next_datablock;
01099         }
01100     }
01101     free_datablock(zi->central_dir.first_block);
01102 
01103     if (err==ZIP_OK) /* Magic End */
01104         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
01105 
01106     if (err==ZIP_OK) /* number of this disk */
01107         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
01108 
01109     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
01110         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
01111 
01112     if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
01113         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
01114 
01115     if (err==ZIP_OK) /* total number of entries in the central dir */
01116         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
01117 
01118     if (err==ZIP_OK) /* size of the central directory */
01119         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
01120 
01121     if (err==ZIP_OK) /* offset of start of central directory with respect to the
01122                             starting disk number */
01123         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
01124                                 (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
01125 
01126     if (err==ZIP_OK) /* zipfile comment length */
01127         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
01128 
01129     if ((err==ZIP_OK) && (size_global_comment>0))
01130         if (ZWRITE(zi->z_filefunc,zi->filestream,
01131                    global_comment,size_global_comment) != size_global_comment)
01132                 err = ZIP_ERRNO;
01133 
01134     if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
01135         if (err == ZIP_OK)
01136             err = ZIP_ERRNO;
01137 
01138     TRYFREE(zi);
01139 
01140     return err;
01141 }
01142 
01143 
01144 }

Generated on Fri Jul 27 22:27:56 2007 for pentagram by  doxygen 1.4.7