⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unzip.c

📁 HEG是一个易用的强大的硬件加速2D游戏引擎 他完全具备了具有开发商业质量的2D游戏的中层引擎
💻 C
📖 第 1 页 / 共 3 页
字号:
/* unzip.c -- IO for uncompress .zip files using zlib
Version 1.01, May 8th, 2004

Copyright (C) 1998-2004 Gilles Vollant

Read unzip.h for more info
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
#include "unzip.h"

#ifdef STDC
  #include <stddef.h>
  #include <string.h>
  #include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
  extern int errno;
#else
  #include <errno.h>
#endif

/* compile with -Dlocal if your debugger can't find static symbols */


#ifndef CASESENSITIVITYDEFAULT_NO
  #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
    #define CASESENSITIVITYDEFAULT_NO
  #endif
#endif


#ifndef UNZ_BUFSIZE
  #define UNZ_BUFSIZE (32768)
#endif

#ifndef UNZ_MAXFILENAMEINZIP
  #define UNZ_MAXFILENAMEINZIP (256)
#endif

#ifndef ALLOC
  #define ALLOC(size) (malloc(size))
#endif
#ifndef TRYFREE
  #define TRYFREE(p) {if (p) free(p);}
#endif

#define SIZECENTRALDIRITEM (0x2e)
#define SIZEZIPLOCALHEADER (0x1e)

/* unz_file_info_interntal contain internal info about a file in zipfile*/

typedef struct unz_file_info_internal_s
{
  DWORD offset_curfile; /* relative offset of local header 4 bytes */
} unz_file_info_internal;


/* file_in_zip_read_info_s contain internal information about a file in zipfile,
when reading and decompress it */

typedef struct
{
  char *read_buffer; /* internal buffer for compressed data */
  z_stream stream; /* zLib stream structure for inflate */
  DWORD pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
  DWORD stream_initialised; /* flag set if stream structure is initialised*/
  DWORD offset_local_extrafield; /* offset of the local extra field */
  DWORD size_local_extrafield; /* size of the local extra field */
  DWORD pos_local_extrafield; /* position in the local extra field in read*/
  DWORD crc32; /* crc32 of all data uncompressed */
  DWORD crc32_wait; /* crc32 we must obtain after decompress all */
  DWORD rest_read_compressed; /* number of byte to be decompressed */
  DWORD rest_read_uncompressed; /*number of byte to be obtained after decomp*/
  zlib_filefunc_def z_filefunc;
  void *filestream; /* io structore of the zipfile */
  DWORD compression_method; /* compression method (0==store) */
  DWORD byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
  int raw;
} file_in_zip_read_info_s;


/* unz_s contain internal information about the zipfile
 */
typedef struct
{
  zlib_filefunc_def z_filefunc;
  void *filestream; /* io structore of the zipfile */
  unz_global_info gi; /* public global information */
  DWORD byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
  DWORD num_file; /* number of the current file in the zipfile*/
  DWORD pos_in_central_dir; /* pos of the current file in the central dir*/
  DWORD current_file_ok; /* flag about the usability of the current file*/
  DWORD central_pos; /* position of the beginning of the central dir*/
  DWORD size_central_dir; /* size of the central directory  */
  DWORD offset_central_dir; /* offset of start of central directory with respect to the starting disk number */
  unz_file_info cur_file_info; /* public info about the current file in zip*/
  unz_file_info_internal cur_file_info_internal; /* private info about it*/
  file_in_zip_read_info_s *pfile_in_zip_read; /* structure about the current file if we are decompressing it */
  int encrypted;

  #ifndef NOUNCRYPT
    DWORD keys[3]; /* keys defining the pseudo-random sequence */
    const DWORD *pcrc_32_tab;
  #endif

} unz_s;


#ifndef NOUNCRYPT
  #include "crypt.h"
#endif

/* ===========================================================================
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
for end of file.
IN assertion: the stream s has been sucessfully opened for reading.
 */


static int unzlocal_getByte(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream, int *pi)
{
  BYTE c;
  int err = (int)ZREAD(*pzlib_filefunc_def, filestream, &c, 1);

  if (err == 1)
  {
    *pi = (int)c;
    return UNZ_OK;
  }
  else
  {
    if (ZERROR(*pzlib_filefunc_def, filestream))
    {
      return UNZ_ERRNO;
    }
    else
    {
      return UNZ_EOF;
    }
  }
}


