Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include <shellapi.h>
  4. #include <stdlib.h>
  5. #include "DZRaw.h"
  6. #include "ZipOp.h"
  7. #include "ZipFnc.h"
  8. #include "dz_errs.h"
  9.  
  10. #undef _DZ_FILE_
  11. #define _DZ_FILE_ DZ_ZIPFILE_CPP
  12.  
  13. /* ZipFile.c Copyright (C) 1990-1996
  14.    Mark Adler, Richard B. Wales, Jean-loup Gailly, Kai Uwe Rommel,
  15.    Onno van der Linden and Igor Mandrichenko.
  16.    This version modified by Chris Vleghert and Eric Engler for BCB/Delphi Zip.
  17.   * distributed under LGPL license ** see license.txt for details
  18.  
  19.   Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
  20.  
  21.   See the accompanying file LICENSE, version 2007-Mar-4 or later
  22.   (the contents of which are also included in zip.h) for terms of use.
  23.   If, for some reason, all these files are missing, the Info-ZIP license
  24.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  25.  
  26.   parts Copyright (C) 1997 Mike White, Eric W. Engler
  27. ************************************************************************
  28.  Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
  29.  
  30.    This file is part of TZipMaster Version 1.9.
  31.  
  32.     TZipMaster is free software: you can redistribute it and/or modify
  33.     it under the terms of the GNU Lesser General Public License as published by
  34.     the Free Software Foundation, either version 3 of the License, or
  35.     (at your option) any later version.
  36.  
  37.     TZipMaster is distributed in the hope that it will be useful,
  38.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  39.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40.     GNU Lesser General Public License for more details.
  41.  
  42.     You should have received a copy of the GNU Lesser General Public License
  43.     along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
  44.  
  45.     contact: problems@delphizip.org (include ZipMaster in the subject).
  46.     updates: http://www.delphizip.org
  47.     DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
  48. ************************************************************************/
  49. #include "direct.h"
  50.  
  51. // -- Structure of a ZIP file --
  52. // Signatures for zip file information headers
  53. #define LOCSIG    0x04034b50L
  54. #define CENSIG    0x02014b50L
  55. #define ENDSIG    0x06054b50L
  56. #define EXTLOCSIG 0x08074b50L
  57.  
  58. // Added R. Aelbrecht for OEM2ISO conversion
  59. #define cpAUTO    0
  60. #define cpISO     1
  61. #define cpOEM     2
  62.  
  63. #define FS_FAT_   0                   // filesystem used by MS-DOS, OS/2, Win32
  64. #define FS_HPFS_  6                   // filesystem used by OS/2, NT
  65. #define FS_NTFS_  11                  // filesystem used by Windows NT
  66.  
  67.  
  68. // Return a pointer to the entry in zfile with the name n, or NULL if not
  69. //   found. n :: Name to find.
  70. ZipItem *ZipFunc::zsearch(const DZStrW &name)
  71. {
  72.     if (fzcount && fndlist)
  73.     {
  74.         ZipItem *x = (ZipItem*)fndlist->FindName(name);
  75.         return x;
  76.     }
  77.  
  78.     return NULL;
  79. }
  80.  
  81.  
  82. void ZipFunc::HWriteInit(void)
  83. {
  84.     if (!fhwbuf)
  85.         {
  86.         fhwsize = 4096;
  87.         fhwbuf = new unsigned char[fhwsize];
  88.     }
  89.  
  90.     LocXData = 0;
  91.  
  92.     fhwcnt = 0;
  93. }
  94.  
  95. // Write headers to a buffer
  96. // if arg == NULL then reset
  97. int ZipFunc::HWrite(const void *arg, int siz)
  98. {
  99.     if (!fhwbuf)
  100.     {
  101.         fhwcnt = -1;
  102.         return -1;
  103.     }
  104.  
  105.     // if error don't continue
  106.     if (fhwcnt < 0)
  107.     {
  108.         return -1;
  109.     }
  110.  
  111.     if (!arg || siz < 1)
  112.     {
  113.         return fhwcnt;
  114.     }
  115.  
  116.     while (fhwcnt + siz >= fhwsize)
  117.         {
  118.         unsigned char * b2 = new unsigned char [fhwsize + 4096];
  119.  
  120.         if (!b2)
  121.         {
  122.             fhwcnt = -1;
  123.             return -1;
  124.         }
  125.  
  126.         memmove(b2, fhwbuf, fhwcnt);
  127.  
  128.         delete[] fhwbuf;
  129.         fhwbuf = b2;
  130.         fhwsize += 4096;
  131.     }
  132.  
  133.     memmove(fhwbuf + fhwcnt, arg, siz);
  134.  
  135.     fhwcnt += siz;
  136.     return fhwcnt;
  137. }
  138.  
  139. #pragma pack(push, 1)
  140. struct XLocal
  141. {
  142.     WORD Tag;
  143.     WORD Siz;
  144.     __int64 usiz;
  145.     __int64 clen;
  146. };
  147. #pragma pack(pop)
  148.  
  149. #pragma pack(push, 1)
  150. struct XNTFS
  151. {
  152.     WORD Tag;
  153.     WORD Siz;
  154.     unsigned res;
  155.     WORD tg1;
  156.     WORD sz1;
  157. };
  158. #pragma pack(pop)
  159.  
  160. // Write a local header described by *z to file *f. Return DZ_ERR_GOOD or
  161. //   ZEN_TEMP07. z :: Zip entry to write local header for. f :: File to write
  162. //   to.
  163. int __fastcall ZipFunc::PutLocal(ZipItem *z)
  164. {
  165.     ush tag;
  166.     int npos;
  167.     unsigned long k;
  168.     ZipLocalHeader zlh;
  169.         DZRawData ox = z->extra;
  170.  
  171.     if (z->ntfs)
  172.         ox = ox - NTFS_STAMP_TAG;
  173.  
  174.     if (Verbose < 0)
  175.         Notify(ITRACE, _T("writing Local Header: %s"), z->iname);
  176.  
  177.     HWriteInit();   // reset
  178.  
  179.         unsigned short UFlag = 0;
  180.     if (z->Enc == zeoUTF8)
  181.         {
  182.         z->options.nameutf8 = 1;
  183.         UFlag = FLAG_UTF8_BIT;
  184.         }
  185.  
  186.         if (z->Enc >= zeoUTF8)
  187.                 z->vem = OUR_VEM;
  188.  
  189. #ifdef _FORCE_Z64_
  190.     z->ver = 45;
  191.     z->vem = OS_NTFS + 45;
  192. #endif
  193.     if (z->siz >= MAX_UNSIGNED)
  194.     {
  195.         z->ver = 45;            // need Zip64
  196.         z->vem = OS_NTFS + 45;
  197.     }
  198.  
  199.     // may have been truncated
  200.     z->nam = strlen(z->hname);
  201.  
  202.     if (z->nam > MAX_PATH)
  203.         z->nam = MAX_PATH;  // keep sane
  204.  
  205.         zlh.HeaderSig = LOCSIG; // Should be 0x04034B50
  206.     zlh.Flag = (WORD)(UFlag | z->lflg | ((z->options.level > 8) ? 2 : 0));
  207.     zlh.ComprMethod = z->how;
  208.     zlh.ModifStamp = z->tim;
  209.     zlh.CRC32 = z->crc;
  210.  
  211.     // allow for bad 'compression'
  212.     bool MakeX64 = (z->ver >= 45) || (z->len + 0x800) > MAX_UNSIGNED ||
  213.         (z->siz + 0x800) > MAX_UNSIGNED;
  214.  
  215.     if ((z->ver < 45) && (z->len >= MAX_UNSIGNED))
  216.     {
  217.         z->flg |= FLAG_EXTEND_BIT;        // use extended data for sizes
  218.         z->ver = 45;        // must be 64 bit
  219.         z->vem = OS_NTFS + 45;
  220.     }
  221.  
  222.     zlh.VersionNeed = (ush)z->ver;
  223.  
  224.     zlh.ComprSize = z->siz >= MAX_UNSIGNED ? MAX_UNSIGNED : (unsigned)z->siz;
  225.     zlh.UnComprSize = z->len >= MAX_UNSIGNED ? MAX_UNSIGNED : (unsigned)z->len;
  226.     zlh.FileNameLen = (ush)z->nam;
  227.     zlh.ExtraLen = 0;   // will be updated
  228.     HWrite(&zlh, sizeof(ZipLocalHeader));
  229.     HWrite(z->hname, z->nam);
  230.     LocXData = -1;
  231.     npos = fhwcnt;  // size without xtra data
  232.  
  233.     // write Zip64 data
  234.     if (MakeX64)
  235.     {
  236.         XLocal xl;
  237.         xl.Tag = ZIP64_XDATA_TAG;
  238.         xl.Siz = 16;
  239.         xl.usiz = z->siz;
  240.         xl.clen = 0;        // not known
  241.         HWrite(&xl, sizeof(xl));
  242.                 LocXData = npos;
  243.         ox -= ZIP64_XDATA_TAG;
  244.     }
  245.  
  246.         // save utf8 name if needed
  247.         if (z->options.enc == zeoUPATH && z->options.nameextd)
  248.     {
  249.         DZStrA unam = StrToUTF8(StrIntSep(z->IName));
  250.         unsigned ncrc = crc32(0, (uch*)z->hname, z->nam);
  251.         tag = UPATH_XDATA_TAG;   // Info-Zip Unicode Path
  252.         int sz = 5 + unam.length();
  253.         HWrite(&tag, 2);
  254.         HWrite(&sz, 2);
  255.         sz = 1; // version
  256.         HWrite(&sz, 1);
  257.         HWrite(&ncrc, 4);
  258.                 HWrite(unam.c_str(), unam.length());
  259.         ox = UPATH_XDATA_TAG;
  260.     }
  261.  
  262.     if (!ox.IsEmpty())
  263.         HWrite(ox, ox.Length());
  264.  
  265.     ((ZipLocalHeader *)fhwbuf)->ExtraLen = (ush)(fhwcnt - npos);
  266.  
  267.     if (fhwcnt <= 0
  268.             || !fZipOutfile->Write(fhwbuf, fhwcnt, &k)
  269.             || k != (unsigned)fhwcnt)
  270.                 return DZ_ERM_TEMP_FAILED;
  271.  
  272.     fBytesWritten += k;
  273.     fOutPosn += k;
  274.  
  275. //  if (Verbose < 0)
  276. //    Notify(IDIAG, "wrote Local Header: %s [%d]", z->name, k);
  277. //#ifdef ZDEBUG1
  278. //Notify(ITRACE, _T("writing Local Header: %s need %x made %x"), z->iname, z->ver, z->vem);
  279. //#endif
  280. #ifdef ZDEBUG
  281.     if (Verbose < 0)
  282.     {
  283.                 const ZipLocalHeader *zc = (ZipLocalHeader *)fhwbuf;
  284.                 Notify(ITRACE, _T("local %s need %x [%x]"), z->iname,
  285.                            zc->VersionNeed, z->ver);
  286.         }
  287. #endif
  288.     return DZ_ERR_GOOD;
  289. }
  290.  
  291. // Rewrite a local header described by *z to file *f. Return DZ_ERR_GOOD or
  292. //   ZEN_TEMP07. z :: Zip entry to write local header for. f :: File to write
  293. //   to.
  294. int __fastcall ZipFunc::UpdateLocal(ZipItem *z)
  295. {
  296.     unsigned long k;
  297.  
  298.     if (!LocXData || fhwcnt <= 0)
  299.     {
  300.         // something went wrong - local not written or old data missing
  301.         Notify(ITRACE, _T("error updating Local Header: %s"), z->iname);
  302.         return DZ_ERM_LOGIC_ERROR;
  303.     }
  304.  
  305.     if (Verbose < 0)
  306.         Notify(ITRACE, _T("updating Local Header: %s"), z->iname);
  307.  
  308.     bool is64 = z->siz >= MAX_UNSIGNED || z->len >= MAX_UNSIGNED;
  309.  
  310.     XLocal *pxd = 0;
  311.  
  312.     if (LocXData > 0)
  313.     {
  314.         pxd = (XLocal*) & fhwbuf[LocXData];
  315.  
  316.         if (pxd->Tag != ZIP64_XDATA_TAG)
  317.             pxd = 0;        // should not happen
  318.     }
  319.  
  320.     ZipLocalHeader *ploc = (ZipLocalHeader *)fhwbuf;
  321.  
  322.     ploc->ComprSize = (unsigned)z->siz;
  323.     ploc->UnComprSize = (unsigned)z->len;
  324.  
  325.     if (is64)
  326.     {
  327.         if (!pxd)
  328.         {
  329.             // cannot update without data
  330.             Notify(IWARNING, _T("error updating Local Header: %s"), z->iname);
  331.             return DZ_ERM_LOGIC_ERROR;
  332.         }
  333.  
  334.         z->ver = 45;        // must be 64 bit
  335.  
  336.         z->vem = OS_NTFS + 45;
  337.                 pxd->usiz = z->len;
  338.                 pxd->clen = z->siz;
  339.  
  340.         if (z->siz >= MAX_UNSIGNED)
  341.             ploc->ComprSize = MAX_UNSIGNED;
  342.  
  343.         if (z->len >= MAX_UNSIGNED)
  344.             ploc->UnComprSize = MAX_UNSIGNED;
  345.     }
  346.  
  347.     ploc->ComprMethod = z->how;  // may have changed
  348.  
  349.     if (z->ver < 45) //30)
  350.         z->ver = (ush)((z->how == STORE) ? 10 : 20);
  351.  
  352.     ploc->VersionNeed = (ush)z->ver;
  353.  
  354.     ploc->Flag = (ush)((ploc->Flag & FLAG_UTF8_BIT) | z->lflg |
  355.                     ((z->options.level > 8) ? 2 : 0));
  356.  
  357.     ploc->ModifStamp = z->tim;
  358.  
  359.     ploc->CRC32 = z->crc;
  360.  
  361.     if (!fZipOutfile->Write(fhwbuf, fhwcnt, &k)
  362.             || k != (unsigned)fhwcnt)
  363.                 return DZ_ERM_TEMP_FAILED;
  364.  
  365. //  if (Verbose < 0)
  366. //    Notify(IDIAG, "updated Local Header: %s", z->name);
  367.     return DZ_ERR_GOOD;
  368. }
  369.  
  370. // Write an extended local header described by *z to file *f. Return an
  371. //   error code in the ZEN_ class. z :: Zip entry to write local header for. f
  372. //   :: File to write to.
  373. int __fastcall ZipFunc::putextended(ZipItem *z)
  374. {
  375.     unsigned long k;
  376.     ZipDataDescriptor zdd;
  377.     ZipDataDescriptor64 zdd64;
  378.  
  379.     if (Verbose < 0)
  380.         Notify(ITRACE, _T("writing extended Local data: %s"), z->iname);
  381.  
  382.     if (z->ver >= 45)
  383.     {
  384.         zdd64.DataDescSig = EXTLOCSIG;
  385.         zdd64.CRC32 = z->crc;
  386.         zdd64.ComprSize = z->siz;
  387.                 zdd64.UnComprSize = z->len;
  388.                 if (!fZipOutfile->Write(&zdd64, sizeof(ZipDataDescriptor64), &k)
  389.                 || k != sizeof(ZipDataDescriptor64))
  390.                         return DZ_ERM_TEMP_FAILED;
  391.     }
  392.     else
  393.     {
  394.         zdd.DataDescSig = EXTLOCSIG;
  395.         zdd.CRC32 = z->crc;
  396.         zdd.ComprSize = (unsigned)z->siz;
  397.                 zdd.UnComprSize = (unsigned)z->len;
  398.                 if (!fZipOutfile->Write(&zdd, sizeof(ZipDataDescriptor), &k) ||
  399.                 k != sizeof(ZipDataDescriptor))
  400.                         return DZ_ERM_TEMP_FAILED;
  401.     }
  402.  
  403.     fBytesWritten += k;
  404.  
  405.     fOutPosn += k;
  406.     return DZ_ERR_GOOD;
  407. }
  408.  
  409. // Write a central header described by *z to file *f. Return an error code
  410. //   in the ZEN_ class. z :: Zip entry to write central header for. f :: File
  411. //   to write to.
  412. int __fastcall ZipFunc::putcentral(ZipItem *z)
  413. {
  414.     ush tag;
  415.     ush siz;
  416. #pragma pack(push, 1)
  417.     ZInt64 dat[3];
  418. #pragma pack(pop)
  419.     int xargs, npos;
  420.     unsigned long k;
  421.     ZipCentralHeader zch;
  422.         DZRawData ox = z->cextra;
  423.  
  424.     HWriteInit();   // reset
  425.  
  426.         tag = ZIP64_XDATA_TAG;
  427.     xargs = 0;
  428.  
  429.     zch.UnComprSize = z->len >= MAX_UNSIGNED ? MAX_UNSIGNED : (unsigned)z->len;
  430.     zch.ComprSize = z->siz >= MAX_UNSIGNED ? MAX_UNSIGNED : (unsigned)z->siz;
  431.     zch.RelOffLocal = z->off >= MAX_UNSIGNED ? MAX_UNSIGNED : (unsigned)z->off;
  432.  
  433.     if (zch.UnComprSize == MAX_UNSIGNED)
  434.         dat[xargs++] = z->len;  // uncompressed
  435.  
  436.     if (zch.ComprSize == MAX_UNSIGNED)
  437.         dat[xargs++] = z->siz;  // compressed
  438.  
  439.     if (zch.RelOffLocal == MAX_UNSIGNED)
  440.         dat[xargs++] = z->off;
  441.  
  442. #ifdef _FORCE_Z64_
  443.     if (!xargs)
  444.     {
  445.         zch.UnComprSize = MAX_UNSIGNED;
  446.         dat[xargs++] = z->len;  // uncompressed
  447.     }
  448. #endif
  449.     siz = (ush)(xargs ? (xargs << 3) : 0);
  450.  
  451.         unsigned short UFlag = 0;
  452.         DZStrA zcom;
  453. //      unsigned cp = z->options.dosflag ? CP_OEM : CP_ACP;
  454.         if (z->com)
  455.                 zcom = z->Comment.SafeNarrow(z->options.dosflag ? CP_OEM : CP_ACP);
  456. //              zcom = z->Comment.SafeAnsi();
  457.         bool ExtCom = z->options.cmntextd;
  458.  
  459.         if (ExtCom && z->Enc == zeoUTF8)
  460.     {
  461.         UFlag = FLAG_UTF8_BIT;
  462.         zcom = StrToUTF8(z->Comment);
  463.                 ExtCom = false;
  464. //              z->com = (ush) zcom.length();
  465.         }
  466.  
  467.     if (z->options.nameutf8)
  468.         UFlag = FLAG_UTF8_BIT;
  469.  
  470.         z->com = (ush) zcom.length();
  471.  
  472.     if (Verbose < 0)
  473.         Notify(ITRACE, _T("central [%d] %s"), xargs, z->iname);
  474.  
  475.     zch.HeaderSig = CENSIG;
  476.     zch.MadeBy = z->vem;
  477.     zch.VersionNeed = (ush)(xargs ? 45 : z->ver);
  478.     zch.Flag = (WORD)(z->flg | UFlag | ((z->options.level > 8) ? 2 : 0));
  479.     zch.ComprMethod = z->how;
  480.     zch.ModifStamp = z->tim;
  481.     zch.CRC32 = z->crc;
  482.     zch.FileNameLen = (ush)z->nam;
  483.     zch.ExtraLen = 0; // will update
  484. //    zch.FileComLen = (ush)zcom.Length();
  485.         zch.FileComLen = (ush)z->com;
  486.     zch.DiskStart = z->dsk;
  487.     zch.IntFileAtt = z->att;
  488.     zch.ExtFileAtt = z->atx;
  489.  
  490.     HWrite(&zch, sizeof(ZipCentralHeader));
  491.         HWrite(z->hname, zch.FileNameLen);
  492.     npos = fhwcnt;
  493.  
  494.     // write Zip64 extra data
  495.     if (xargs)
  496.     {
  497.         HWrite(&tag, 2);
  498.         HWrite(&siz, 2);
  499.                 HWrite(dat, siz);
  500.         ox -= ZIP64_XDATA_TAG;
  501.     }
  502.  
  503.     if (z->ntfs)
  504.     {
  505.         XNTFS xn;
  506.         xn.Tag = NTFS_STAMP_TAG;
  507.         xn.Siz = 32;
  508.         xn.res = 0;
  509.         xn.tg1 = 1;
  510.         xn.sz1 = 24;
  511.         HWrite(&xn, sizeof(xn));
  512.         HWrite(z->ntfs, 24);
  513.         ox = ox - NTFS_STAMP_TAG;
  514.     }
  515.  
  516.         // save utf8 name if needed
  517.     if (z->options.enc == zeoUPATH && z->options.nameextd)
  518.     {
  519.         DZStrA unam = StrToUTF8(StrIntSep(z->IName));
  520.         unsigned ncrc = crc32(0, (uch*)z->hname, z->nam);
  521.         tag = UPATH_XDATA_TAG;   // Info-Zip Unicode Path
  522.         int sz = 5 + unam.length();
  523.         HWrite(&tag, 2);
  524.         HWrite(&sz, 2);
  525.         sz = 1; // version
  526.         HWrite(&sz, 1);
  527.         HWrite(&ncrc, 4);
  528.                 HWrite(unam.c_str(), unam.length());
  529.         ox -= UPATH_XDATA_TAG;
  530.     }
  531.  
  532.         // UTF8 comment too
  533.         if (ExtCom && z->options.enc == zeoUPATH && z->options.cmntextd)
  534.     {
  535.         unsigned ncrc = crc32(0, (uch*)zcom.c_str(), zcom.length());
  536.                 DZStrA ucom = StrToUTF8(z->Comment);
  537.                 tag = UCMNT_XDATA_TAG;   // Info-Zip Unicode Comment
  538.         int sz = 5 + ucom.length();
  539.         HWrite(&tag, 2);
  540.         HWrite(&sz, 2);
  541.         sz = 1; // version
  542.         HWrite(&sz, 1);
  543.         HWrite(&ncrc, 4);
  544.                 HWrite(ucom, ucom.length());
  545.         ox -= UCMNT_XDATA_TAG;
  546.     }
  547.  
  548.     // write remaining 'old' extra data
  549.     if (!ox.IsEmpty())
  550.         HWrite(ox, ox.Length());
  551.  
  552.     ((ZipCentralHeader *)fhwbuf)->ExtraLen = (ush)(fhwcnt - npos);
  553.  
  554.     if (zch.FileComLen)
  555.                 HWrite(zcom.c_str(), zch.FileComLen);
  556.  
  557.     if (fhwcnt <= 0
  558.             || !fZipOutfile->Write(fhwbuf, fhwcnt, &k)
  559.             || k != (unsigned)fhwcnt)
  560.         return DZ_ERM_TEMP_FAILED;
  561.  
  562.     fBytesWritten += k;
  563.     fOutPosn += k;
  564.  
  565. #ifdef ZDEBUG
  566.         if (Verbose < 0)
  567.     {
  568.         const ZipCentralHeader *zc = (ZipCentralHeader *)fhwbuf;
  569.         Notify(ITRACE, _T("central %s-"), z->iname);
  570.                 Notify(ITRACE, _T(" made %x [%x] need %x [%x]"),
  571.                            zc->MadeBy, z->vem, zc->VersionNeed, z->ver);
  572.         }
  573. #endif
  574.     return DZ_ERR_GOOD;
  575. }
  576.  
  577. // Write the end of central directory data to file *f. Return DZ_ERR_GOOD or
  578. //   ZEN_TEMP09.
  579. //    n :: Number of entries in central directory.
  580. //    s :: Size of central directory.
  581. //    c :: Offset of central directory.
  582. //    f :: File to write to.
  583. int __fastcall ZipFunc::PutEnd(unsigned CentralCnt, __int64 CentralOffs) //, HANDLE f)
  584. {
  585.     ZipEndOfCentral eoc;
  586.     unsigned long k;
  587.     __int64 cz = fOutPosn - CentralOffs;
  588. //    Assert(fOutPosn == SetFilePointer64(fhOutz, 0, 2), _T("invalid out posn"));
  589.     HWriteInit();   // reset
  590. #ifndef _FORCE_Z64_
  591.  
  592.     if (CentralCnt >= MAXWORD || cz >= MAX_UNSIGNED || CentralOffs >= MAX_UNSIGNED)
  593. #endif
  594.     {
  595.         // make EOC64
  596.         ZipEOC64 e64;
  597.         Zip64EOCLocator loc;
  598.         e64.HeaderSig = EndCentral64Sig;
  599.         e64.vsize = sizeof(ZipEOC64) - 12;    // data size
  600.         e64.VersionMade = 45;
  601.         e64.VersionNeed = 45;
  602.         e64.ThisDiskNo = 0;
  603.         e64.CentralDiskNo = 0;
  604.         e64.CentralEntries = CentralCnt;
  605.         e64.TotalEntries = CentralCnt;
  606.         e64.CentralSize = cz;
  607.         e64.CentralOffSet = CentralOffs;
  608.         HWrite(&e64, sizeof(ZipEOC64));
  609.         // make EOC64Locator
  610.         loc.HeaderSig = EOC64LocatorSig;
  611.         loc.EOC64DiskStt = 0;
  612.         loc.EOC64RelOfs = fOutPosn;
  613.         loc.NumberDisks = 1;
  614.         HWrite(&loc, sizeof(Zip64EOCLocator));
  615.     }
  616.     eoc.HeaderSig = ENDSIG;
  617.     eoc.CentralDiskNo = eoc.ThisDiskNo = 0;
  618.  
  619.     if (CentralCnt < MAXWORD)
  620.     {
  621.         eoc.CentralEntries = (ush)CentralCnt;
  622.         eoc.TotalEntries = (ush)CentralCnt;
  623.     }
  624.     else
  625.     {
  626.         eoc.CentralEntries = (ush) - 1;
  627.         eoc.TotalEntries = (ush) - 1;
  628.     }
  629.  
  630.     if (cz < MAX_UNSIGNED)
  631.         eoc.CentralSize = (unsigned)cz;
  632.     else
  633.         eoc.CentralSize = (unsigned) - 1;
  634.  
  635.     if (CentralOffs < MAX_UNSIGNED)
  636.         eoc.CentralOffset = (unsigned)CentralOffs;
  637.     else
  638.         eoc.CentralOffset = (unsigned) - 1;
  639.  
  640. #ifdef _FORCE_Z64_
  641.     eoc.CentralOffset = (unsigned) - 1;
  642. #endif
  643.     eoc.ZipCommentLen = (ush)fzcomlen;
  644.  
  645.     HWrite(&eoc, sizeof(ZipEndOfCentral));
  646.  
  647.     if (eoc.ZipCommentLen)
  648.         HWrite(fzcomment, fzcomlen);
  649.  
  650.         if (fhwcnt <= 0
  651.                         || !fZipOutfile->Write(fhwbuf, fhwcnt, &k)
  652.             || k != (unsigned)fhwcnt)
  653.                 return DZ_ERM_TEMP_FAILED;
  654.  
  655.     fBytesWritten += k;
  656.     fOutPosn += k;
  657.  
  658.     return DZ_ERR_GOOD;
  659. }
  660.  
  661. // Note: a zip "entry" includes a local header (which includes the file
  662. //   name), an encryption header if encrypting, the compressed data and
  663. //   possibly an extended local header.
  664. // Copy the zip entry described by *z from file *x to file *y. Return an
  665. //   error code in the ZEN_ class. Also update tempzn by the number of bytes
  666. //   copied. z :: Zip entry to copy. x, *y :: Source and destination files.
  667. int __fastcall ZipFunc::zipcopy(ZipItem *z)
  668. {
  669.     ZInt64 n; // holds local header offset
  670.     //  Trace(("zipcopy %s\n", z->zname));
  671.     n = (ulg)(4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext;
  672.         // seek to local header
  673.     if (SetFilePointer64(fhInz, z->off, FILE_BEGIN) == -1)
  674.                 return DZ_ERM_ERROR_SEEK;
  675.  
  676.     z->off = fOutPosn;
  677.  
  678.     n += z->siz;
  679.  
  680.     // copy the compressed data and the extended local header if there is one
  681.     if (z->lflg & FLAG_EXTEND_BIT)
  682.         n += (z->ver >= 45 ? 20 : 16);
  683.  
  684.     fOutPosn += n;
  685.         CB->UserItem(n, z->IName);
  686.  
  687. //    return fcopy(n);
  688.         int err = fcopy(n);
  689.         /* TODO 1 -oRP -cenhancement : Finished Item */
  690.         return err;
  691. }
  692.  
  693. //-------------------------------------------------------------------------
  694.  
  695.  
  696. int ZipFunc::TrashDir(const DZStrW &dir)
  697. {
  698.     DZStrW tmp = StrExcSep(dir);
  699.  
  700.     if (tmp.IsEmpty())
  701.                 return -1;
  702.  
  703.     if (Verbose)
  704.         Notify(IVERBOSE, _T("trashing directory %s (if empty)"), tmp.c_str());
  705.  
  706.     int err = EraseFile(tmp, fHowToMove);
  707.     if (err && Verbose < 0)
  708.           Notify(IWARNING, _T("error deleting %s {%x}"), tmp.c_str(), err);
  709.  
  710.     return 0;
  711. }
  712.  
  713.  
  714. // Used by qsort() to compare entries in the zfile list. Compare the
  715. //   strings in reverse order. a, *b :: char *
  716. static int rcmp(const void *a, const void *b)
  717. {
  718.         return _tcscmp(*(const TCHAR**)b, *(const TCHAR**)a);
  719. }
  720.  
  721. // Delete the compressed files and the directories that contained the
  722. //   deleted files, if empty. Return an error code in the ZEN_ class. Failure
  723. //   of destroy() or rmdir() is ignored.
  724. int ZipFunc::trash(void)
  725. {
  726.     int i; // counter on deleted names
  727.         int n; // number of directories to delete
  728.     ZipItem *z, *prv = NULL; // current zip entry
  729.     // Delete marked names and count directories
  730.     n = 0;
  731.  
  732.     for (z = fzfiles; z != NULL; z = z->nxt)
  733.     {
  734.         if (z->mark == 1 || z->trash)
  735.         {
  736.             z->mark = 1;
  737.             DZStrW f = z->FullPath();
  738.             if (!z->IsFolder)
  739.             {
  740.                 // don't unlink directory SLASH
  741.                 if (Verbose)
  742.                     Notify(IVERBOSE, _T("deleting file %s"), f.c_str());
  743.  
  744.                 int err = EraseFile(f, fHowToMove);
  745.                 if (err && Verbose < 0)
  746.                                         Notify(IWARNING, _T("error deleting %s {%x}"), f.c_str(), err);
  747.  
  748.                 // Try to delete all paths that lead up to marked names. This is
  749.                 //   necessary only with the -D option.
  750.                 if (!fdirnames)
  751.                 {
  752.                     diag(_T("no dirnames will be kept"));
  753.                     DZStrW pth = z->xname;
  754.                                         int ls = pth.ReverseFind(_T('\\'));
  755.                     if (ls > 0)
  756.                     {
  757.                         pth = pth.Left(ls);   // only leave prev folders
  758.                                                 // remove a lot of duplicates
  759.                         if (prv && ZMatch(prv->xname, pth))
  760.                             z->mark = 0;   // ignore same path
  761.                         else
  762.                             z->xname = pth.c_str();
  763.                     }
  764.                     else
  765.                     {
  766.                         z->mark = 0;   // done with it
  767.                         z->xname = NULL;  // free up
  768.                     }
  769.                 }
  770.             }
  771.         }
  772.  
  773.         // is it directory we want to remove?
  774.         if (z->mark)
  775.         {
  776.             n++;
  777.             prv = z;
  778.         }
  779.     }
  780.  
  781.     if (n == 1 && prv)
  782.     {
  783.         TrashDir(prv->FullPath());
  784.         n = 0;
  785.     }
  786.  
  787.     if (n)
  788.     {
  789.         // Construct the list of all marked directories. Some may be duplicated if
  790.         //   -D was used.
  791.         TCHAR **dlist;       // for sorting
  792.         typedef TCHAR* PTChar;
  793.         dlist = new PTChar[n];
  794.  
  795.         int dcnt = 0;
  796.         for (z = fzfiles; z != NULL; z = z->nxt)
  797.         {
  798.                         if (z->mark  && dcnt < n)
  799.                         {
  800.                 if (_tcslen(z->xname) < 1)
  801.                     continue;
  802.  
  803.                 DZStrW fullpth = z->FullPath();
  804.                 const TCHAR *fp = fullpth.c_str();
  805.                                 int dlen = _tcslen(fp);
  806.                 TCHAR *dn = new TCHAR[dlen + 1];
  807.  
  808.                 if (!dn)
  809.                     break;   // keep safe
  810.  
  811.                 TCHAR *d = dn;
  812.  
  813.                 for (int i = 0; i < dlen; i++)
  814.                     *d++ = (TCHAR)_totupper(*fp++);
  815.  
  816.                 *d = 0;
  817.                 if (dcnt == 0 || !ZMatch(dn, dlist[dcnt - 1]))
  818.                     dlist[dcnt++] = dn;
  819.                 else
  820.                     delete dn;
  821.             }
  822.         }
  823.  
  824.         // Sort the files in reverse order to get subdirectories first,
  825.         //  so x/y/z will always be removed before x/y.
  826.         qsort((TCHAR*)dlist, dcnt, sizeof(TCHAR*), rcmp);
  827.  
  828.         for (i = 0; i < dcnt; i++)
  829.         {
  830.             TCHAR *p = dlist[i];
  831.  
  832.             if (*p == '\0')
  833.                 continue;
  834.  
  835.             if (i == 0 || !ZMatch(p, dlist[i - 1]))
  836.                 TrashDir(p);
  837.         }
  838.  
  839.         // clean up
  840.         for (int i = 0; i < dcnt; i++)
  841.             delete[] dlist[i];
  842.         delete[] dlist;
  843.     }
  844.  
  845.         return DZ_ERR_GOOD;
  846. }
  847.  
  848.  
  849.  
  850.  
  851.