PageRenderTime 337ms CodeModel.GetById 80ms app.highlight 199ms RepoModel.GetById 43ms app.codeStats 1ms

/src/libtomahawk/thirdparty/quazip/quazip/unzip.c

http://github.com/tomahawk-player/tomahawk
C | 1603 lines | 1105 code | 277 blank | 221 comment | 265 complexity | 33e9d333661c1ec22d8fc89abfe0c2ea MD5 | raw file
   1/* unzip.c -- IO for uncompress .zip files using zlib
   2   Version 1.01e, February 12th, 2005
   3
   4   Copyright (C) 1998-2005 Gilles Vollant
   5
   6   Read unzip.h for more info
   7
   8   Modified by Sergey A. Tachenov to integrate with Qt.
   9*/
  10
  11/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
  12compatibility with older software. The following is from the original crypt.c. Code
  13woven in by Terry Thorsen 1/2003.
  14*/
  15/*
  16  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
  17
  18  See the accompanying file LICENSE, version 2000-Apr-09 or later
  19  (the contents of which are also included in zip.h) for terms of use.
  20  If, for some reason, all these files are missing, the Info-ZIP license
  21  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  22*/
  23/*
  24  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
  25
  26  The encryption/decryption parts of this source code (as opposed to the
  27  non-echoing password parts) were originally written in Europe.  The
  28  whole source package can be freely distributed, including from the USA.
  29  (Prior to January 2000, re-export from the US was a violation of US law.)
  30 */
  31
  32/*
  33  This encryption code is a direct transcription of the algorithm from
  34  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
  35  file (appnote.txt) is distributed with the PKZIP program (even in the
  36  version without encryption capabilities).
  37 */
  38
  39
  40#include <stdio.h>
  41#include <stdlib.h>
  42#include <string.h>
  43#include "zlib.h"
  44#include "unzip.h"
  45
  46#ifdef STDC
  47#  include <stddef.h>
  48#  include <string.h>
  49#  include <stdlib.h>
  50#endif
  51#ifdef NO_ERRNO_H
  52    extern int errno;
  53#else
  54#   include <errno.h>
  55#endif
  56
  57
  58#ifndef local
  59#  define local static
  60#endif
  61/* compile with -Dlocal if your debugger can't find static symbols */
  62
  63
  64#ifndef CASESENSITIVITYDEFAULT_NO
  65#  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
  66#    define CASESENSITIVITYDEFAULT_NO
  67#  endif
  68#endif
  69
  70
  71#ifndef UNZ_BUFSIZE
  72#define UNZ_BUFSIZE (16384)
  73#endif
  74
  75#ifndef UNZ_MAXFILENAMEINZIP
  76#define UNZ_MAXFILENAMEINZIP (256)
  77#endif
  78
  79#ifndef ALLOC
  80# define ALLOC(size) (malloc(size))
  81#endif
  82#ifndef TRYFREE
  83# define TRYFREE(p) {if (p) free(p);}
  84#endif
  85
  86#define SIZECENTRALDIRITEM (0x2e)
  87#define SIZEZIPLOCALHEADER (0x1e)
  88
  89
  90
  91
  92const char unz_copyright[] =
  93   " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
  94
  95/* unz_file_info_interntal contain internal info about a file in zipfile*/
  96typedef struct unz_file_info_internal_s
  97{
  98    uLong offset_curfile;/* relative offset of local header 4 bytes */
  99} unz_file_info_internal;
 100
 101
 102/* file_in_zip_read_info_s contain internal information about a file in zipfile,
 103    when reading and decompress it */
 104typedef struct
 105{
 106    char  *read_buffer;         /* internal buffer for compressed data */
 107    z_stream stream;            /* zLib stream structure for inflate */
 108
 109    uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
 110    uLong stream_initialised;   /* flag set if stream structure is initialised*/
 111
 112    uLong offset_local_extrafield;/* offset of the local extra field */
 113    uInt  size_local_extrafield;/* size of the local extra field */
 114    uLong pos_local_extrafield;   /* position in the local extra field in read*/
 115
 116    uLong crc32;                /* crc32 of all data uncompressed */
 117    uLong crc32_wait;           /* crc32 we must obtain after decompress all */
 118    uLong rest_read_compressed; /* number of byte to be decompressed */
 119    uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
 120    zlib_filefunc_def z_filefunc;
 121    voidpf filestream;        /* io structore of the zipfile */
 122    uLong compression_method;   /* compression method (0==store) */
 123    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
 124    int   raw;
 125} file_in_zip_read_info_s;
 126
 127
 128/* unz_s contain internal information about the zipfile
 129*/
 130typedef struct
 131{
 132    zlib_filefunc_def z_filefunc;
 133    voidpf filestream;        /* io structore of the zipfile */
 134    unz_global_info gi;       /* public global information */
 135    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
 136    uLong num_file;             /* number of the current file in the zipfile*/
 137    uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
 138    uLong current_file_ok;      /* flag about the usability of the current file*/
 139    uLong central_pos;          /* position of the beginning of the central dir*/
 140
 141    uLong size_central_dir;     /* size of the central directory  */
 142    uLong offset_central_dir;   /* offset of start of central directory with
 143                                   respect to the starting disk number */
 144
 145    unz_file_info cur_file_info; /* public info about the current file in zip*/
 146    unz_file_info_internal cur_file_info_internal; /* private info about it*/
 147    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
 148                                        file if we are decompressing it */
 149    int encrypted;
 150#    ifndef NOUNCRYPT
 151    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
 152    const unsigned long* pcrc_32_tab;
 153#    endif
 154} unz_s;
 155
 156
 157#ifndef NOUNCRYPT
 158#include "crypt.h"
 159#endif
 160
 161/* ===========================================================================
 162     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
 163   for end of file.
 164   IN assertion: the stream s has been sucessfully opened for reading.
 165*/
 166
 167
 168local int unzlocal_getByte OF((
 169    const zlib_filefunc_def* pzlib_filefunc_def,
 170    voidpf filestream,
 171    int *pi));
 172
 173local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
 174    const zlib_filefunc_def* pzlib_filefunc_def;
 175    voidpf filestream;
 176    int *pi;
 177{
 178    unsigned char c;
 179    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
 180    if (err==1)
 181    {
 182        *pi = (int)c;
 183        return UNZ_OK;
 184    }
 185    else
 186    {
 187        if (ZERROR(*pzlib_filefunc_def,filestream))
 188            return UNZ_ERRNO;
 189        else
 190            return UNZ_EOF;
 191    }
 192}
 193
 194
 195/* ===========================================================================
 196   Reads a long in LSB order from the given gz_stream. Sets
 197*/
 198local int unzlocal_getShort OF((
 199    const zlib_filefunc_def* pzlib_filefunc_def,
 200    voidpf filestream,
 201    uLong *pX));
 202
 203local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
 204    const zlib_filefunc_def* pzlib_filefunc_def;
 205    voidpf filestream;
 206    uLong *pX;
 207{
 208    uLong x ;
 209    int i;
 210    int err;
 211
 212    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
 213    x = (uLong)i;
 214
 215    if (err==UNZ_OK)
 216        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
 217    x += ((uLong)i)<<8;
 218
 219    if (err==UNZ_OK)
 220        *pX = x;
 221    else
 222        *pX = 0;
 223    return err;
 224}
 225
 226local int unzlocal_getLong OF((
 227    const zlib_filefunc_def* pzlib_filefunc_def,
 228    voidpf filestream,
 229    uLong *pX));
 230
 231local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
 232    const zlib_filefunc_def* pzlib_filefunc_def;
 233    voidpf filestream;
 234    uLong *pX;
 235{
 236    uLong x ;
 237    int i;
 238    int err;
 239
 240    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
 241    x = (uLong)i;
 242
 243    if (err==UNZ_OK)
 244        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
 245    x += ((uLong)i)<<8;
 246
 247    if (err==UNZ_OK)
 248        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
 249    x += ((uLong)i)<<16;
 250
 251    if (err==UNZ_OK)
 252        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
 253    x += ((uLong)i)<<24;
 254
 255    if (err==UNZ_OK)
 256        *pX = x;
 257    else
 258        *pX = 0;
 259    return err;
 260}
 261
 262
 263/* My own strcmpi / strcasecmp */
 264local int strcmpcasenosensitive_internal (fileName1,fileName2)
 265    const char* fileName1;
 266    const char* fileName2;
 267{
 268    for (;;)
 269    {
 270        char c1=*(fileName1++);
 271        char c2=*(fileName2++);
 272        if ((c1>='a') && (c1<='z'))
 273            c1 -= 0x20;
 274        if ((c2>='a') && (c2<='z'))
 275            c2 -= 0x20;
 276        if (c1=='\0')
 277            return ((c2=='\0') ? 0 : -1);
 278        if (c2=='\0')
 279            return 1;
 280        if (c1<c2)
 281            return -1;
 282        if (c1>c2)
 283            return 1;
 284    }
 285}
 286
 287
 288#ifdef  CASESENSITIVITYDEFAULT_NO
 289#define CASESENSITIVITYDEFAULTVALUE 2
 290#else
 291#define CASESENSITIVITYDEFAULTVALUE 1
 292#endif
 293
 294#ifndef STRCMPCASENOSENTIVEFUNCTION
 295#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
 296#endif
 297
 298/*
 299   Compare two filename (fileName1,fileName2).
 300   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
 301   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
 302                                                                or strcasecmp)
 303   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
 304        (like 1 on Unix, 2 on Windows)
 305
 306*/
 307extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
 308    const char* fileName1;
 309    const char* fileName2;
 310    int iCaseSensitivity;
 311{
 312    if (iCaseSensitivity==0)
 313        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
 314
 315    if (iCaseSensitivity==1)
 316        return strcmp(fileName1,fileName2);
 317
 318    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
 319}
 320
 321#ifndef BUFREADCOMMENT
 322#define BUFREADCOMMENT (0x400)
 323#endif
 324
 325/*
 326  Locate the Central directory of a zipfile (at the end, just before
 327    the global comment)
 328*/
 329local uLong unzlocal_SearchCentralDir OF((
 330    const zlib_filefunc_def* pzlib_filefunc_def,
 331    voidpf filestream));
 332
 333local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
 334    const zlib_filefunc_def* pzlib_filefunc_def;
 335    voidpf filestream;
 336{
 337    unsigned char* buf;
 338    uLong uSizeFile;
 339    uLong uBackRead;
 340    uLong uMaxBack=0xffff; /* maximum size of global comment */
 341    uLong uPosFound=0;
 342
 343    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
 344        return 0;
 345
 346
 347    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
 348
 349    if (uMaxBack>uSizeFile)
 350        uMaxBack = uSizeFile;
 351
 352    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
 353    if (buf==NULL)
 354        return 0;
 355
 356    uBackRead = 4;
 357    while (uBackRead<uMaxBack)
 358    {
 359        uLong uReadSize,uReadPos ;
 360        int i;
 361        if (uBackRead+BUFREADCOMMENT>uMaxBack)
 362            uBackRead = uMaxBack;
 363        else
 364            uBackRead+=BUFREADCOMMENT;
 365        uReadPos = uSizeFile-uBackRead ;
 366
 367        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
 368                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
 369        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
 370            break;
 371
 372        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
 373            break;
 374
 375        for (i=(int)uReadSize-3; (i--)>0;)
 376            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
 377                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
 378            {
 379                uPosFound = uReadPos+i;
 380                break;
 381            }
 382
 383        if (uPosFound!=0)
 384            break;
 385    }
 386    TRYFREE(buf);
 387    return uPosFound;
 388}
 389
 390/*
 391  Open a Zip file. path contain the full pathname (by example,
 392     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
 393     "zlib/zlib114.zip".
 394     If the zipfile cannot be opened (file doesn't exist or in not valid), the
 395       return value is NULL.
 396     Else, the return value is a unzFile Handle, usable with other function
 397       of this unzip package.
 398*/
 399extern unzFile ZEXPORT unzOpen2 (file, pzlib_filefunc_def)
 400    voidpf file;
 401    zlib_filefunc_def* pzlib_filefunc_def;
 402{
 403    unz_s us;
 404    unz_s *s;
 405    uLong central_pos,uL;
 406
 407    uLong number_disk;          /* number of the current dist, used for
 408                                   spaning ZIP, unsupported, always 0*/
 409    uLong number_disk_with_CD;  /* number the the disk with central dir, used
 410                                   for spaning ZIP, unsupported, always 0*/
 411    uLong number_entry_CD;      /* total number of entries in
 412                                   the central dir
 413                                   (same than number_entry on nospan) */
 414
 415    int err=UNZ_OK;
 416
 417    if (unz_copyright[0]!=' ')
 418        return NULL;
 419
 420    if (pzlib_filefunc_def==NULL)
 421        fill_qiodevice_filefunc(&us.z_filefunc);
 422    else
 423        us.z_filefunc = *pzlib_filefunc_def;
 424
 425    us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
 426                                                 file,
 427                                                 ZLIB_FILEFUNC_MODE_READ |
 428                                                 ZLIB_FILEFUNC_MODE_EXISTING);
 429    if (us.filestream==NULL)
 430        return NULL;
 431
 432    central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
 433    if (central_pos==0)
 434        err=UNZ_ERRNO;
 435
 436    if (ZSEEK(us.z_filefunc, us.filestream,
 437                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
 438        err=UNZ_ERRNO;
 439
 440    /* the signature, already checked */
 441    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
 442        err=UNZ_ERRNO;
 443
 444    /* number of this disk */
 445    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
 446        err=UNZ_ERRNO;
 447
 448    /* number of the disk with the start of the central directory */
 449    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
 450        err=UNZ_ERRNO;
 451
 452    /* total number of entries in the central dir on this disk */
 453    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
 454        err=UNZ_ERRNO;
 455
 456    /* total number of entries in the central dir */
 457    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
 458        err=UNZ_ERRNO;
 459
 460    if ((number_entry_CD!=us.gi.number_entry) ||
 461        (number_disk_with_CD!=0) ||
 462        (number_disk!=0))
 463        err=UNZ_BADZIPFILE;
 464
 465    /* size of the central directory */
 466    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
 467        err=UNZ_ERRNO;
 468
 469    /* offset of start of central directory with respect to the
 470          starting disk number */
 471    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
 472        err=UNZ_ERRNO;
 473
 474    /* zipfile comment length */
 475    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
 476        err=UNZ_ERRNO;
 477
 478    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
 479        (err==UNZ_OK))
 480        err=UNZ_BADZIPFILE;
 481
 482    if (err!=UNZ_OK)
 483    {
 484        ZCLOSE(us.z_filefunc, us.filestream);
 485        return NULL;
 486    }
 487
 488    us.byte_before_the_zipfile = central_pos -
 489                            (us.offset_central_dir+us.size_central_dir);
 490    us.central_pos = central_pos;
 491    us.pfile_in_zip_read = NULL;
 492    us.encrypted = 0;
 493
 494
 495    s=(unz_s*)ALLOC(sizeof(unz_s));
 496    *s=us;
 497    unzGoToFirstFile((unzFile)s);
 498    return (unzFile)s;
 499}
 500
 501
 502extern unzFile ZEXPORT unzOpen (file)
 503    voidpf file;
 504{
 505    return unzOpen2(file, NULL);
 506}
 507
 508/*
 509  Close a ZipFile opened with unzipOpen.
 510  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
 511    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
 512  return UNZ_OK if there is no problem. */
 513extern int ZEXPORT unzClose (file)
 514    unzFile file;
 515{
 516    unz_s* s;
 517    if (file==NULL)
 518        return UNZ_PARAMERROR;
 519    s=(unz_s*)file;
 520
 521    if (s->pfile_in_zip_read!=NULL)
 522        unzCloseCurrentFile(file);
 523
 524    ZCLOSE(s->z_filefunc, s->filestream);
 525    TRYFREE(s);
 526    return UNZ_OK;
 527}
 528
 529
 530/*
 531  Write info about the ZipFile in the *pglobal_info structure.
 532  No preparation of the structure is needed
 533  return UNZ_OK if there is no problem. */
 534extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
 535    unzFile file;
 536    unz_global_info *pglobal_info;
 537{
 538    unz_s* s;
 539    if (file==NULL)
 540        return UNZ_PARAMERROR;
 541    s=(unz_s*)file;
 542    *pglobal_info=s->gi;
 543    return UNZ_OK;
 544}
 545
 546
 547/*
 548   Translate date/time from Dos format to tm_unz (readable more easilty)
 549*/
 550local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
 551    uLong ulDosDate;
 552    tm_unz* ptm;
 553{
 554    uLong uDate;
 555    uDate = (uLong)(ulDosDate>>16);
 556    ptm->tm_mday = (uInt)(uDate&0x1f) ;
 557    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
 558    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
 559
 560    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
 561    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
 562    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
 563}
 564
 565/*
 566  Get Info about the current file in the zipfile, with internal only info
 567*/
 568local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
 569                                                  unz_file_info *pfile_info,
 570                                                  unz_file_info_internal
 571                                                  *pfile_info_internal,
 572                                                  char *szFileName,
 573                                                  uLong fileNameBufferSize,
 574                                                  void *extraField,
 575                                                  uLong extraFieldBufferSize,
 576                                                  char *szComment,
 577                                                  uLong commentBufferSize));
 578
 579local int unzlocal_GetCurrentFileInfoInternal (file,
 580                                              pfile_info,
 581                                              pfile_info_internal,
 582                                              szFileName, fileNameBufferSize,
 583                                              extraField, extraFieldBufferSize,
 584                                              szComment,  commentBufferSize)
 585    unzFile file;
 586    unz_file_info *pfile_info;
 587    unz_file_info_internal *pfile_info_internal;
 588    char *szFileName;
 589    uLong fileNameBufferSize;
 590    void *extraField;
 591    uLong extraFieldBufferSize;
 592    char *szComment;
 593    uLong commentBufferSize;
 594{
 595    unz_s* s;
 596    unz_file_info file_info;
 597    unz_file_info_internal file_info_internal;
 598    int err=UNZ_OK;
 599    uLong uMagic;
 600    uLong uSeek=0;
 601
 602    if (file==NULL)
 603        return UNZ_PARAMERROR;
 604    s=(unz_s*)file;
 605    if (ZSEEK(s->z_filefunc, s->filestream,
 606              s->pos_in_central_dir+s->byte_before_the_zipfile,
 607              ZLIB_FILEFUNC_SEEK_SET)!=0)
 608        err=UNZ_ERRNO;
 609
 610
 611    /* we check the magic */
 612    if (err==UNZ_OK) {
 613        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
 614            err=UNZ_ERRNO;
 615        else if (uMagic!=0x02014b50)
 616            err=UNZ_BADZIPFILE;
 617    }
 618
 619    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
 620        err=UNZ_ERRNO;
 621
 622    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
 623        err=UNZ_ERRNO;
 624
 625    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
 626        err=UNZ_ERRNO;
 627
 628    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
 629        err=UNZ_ERRNO;
 630
 631    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
 632        err=UNZ_ERRNO;
 633
 634    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
 635
 636    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
 637        err=UNZ_ERRNO;
 638
 639    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
 640        err=UNZ_ERRNO;
 641
 642    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
 643        err=UNZ_ERRNO;
 644
 645    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
 646        err=UNZ_ERRNO;
 647
 648    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
 649        err=UNZ_ERRNO;
 650
 651    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
 652        err=UNZ_ERRNO;
 653
 654    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
 655        err=UNZ_ERRNO;
 656
 657    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
 658        err=UNZ_ERRNO;
 659
 660    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
 661        err=UNZ_ERRNO;
 662
 663    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
 664        err=UNZ_ERRNO;
 665
 666    uSeek+=file_info.size_filename;
 667    if ((err==UNZ_OK) && (szFileName!=NULL))
 668    {
 669        uLong uSizeRead ;
 670        if (file_info.size_filename<fileNameBufferSize)
 671        {
 672            *(szFileName+file_info.size_filename)='\0';
 673            uSizeRead = file_info.size_filename;
 674        }
 675        else
 676            uSizeRead = fileNameBufferSize;
 677
 678        if ((file_info.size_filename>0) && (fileNameBufferSize>0))
 679            if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
 680                err=UNZ_ERRNO;
 681        uSeek -= uSizeRead;
 682    }
 683
 684
 685    if ((err==UNZ_OK) && (extraField!=NULL))
 686    {
 687        uLong uSizeRead ;
 688        if (file_info.size_file_extra<extraFieldBufferSize)
 689            uSizeRead = file_info.size_file_extra;
 690        else
 691            uSizeRead = extraFieldBufferSize;
 692
 693        if (uSeek!=0) {
 694            if (ZSEEK(s->z_filefunc, s->filestream,uSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
 695                uSeek=0;
 696            else
 697                err=UNZ_ERRNO;
 698        }
 699        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
 700            if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
 701                err=UNZ_ERRNO;
 702        uSeek += file_info.size_file_extra - uSizeRead;
 703    }
 704    else
 705        uSeek+=file_info.size_file_extra;
 706
 707
 708    if ((err==UNZ_OK) && (szComment!=NULL))
 709    {
 710        uLong uSizeRead ;
 711        if (file_info.size_file_comment<commentBufferSize)
 712        {
 713            *(szComment+file_info.size_file_comment)='\0';
 714            uSizeRead = file_info.size_file_comment;
 715        }
 716        else
 717            uSizeRead = commentBufferSize;
 718
 719        if (uSeek!=0) {
 720            if (ZSEEK(s->z_filefunc, s->filestream,uSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
 721                uSeek=0;
 722            else
 723                err=UNZ_ERRNO;
 724        }
 725        if ((file_info.size_file_comment>0) && (commentBufferSize>0))
 726            if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
 727                err=UNZ_ERRNO;
 728        uSeek+=file_info.size_file_comment - uSizeRead;
 729    }
 730    else
 731        uSeek+=file_info.size_file_comment;
 732
 733    if ((err==UNZ_OK) && (pfile_info!=NULL))
 734        *pfile_info=file_info;
 735
 736    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
 737        *pfile_info_internal=file_info_internal;
 738
 739    return err;
 740}
 741
 742
 743
 744/*
 745  Write info about the ZipFile in the *pglobal_info structure.
 746  No preparation of the structure is needed
 747  return UNZ_OK if there is no problem.
 748*/
 749extern int ZEXPORT unzGetCurrentFileInfo (file,
 750                                          pfile_info,
 751                                          szFileName, fileNameBufferSize,
 752                                          extraField, extraFieldBufferSize,
 753                                          szComment,  commentBufferSize)
 754    unzFile file;
 755    unz_file_info *pfile_info;
 756    char *szFileName;
 757    uLong fileNameBufferSize;
 758    void *extraField;
 759    uLong extraFieldBufferSize;
 760    char *szComment;
 761    uLong commentBufferSize;
 762{
 763    return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
 764                                                szFileName,fileNameBufferSize,
 765                                                extraField,extraFieldBufferSize,
 766                                                szComment,commentBufferSize);
 767}
 768
 769/*
 770  Set the current file of the zipfile to the first file.
 771  return UNZ_OK if there is no problem
 772*/
 773extern int ZEXPORT unzGoToFirstFile (file)
 774    unzFile file;
 775{
 776    int err=UNZ_OK;
 777    unz_s* s;
 778    if (file==NULL)
 779        return UNZ_PARAMERROR;
 780    s=(unz_s*)file;
 781    s->pos_in_central_dir=s->offset_central_dir;
 782    s->num_file=0;
 783    err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
 784                                             &s->cur_file_info_internal,
 785                                             NULL,0,NULL,0,NULL,0);
 786    s->current_file_ok = (err == UNZ_OK);
 787    return err;
 788}
 789
 790/*
 791  Set the current file of the zipfile to the next file.
 792  return UNZ_OK if there is no problem
 793  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
 794*/
 795extern int ZEXPORT unzGoToNextFile (file)
 796    unzFile file;
 797{
 798    unz_s* s;
 799    int err;
 800
 801    if (file==NULL)
 802        return UNZ_PARAMERROR;
 803    s=(unz_s*)file;
 804    if (!s->current_file_ok)
 805        return UNZ_END_OF_LIST_OF_FILE;
 806    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
 807      if (s->num_file+1==s->gi.number_entry)
 808        return UNZ_END_OF_LIST_OF_FILE;
 809
 810    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
 811            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
 812    s->num_file++;
 813    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
 814                                               &s->cur_file_info_internal,
 815                                               NULL,0,NULL,0,NULL,0);
 816    s->current_file_ok = (err == UNZ_OK);
 817    return err;
 818}
 819
 820
 821/*
 822  Try locate the file szFileName in the zipfile.
 823  For the iCaseSensitivity signification, see unzipStringFileNameCompare
 824
 825  return value :
 826  UNZ_OK if the file is found. It becomes the current file.
 827  UNZ_END_OF_LIST_OF_FILE if the file is not found
 828*/
 829extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
 830    unzFile file;
 831    const char *szFileName;
 832    int iCaseSensitivity;
 833{
 834    unz_s* s;
 835    int err;
 836
 837    /* We remember the 'current' position in the file so that we can jump
 838     * back there if we fail.
 839     */
 840    unz_file_info cur_file_infoSaved;
 841    unz_file_info_internal cur_file_info_internalSaved;
 842    uLong num_fileSaved;
 843    uLong pos_in_central_dirSaved;
 844
 845
 846    if (file==NULL)
 847        return UNZ_PARAMERROR;
 848
 849    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
 850        return UNZ_PARAMERROR;
 851
 852    s=(unz_s*)file;
 853    if (!s->current_file_ok)
 854        return UNZ_END_OF_LIST_OF_FILE;
 855
 856    /* Save the current state */
 857    num_fileSaved = s->num_file;
 858    pos_in_central_dirSaved = s->pos_in_central_dir;
 859    cur_file_infoSaved = s->cur_file_info;
 860    cur_file_info_internalSaved = s->cur_file_info_internal;
 861
 862    err = unzGoToFirstFile(file);
 863
 864    while (err == UNZ_OK)
 865    {
 866        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
 867        err = unzGetCurrentFileInfo(file,NULL,
 868                                    szCurrentFileName,sizeof(szCurrentFileName)-1,
 869                                    NULL,0,NULL,0);
 870        if (err == UNZ_OK)
 871        {
 872            if (unzStringFileNameCompare(szCurrentFileName,
 873                                            szFileName,iCaseSensitivity)==0)
 874                return UNZ_OK;
 875            err = unzGoToNextFile(file);
 876        }
 877    }
 878
 879    /* We failed, so restore the state of the 'current file' to where we
 880     * were.
 881     */
 882    s->num_file = num_fileSaved ;
 883    s->pos_in_central_dir = pos_in_central_dirSaved ;
 884    s->cur_file_info = cur_file_infoSaved;
 885    s->cur_file_info_internal = cur_file_info_internalSaved;
 886    return err;
 887}
 888
 889
 890/*
 891///////////////////////////////////////////
 892// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
 893// I need random access
 894//
 895// Further optimization could be realized by adding an ability
 896// to cache the directory in memory. The goal being a single
 897// comprehensive file read to put the file I need in a memory.
 898*/
 899
 900/*
 901typedef struct unz_file_pos_s
 902{
 903    uLong pos_in_zip_directory;   // offset in file
 904    uLong num_of_file;            // # of file
 905} unz_file_pos;
 906*/
 907
 908extern int ZEXPORT unzGetFilePos(file, file_pos)
 909    unzFile file;
 910    unz_file_pos* file_pos;
 911{
 912    unz_s* s;
 913
 914    if (file==NULL || file_pos==NULL)
 915        return UNZ_PARAMERROR;
 916    s=(unz_s*)file;
 917    if (!s->current_file_ok)
 918        return UNZ_END_OF_LIST_OF_FILE;
 919
 920    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
 921    file_pos->num_of_file           = s->num_file;
 922
 923    return UNZ_OK;
 924}
 925
 926extern int ZEXPORT unzGoToFilePos(file, file_pos)
 927    unzFile file;
 928    unz_file_pos* file_pos;
 929{
 930    unz_s* s;
 931    int err;
 932
 933    if (file==NULL || file_pos==NULL)
 934        return UNZ_PARAMERROR;
 935    s=(unz_s*)file;
 936
 937    /* jump to the right spot */
 938    s->pos_in_central_dir = file_pos->pos_in_zip_directory;
 939    s->num_file           = file_pos->num_of_file;
 940
 941    /* set the current file */
 942    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
 943                                               &s->cur_file_info_internal,
 944                                               NULL,0,NULL,0,NULL,0);
 945    /* return results */
 946    s->current_file_ok = (err == UNZ_OK);
 947    return err;
 948}
 949
 950/*
 951// Unzip Helper Functions - should be here?
 952///////////////////////////////////////////
 953*/
 954
 955/*
 956  Read the local header of the current zipfile
 957  Check the coherency of the local header and info in the end of central
 958        directory about this file
 959  store in *piSizeVar the size of extra info in local header
 960        (filename and size of extra field data)
 961*/
 962local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
 963                                                    poffset_local_extrafield,
 964                                                    psize_local_extrafield)
 965    unz_s* s;
 966    uInt* piSizeVar;
 967    uLong *poffset_local_extrafield;
 968    uInt  *psize_local_extrafield;
 969{
 970    uLong uMagic,uData,uFlags;
 971    uLong size_filename;
 972    uLong size_extra_field;
 973    int err=UNZ_OK;
 974
 975    *piSizeVar = 0;
 976    *poffset_local_extrafield = 0;
 977    *psize_local_extrafield = 0;
 978
 979    if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
 980                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
 981        return UNZ_ERRNO;
 982
 983
 984    if (err==UNZ_OK) {
 985        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
 986            err=UNZ_ERRNO;
 987        else if (uMagic!=0x04034b50)
 988            err=UNZ_BADZIPFILE;
 989    }
 990
 991    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
 992        err=UNZ_ERRNO;
 993/*
 994    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
 995        err=UNZ_BADZIPFILE;
 996*/
 997    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
 998        err=UNZ_ERRNO;
 999
1000    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1001        err=UNZ_ERRNO;
1002    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1003        err=UNZ_BADZIPFILE;
1004
1005    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1006                         (s->cur_file_info.compression_method!=Z_DEFLATED))
1007        err=UNZ_BADZIPFILE;
1008
1009    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1010        err=UNZ_ERRNO;
1011
1012    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1013        err=UNZ_ERRNO;
1014    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1015                              ((uFlags & 8)==0))
1016        err=UNZ_BADZIPFILE;
1017
1018    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1019        err=UNZ_ERRNO;
1020    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1021                              ((uFlags & 8)==0))
1022        err=UNZ_BADZIPFILE;
1023
1024    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1025        err=UNZ_ERRNO;
1026    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1027                              ((uFlags & 8)==0))
1028        err=UNZ_BADZIPFILE;
1029
1030
1031    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1032        err=UNZ_ERRNO;
1033    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1034        err=UNZ_BADZIPFILE;
1035
1036    *piSizeVar += (uInt)size_filename;
1037
1038    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1039        err=UNZ_ERRNO;
1040    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1041                                    SIZEZIPLOCALHEADER + size_filename;
1042    *psize_local_extrafield = (uInt)size_extra_field;
1043
1044    *piSizeVar += (uInt)size_extra_field;
1045
1046    return err;
1047}
1048
1049/*
1050  Open for reading data the current file in the zipfile.
1051  If there is no error and the file is opened, the return value is UNZ_OK.
1052*/
1053extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1054    unzFile file;
1055    int* method;
1056    int* level;
1057    int raw;
1058    const char* password;
1059{
1060    int err=UNZ_OK;
1061    uInt iSizeVar;
1062    unz_s* s;
1063    file_in_zip_read_info_s* pfile_in_zip_read_info;
1064    uLong offset_local_extrafield;  /* offset of the local extra field */
1065    uInt  size_local_extrafield;    /* size of the local extra field */
1066#    ifndef NOUNCRYPT
1067    char source[12];
1068#    else
1069    if (password != NULL)
1070        return UNZ_PARAMERROR;
1071#    endif
1072
1073    if (file==NULL)
1074        return UNZ_PARAMERROR;
1075    s=(unz_s*)file;
1076    if (!s->current_file_ok)
1077        return UNZ_PARAMERROR;
1078
1079    if (s->pfile_in_zip_read != NULL)
1080        unzCloseCurrentFile(file);
1081
1082    if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1083                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1084        return UNZ_BADZIPFILE;
1085
1086    pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1087                                        ALLOC(sizeof(file_in_zip_read_info_s));
1088    if (pfile_in_zip_read_info==NULL)
1089        return UNZ_INTERNALERROR;
1090
1091    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1092    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1093    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1094    pfile_in_zip_read_info->pos_local_extrafield=0;
1095    pfile_in_zip_read_info->raw=raw;
1096
1097    if (pfile_in_zip_read_info->read_buffer==NULL)
1098    {
1099        TRYFREE(pfile_in_zip_read_info);
1100        return UNZ_INTERNALERROR;
1101    }
1102
1103    pfile_in_zip_read_info->stream_initialised=0;
1104
1105    if (method!=NULL)
1106        *method = (int)s->cur_file_info.compression_method;
1107
1108    if (level!=NULL)
1109    {
1110        *level = 6;
1111        switch (s->cur_file_info.flag & 0x06)
1112        {
1113          case 6 : *level = 1; break;
1114          case 4 : *level = 2; break;
1115          case 2 : *level = 9; break;
1116        }
1117    }
1118
1119    if ((s->cur_file_info.compression_method!=0) &&
1120        (s->cur_file_info.compression_method!=Z_DEFLATED))
1121        err=UNZ_BADZIPFILE;
1122
1123    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1124    pfile_in_zip_read_info->crc32=0;
1125    pfile_in_zip_read_info->compression_method =
1126            s->cur_file_info.compression_method;
1127    pfile_in_zip_read_info->filestream=s->filestream;
1128    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1129    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1130
1131    pfile_in_zip_read_info->stream.total_out = 0;
1132
1133    if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1134        (!raw))
1135    {
1136      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1137      pfile_in_zip_read_info->stream.zfree = (free_func)0;
1138      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1139      pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1140      pfile_in_zip_read_info->stream.avail_in = 0;
1141
1142      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1143      if (err == Z_OK)
1144        pfile_in_zip_read_info->stream_initialised=1;
1145      else
1146      {
1147        TRYFREE(pfile_in_zip_read_info);
1148        return err;
1149      }
1150        /* windowBits is passed < 0 to tell that there is no zlib header.
1151         * Note that in this case inflate *requires* an extra "dummy" byte
1152         * after the compressed stream in order to complete decompression and
1153         * return Z_STREAM_END.
1154         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1155         * size of both compressed and uncompressed data
1156         */
1157    }
1158    pfile_in_zip_read_info->rest_read_compressed =
1159            s->cur_file_info.compressed_size ;
1160    pfile_in_zip_read_info->rest_read_uncompressed =
1161            s->cur_file_info.uncompressed_size ;
1162
1163
1164    pfile_in_zip_read_info->pos_in_zipfile =
1165            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1166              iSizeVar;
1167
1168    pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1169
1170    s->pfile_in_zip_read = pfile_in_zip_read_info;
1171
1172#    ifndef NOUNCRYPT
1173    if (password != NULL)
1174    {
1175        int i;
1176        s->pcrc_32_tab = get_crc_table();
1177        init_keys(password,s->keys,s->pcrc_32_tab);
1178        if (ZSEEK(s->z_filefunc, s->filestream,
1179                  s->pfile_in_zip_read->pos_in_zipfile +
1180                     s->pfile_in_zip_read->byte_before_the_zipfile,
1181                  SEEK_SET)!=0)
1182            return UNZ_INTERNALERROR;
1183        if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1184            return UNZ_INTERNALERROR;
1185
1186        for (i = 0; i<12; i++)
1187            zdecode(s->keys,s->pcrc_32_tab,source[i]);
1188
1189        s->pfile_in_zip_read->pos_in_zipfile+=12;
1190        s->encrypted=1;
1191    }
1192#    endif
1193
1194
1195    return UNZ_OK;
1196}
1197
1198extern int ZEXPORT unzOpenCurrentFile (file)
1199    unzFile file;
1200{
1201    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1202}
1203
1204extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1205    unzFile file;
1206    const char* password;
1207{
1208    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1209}
1210
1211extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1212    unzFile file;
1213    int* method;
1214    int* level;
1215    int raw;
1216{
1217    return unzOpenCurrentFile3(file, method, level, raw, NULL);
1218}
1219
1220/*
1221  Read bytes from the current file.
1222  buf contain buffer where data must be copied
1223  len the size of buf.
1224
1225  return the number of byte copied if somes bytes are copied
1226  return 0 if the end of file was reached
1227  return <0 with error code if there is an error
1228    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1229*/
1230extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1231    unzFile file;
1232    voidp buf;
1233    unsigned len;
1234{
1235    int err=UNZ_OK;
1236    uInt iRead = 0;
1237    unz_s* s;
1238    file_in_zip_read_info_s* pfile_in_zip_read_info;
1239    if (file==NULL)
1240        return UNZ_PARAMERROR;
1241    s=(unz_s*)file;
1242    pfile_in_zip_read_info=s->pfile_in_zip_read;
1243
1244    if (pfile_in_zip_read_info==NULL)
1245        return UNZ_PARAMERROR;
1246
1247
1248    if ((pfile_in_zip_read_info->read_buffer == NULL))
1249        return UNZ_END_OF_LIST_OF_FILE;
1250    if (len==0)
1251        return 0;
1252
1253    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1254
1255    pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1256
1257    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1258        (!(pfile_in_zip_read_info->raw)))
1259        pfile_in_zip_read_info->stream.avail_out =
1260            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1261
1262    if ((len>pfile_in_zip_read_info->rest_read_compressed+
1263           pfile_in_zip_read_info->stream.avail_in) &&
1264         (pfile_in_zip_read_info->raw))
1265        pfile_in_zip_read_info->stream.avail_out =
1266            (uInt)pfile_in_zip_read_info->rest_read_compressed+
1267            pfile_in_zip_read_info->stream.avail_in;
1268
1269    while (pfile_in_zip_read_info->stream.avail_out>0)
1270    {
1271        if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1272            (pfile_in_zip_read_info->rest_read_compressed>0))
1273        {
1274            uInt uReadThis = UNZ_BUFSIZE;
1275            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1276                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1277            if (uReadThis == 0)
1278                return UNZ_EOF;
1279            if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1280                      pfile_in_zip_read_info->filestream,
1281                      pfile_in_zip_read_info->pos_in_zipfile +
1282                         pfile_in_zip_read_info->byte_before_the_zipfile,
1283                         ZLIB_FILEFUNC_SEEK_SET)!=0)
1284                return UNZ_ERRNO;
1285            if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1286                      pfile_in_zip_read_info->filestream,
1287                      pfile_in_zip_read_info->read_buffer,
1288                      uReadThis)!=uReadThis)
1289                return UNZ_ERRNO;
1290
1291
1292#            ifndef NOUNCRYPT
1293            if(s->encrypted)
1294            {
1295                uInt i;
1296                for(i=0;i<uReadThis;i++)
1297                  pfile_in_zip_read_info->read_buffer[i] =
1298                      zdecode(s->keys,s->pcrc_32_tab,
1299                              pfile_in_zip_read_info->read_buffer[i]);
1300            }
1301#            endif
1302
1303
1304            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1305
1306            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1307
1308            pfile_in_zip_read_info->stream.next_in =
1309                (Bytef*)pfile_in_zip_read_info->read_buffer;
1310            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1311        }
1312
1313        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1314        {
1315            uInt uDoCopy,i ;
1316
1317            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1318                (pfile_in_zip_read_info->rest_read_compressed == 0))
1319                return (iRead==0) ? UNZ_EOF : iRead;
1320
1321            if (pfile_in_zip_read_info->stream.avail_out <
1322                            pfile_in_zip_read_info->stream.avail_in)
1323                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1324            else
1325                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1326
1327            for (i=0;i<uDoCopy;i++)
1328                *(pfile_in_zip_read_info->stream.next_out+i) =
1329                        *(pfile_in_zip_read_info->stream.next_in+i);
1330
1331            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1332                                pfile_in_zip_read_info->stream.next_out,
1333                                uDoCopy);
1334            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1335            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1336            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1337            pfile_in_zip_read_info->stream.next_out += uDoCopy;
1338            pfile_in_zip_read_info->stream.next_in += uDoCopy;
1339            pfile_in_zip_read_info->stream.total_out += uDoCopy;
1340            iRead += uDoCopy;
1341        }
1342        else
1343        {
1344            uLong uTotalOutBefore,uTotalOutAfter;
1345            const Bytef *bufBefore;
1346            uLong uOutThis;
1347            int flush=Z_SYNC_FLUSH;
1348
1349            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1350            bufBefore = pfile_in_zip_read_info->stream.next_out;
1351
1352            /*
1353            if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1354                     pfile_in_zip_read_info->stream.avail_out) &&
1355                (pfile_in_zip_read_info->rest_read_compressed == 0))
1356                flush = Z_FINISH;
1357            */
1358            err=inflate(&pfile_in_zip_read_info->stream,flush);
1359
1360            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1361              err = Z_DATA_ERROR;
1362
1363            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1364            uOutThis = uTotalOutAfter-uTotalOutBefore;
1365
1366            pfile_in_zip_read_info->crc32 =
1367                crc32(pfile_in_zip_read_info->crc32,bufBefore,
1368                        (uInt)(uOutThis));
1369
1370            pfile_in_zip_read_info->rest_read_uncompressed -=
1371                uOutThis;
1372
1373            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1374
1375            if (err==Z_STREAM_END)
1376                return (iRead==0) ? UNZ_EOF : iRead;
1377            if (err!=Z_OK)
1378                break;
1379        }
1380    }
1381
1382    if (err==Z_OK)
1383        return iRead;
1384    return err;
1385}
1386
1387
1388/*
1389  Give the current position in uncompressed data
1390*/
1391extern z_off_t ZEXPORT unztell (file)
1392    unzFile file;
1393{
1394    unz_s* s;
1395    file_in_zip_read_info_s* pfile_in_zip_read_info;
1396    if (file==NULL)
1397        return UNZ_PARAMERROR;
1398    s=(unz_s*)file;
1399    pfile_in_zip_read_info=s->pfile_in_zip_read;
1400
1401    if (pfile_in_zip_read_info==NULL)
1402        return UNZ_PARAMERROR;
1403
1404    return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1405}
1406
1407
1408/*
1409  return 1 if the end of file was reached, 0 elsewhere
1410*/
1411extern int ZEXPORT unzeof (file)
1412    unzFile file;
1413{
1414    unz_s* s;
1415    file_in_zip_read_info_s* pfile_in_zip_read_info;
1416    if (file==NULL)
1417        return UNZ_PARAMERROR;
1418    s=(unz_s*)file;
1419    pfile_in_zip_read_info=s->pfile_in_zip_read;
1420
1421    if (pfile_in_zip_read_info==NULL)
1422        return UNZ_PARAMERROR;
1423
1424    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1425        return 1;
1426    else
1427        return 0;
1428}
1429
1430
1431
1432/*
1433  Read extra field from the current file (opened by unzOpenCurrentFile)
1434  This is the local-header version of the extra field (sometimes, there is
1435    more info in the local-header version than in the central-header)
1436
1437  if buf==NULL, it return the size of the local extra field that can be read
1438
1439  if buf!=NULL, len is the size of the buffer, the extra header is copied in
1440    buf.
1441  the return value is the number of bytes copied in buf, or (if <0)
1442    the error code
1443*/
1444extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1445    unzFile file;
1446    voidp buf;
1447    unsigned len;
1448{
1449    unz_s* s;
1450    file_in_zip_read_info_s* pfile_in_zip_read_info;
1451    uInt read_now;
1452    uLong size_to_read;
1453
1454    if (file==NULL)
1455        return UNZ_PARAMERROR;
1456    s=(unz_s*)file;
1457    pfile_in_zip_read_info=s->pfile_in_zip_read;
1458
1459    if (pfile_in_zip_read_info==NULL)
1460        return UNZ_PARAMERROR;
1461
1462    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1463                pfile_in_zip_read_info->pos_local_extrafield);
1464
1465    if (buf==NULL)
1466        return (int)size_to_read;
1467
1468    if (len>size_to_read)
1469        read_now = (uInt)size_to_read;
1470    else
1471        read_now = (uInt)len ;
1472
1473    if (read_now==0)
1474        return 0;
1475
1476    if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1477              pfile_in_zip_read_info->filestream,
1478              pfile_in_zip_read_info->offset_local_extrafield +
1479              pfile_in_zip_read_info->pos_local_extrafield,
1480              ZLIB_FILEFUNC_SEEK_SET)!=0)
1481        return UNZ_ERRNO;
1482
1483    if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1484              pfile_in_zip_read_info->filestream,
1485              buf,read_now)!=read_now)
1486        return UNZ_ERRNO;
1487
1488    return (int)read_now;
1489}
1490
1491/*
1492  Close the file in zip opened with unzipOpenCurrentFile
1493  Return UNZ_CRCERROR if all the file was read but the CRC is not good
1494*/
1495extern int ZEXPORT unzCloseCurrentFile (file)
1496    unzFile file;
1497{
1498    int err=UNZ_OK;
1499
1500    unz_s* s;
1501    file_in_zip_read_info_s* pfile_in_zip_read_info;
1502    if (file==NULL)
1503        return UNZ_PARAMERROR;
1504    s=(unz_s*)file;
1505    pfile_in_zip_read_info=s->pfile_in_zip_read;
1506
1507    if (pfile_in_zip_read_info==NULL)
1508        return UNZ_PARAMERROR;
1509
1510
1511    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1512        (!pfile_in_zip_read_info->raw))
1513    {
1514        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1515            err=UNZ_CRCERROR;
1516    }
1517
1518
1519    TRYFREE(pfile_in_zip_read_info->read_buffer);
1520    pfile_in_zip_read_info->read_buffer = NULL;
1521    if (pfile_in_zip_read_info->stream_initialised)
1522        inflateEnd(&pfile_in_zip_read_info->stream);
1523
1524    pfile_in_zip_read_info->stream_initialised = 0;
1525    TRYFREE(pfile_in_zip_read_info);
1526
1527    s->pfile_in_zip_read=NULL;
1528
1529    return err;
1530}
1531
1532
1533/*
1534  Get the global comment string of the ZipFile, in the szComment buffer.
1535  uSizeBuf is the size of the szComment buffer.
1536  return the number of byte copied or an error code <0
1537*/
1538extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1539    unzFile file;
1540    char *szComment;
1541    uLong uSizeBuf;
1542{
1543    unz_s* s;
1544    uLong uReadThis ;
1545    if (file==NULL)
1546        return UNZ_PARAMERROR;
1547    s=(unz_s*)file;
1548
1549    uReadThis = uSizeBuf;
1550    if (uReadThis>s->gi.size_comment)
1551        uReadThis = s->gi.size_comment;
1552
1553    if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1554        return UNZ_ERRNO;
1555
1556    if (uReadThis>0)
1557    {
1558      *szComment='\0';
1559      if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1560        return UNZ_ERRNO;
1561    }
1562
1563    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1564        *(szComment+s->gi.size_comment)='\0';
1565    return (int)uReadThis;
1566}
1567
1568/* Additions by RX '2004 */
1569extern uLong ZEXPORT unzGetOffset (file)
1570    unzFile file;
1571{
1572    unz_s* s;
1573
1574    if (file==NULL)
1575          return UNZ_PARAMERROR;
1576    s=(unz_s*)file;
1577    if (!s->current_file_ok)
1578      return 0;
1579    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1580      if (s->num_file==s->gi.number_entry)
1581         return 0;
1582    return s->pos_in_central_dir;
1583}
1584
1585extern int ZEXPORT unzSetOffset (file, pos)
1586        unzFile file;
1587        uLong pos;
1588{
1589    unz_s* s;
1590    int err;
1591
1592    if (file==NULL)
1593        return UNZ_PARAMERROR;
1594    s=(unz_s*)file;
1595
1596    s->pos_in_central_dir = pos;
1597    s->num_file = s->gi.number_entry;      /* hack */
1598    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1599                                              &s->cur_file_info_internal,
1600                                              NULL,0,NULL,0,NULL,0);
1601    s->current_file_ok = (err == UNZ_OK);
1602    return err;
1603}