/* ===========================================================================
Reads a long in LSB order from the given gz_stream. Sets
 */

static int unzlocal_getShort(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream, DWORD *pX)
{
  DWORD x;
  int i;
  int err;

  err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);

  x = (DWORD)i;

  if (err == UNZ_OK)
  {
    err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
  }

  x += ((DWORD)i) << 8;

  if (err == UNZ_OK)
  {
    *pX = x;
  }
  else
  {
    *pX = 0;
  }

  return err;
}

//-------------------------------------------------------------------------


static int unzlocal_getLong(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream, DWORD *pX)
{
  DWORD x;
  int i;
  int err;

  err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
  x = (DWORD)i;

  if (err == UNZ_OK)
  {
    err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
  }
  x += ((DWORD)i) << 8;

  if (err == UNZ_OK)
  {
    err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
  }
  x += ((DWORD)i) << 16;

  if (err == UNZ_OK)
  {
    err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
  }
  x += ((DWORD)i) << 24;

  if (err == UNZ_OK)
  {
    *pX = x;
  }
  else
  {
    *pX = 0;
  }
  return err;
}


//-------------------------------------------------------------------------


#ifdef CASESENSITIVITYDEFAULT_NO
  #define CASESENSITIVITYDEFAULTVALUE 2
#else
  #define CASESENSITIVITYDEFAULTVALUE 1
#endif

#ifndef STRCMPCASENOSENTIVEFUNCTION
  #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
#endif

/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
or strcasecmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
/*
extern int ZEXPORT unzStringFileNameCompare(const char *fileName1, const char *fileName2, int iCaseSensitivity)
{
  if (iCaseSensitivity == 0)
  {
    iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE;
  }

  if (iCaseSensitivity == 1)
  {
    return strcmp(fileName1, fileName2);
  }

  return stricmp(fileName1, fileName2);
}
*/
//-------------------------------------------------------------------------

#ifndef BUFREADCOMMENT
  #define BUFREADCOMMENT (0x400)
#endif

/*
Locate the Central directory of a zipfile (at the end, just before
the global comment)
 */

static DWORD unzlocal_SearchCentralDir(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream)
{
  BYTE *buf;
  DWORD uSizeFile;
  DWORD uBackRead;
  DWORD uMaxBack = 0xffff; /* maximum size of global comment */
  DWORD uPosFound = 0;

  if (ZSEEK(*pzlib_filefunc_def, filestream, 0, SEEK_END) != 0)
  {
    return 0;
  }


  uSizeFile = ZTELL(*pzlib_filefunc_def, filestream);

  if (uMaxBack > uSizeFile)
  {
    uMaxBack = uSizeFile;
  }

  buf = (BYTE*)ALLOC(BUFREADCOMMENT + 4);
  if (buf == NULL)
  {
    return 0;
  }

  uBackRead = 4;
  while (uBackRead < uMaxBack)
  {
    DWORD uReadSize, uReadPos;
    int i;
    if (uBackRead + BUFREADCOMMENT > uMaxBack)
    {
      uBackRead = uMaxBack;
    }
    else
    {
      uBackRead += BUFREADCOMMENT;
    }
    uReadPos = uSizeFile - uBackRead;

    uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4): (uSizeFile - uReadPos);
    if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos, SEEK_SET) != 0)
    {
      break;
    }

    if (ZREAD(*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
    {
      break;
    }

    for (i = (int)uReadSize - 3; (i--) > 0;)
    if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06))
    {
      uPosFound = uReadPos + i;
      break;
    }

    if (uPosFound != 0)
    {
      break;
    }
  }
  TRYFREE(buf);
  return uPosFound;
}

/*
Open a Zip file. path contain the full pathname (by example,
on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
"zlib/zlib114.zip".
If the zipfile cannot be opened (file doesn't exist or in not valid), the
return value is NULL.
Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
 */
extern unzFile ZEXPORT unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def)
{
  unz_s us;
  unz_s *s;
  DWORD central_pos, uL;

  DWORD number_disk; /* number of the current dist, used for
  spaning ZIP, unsupported, always 0*/
  DWORD number_disk_with_CD; /* number the the disk with central dir, used
  for spaning ZIP, unsupported, always 0*/
  DWORD number_entry_CD; /* total number of entries in
  the central dir
  (same than number_entry on nospan) */

  int err = UNZ_OK;

  if (pzlib_filefunc_def == NULL)
  {
    fill_fopen_filefunc(&us.z_filefunc);
  }
  else
  {
    us.z_filefunc =  *pzlib_filefunc_def;
  }

  us.filestream = (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
  if (us.filestream == NULL)
  {
    return NULL;
  }

  central_pos = unzlocal_SearchCentralDir(&us.z_filefunc, us.filestream);
  if (central_pos == 0)
  {
    err = UNZ_ERRNO;
  }

  if (ZSEEK(us.z_filefunc, us.filestream, central_pos, SEEK_SET) != 0)
  {
    err = UNZ_ERRNO;
  }

  /* the signature, already checked */
  if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  /* number of this disk */
  if (unzlocal_getShort(&us.z_filefunc, us.filestream, &number_disk) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  /* number of the disk with the start of the central directory */
  if (unzlocal_getShort(&us.z_filefunc, us.filestream, &number_disk_with_CD) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  /* total number of entries in the central dir on this disk */
  if (unzlocal_getShort(&us.z_filefunc, us.filestream, &us.gi.number_entry) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  /* total number of entries in the central dir */
  if (unzlocal_getShort(&us.z_filefunc, us.filestream, &number_entry_CD) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  if ((number_entry_CD != us.gi.number_entry) || (number_disk_with_CD != 0) || (number_disk != 0))
  {
    err = UNZ_BADZIPFILE;
  }

  /* size of the central directory */
  if (unzlocal_getLong(&us.z_filefunc, us.filestream, &us.size_central_dir) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  /* offset of start of central directory with respect to the
  starting disk number */
  if (unzlocal_getLong(&us.z_filefunc, us.filestream, &us.offset_central_dir) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  /* zipfile comment length */
  if (unzlocal_getShort(&us.z_filefunc, us.filestream, &us.gi.size_comment) != UNZ_OK)
  {
    err = UNZ_ERRNO;
  }

  if ((central_pos < us.offset_central_dir + us.size_central_dir) && (err == UNZ_OK))
  {
    err = UNZ_BADZIPFILE;
  }

  if (err != UNZ_OK)
  {
    ZCLOSE(us.z_filefunc, us.filestream);
    return NULL;
  }

  us.byte_before_the_zipfile = central_pos - (us.offset_central_dir + us.size_central_dir);
  us.central_pos = central_pos;
  us.pfile_in_zip_read = NULL;
  us.encrypted = 0;


  s = (unz_s*)ALLOC(sizeof(unz_s));
  *s = us;
  unzGoToFirstFile((unzFile)s);
  return (unzFile)s;
}

//-------------------------------------------------------------------------


extern unzFile ZEXPORT unzOpen(const char *path)
{
  return unzOpen2(path, NULL);
}

/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */

extern int ZEXPORT unzClose(unzFile file)
{
  unz_s *s;

  if (file == NULL)
  {
    return UNZ_PARAMERROR;
  }
  s = (unz_s*)file;

  if (s->pfile_in_zip_read != NULL)
  {
    unzCloseCurrentFile(file);
  }

  ZCLOSE(s->z_filefunc, s->filestream);
  TRYFREE(s);
  return UNZ_OK;
}


/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
/*
extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info)
{
  unz_s *s;

  if (file == NULL)
  {
    return UNZ_PARAMERROR;
  }

  s = (unz_s*)file;
  *pglobal_info = s->gi;
  return UNZ_OK;
}
*/

/*
Translate date/time from Dos format to tm_unz (readable more easilty)
 */

static void unzlocal_DosDateToTmuDate(DWORD ulDosDate, tm_unz *ptm)
{
  DWORD uDate;
  uDate = (DWORD)(ulDosDate >> 16);
  ptm->tm_mday = (DWORD)(uDate &0x1f);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -