Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include <stdio.h>
  4. #include "common.h"
  5. #include "dz_errs.h"
  6.  
  7. #undef _DZ_FILE_
  8. #define _DZ_FILE_ DZ_UNZFIO_CPP
  9. /*
  10. unzfio.cpp -
  11.  
  12.   Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
  13.  
  14.   See the accompanying file LICENSE, version 2007-Mar-4 or later
  15.   (the contents of which are also included in zip.h) for terms of use.
  16.   If, for some reason, all these files are missing, the Info-ZIP license
  17.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  18.  
  19.   parts Copyright (C) 1997 Mike White, Eric W. Engler
  20. ************************************************************************
  21.  Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
  22.  
  23.    This file is part of TZipMaster Version 1.9.
  24.  
  25.     TZipMaster is free software: you can redistribute it and/or modify
  26.     it under the terms of the GNU Lesser General Public License as published by
  27.     the Free Software Foundation, either version 3 of the License, or
  28.     (at your option) any later version.
  29.  
  30.     TZipMaster is distributed in the hope that it will be useful,
  31.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  32.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  33.     GNU Lesser General Public License for more details.
  34.  
  35.     You should have received a copy of the GNU Lesser General Public License
  36.     along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
  37.  
  38.     contact: problems@delphizip.org (include ZipMaster in the subject).
  39.     updates: http://www.delphizip.org
  40.     DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
  41. ************************************************************************/
  42.  
  43.  
  44. /* This version modified by Chris Vleghert and Eric W. Engler
  45.  * for BCB/Delphi Zip, Jun 18, 2000.
  46.  * RP - new GetFullPath, Jul 10, 2002.
  47.  * RP - "fixed" dos_to_unix_time for problem with localtime Jul 10, 2002
  48.  */
  49.  
  50. /*---------------------------------------------------------------------------
  51.  * fileio.c
  52.  * This file contains routines for doing direct but relatively generic input/
  53.  * output, file-related sorts of things, plus some miscellaneous stuff.  Most
  54.  * of the stuff has to do with opening, closing, reading and/or writing files.
  55.  * Contains:  open_input_file()
  56.  *            open_outfile()           (non-VMS, non-AOS/VS, non-CMS_MVS)
  57.  *            undefer_input()
  58.  *            defer_leftover_input()
  59.  *            readbuf()
  60.  *            readbyte()
  61.  *            fillinbuf()
  62.  *            flush()                  (non-VMS)
  63.  *            disk_error()             (non-VMS)
  64.  *            handler()
  65.  *            dos_to_unix_time()       (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
  66.  *            check_for_newer()        (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
  67.  *            do_string()
  68.  *            makeword()
  69.  *            makelong()
  70.  *            str2iso()
  71.  *            str2oem()
  72.  *            zstrnicmp()
  73.  *            ExtASCII2Native()
  74.  *            WriteToMemory()
  75.  *            ShowSysMsg()
  76.  *---------------------------------------------------------------------------
  77.  */
  78.  
  79. #include "WinUser.h"
  80. #include <shlobj.h>
  81. #include <io.h>
  82. #include "UnzOp.h"
  83. #include "enter.h"
  84.  
  85. /* ===========================================================================
  86. *                  Function open_outfile() *
  87. * Return 0 on success and leave foutfile open.
  88. * Return PK_DISK if failed. */
  89. int UnzOpr::open_outfile(void)
  90. {
  91.         if (Is_Drv(ffilename) < 0)
  92.                 fUnzOutfile = new ZStream(this, ffilename);
  93.         else
  94.         {
  95.                 DWORD dwAttrs = GetFileAttributes(ffilename);
  96.                 if (dwAttrs != INVALID_FILE_ATTRIBUTES)
  97.                 {
  98.                         if (Verbose)
  99.                                 Notify(IVERBOSE, _T(
  100.                                         "open_outfile:  stat(%s) returns file exists"),
  101.                                 ffilename.c_str());
  102.                         if ((dwAttrs & FILE_ATTRIBUTE_READONLY))
  103.                         {
  104.                                 if (Verbose)
  105.                                         Notify(IVERBOSE, _T(
  106.                                                 "open_outfile:  existing file %s is read-only"),
  107.                                         ffilename.c_str());
  108.                                 if (!SetFileAttributes(ffilename,
  109.                                                 dwAttrs&~FILE_ATTRIBUTE_READONLY) && Verbose < 0)
  110.                                         Notify(IVERBOSE, _T("could not reset read-only %s [%s]"),
  111.                                         ffilename.c_str(), SysMsg().c_str());
  112.                         }
  113.                         if (!DeleteFile(ffilename))
  114.                         {
  115.                                 if (Verbose)
  116.                                         Notify(IVERBOSE, _T("DeleteFile(%s) failed [%s]"),
  117.                                         ffilename.c_str(), SysMsg().c_str());
  118.                                 return PK_NODEL;
  119.                         }
  120. #if defined(UNICODE) && defined(ALLOW_WIN98)
  121.                         if (IsNTorAbove)
  122.                                 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH,
  123.                                 fpInfo->spec->Base->FullPath(ffilename), NULL);
  124.                         else
  125.                         {
  126.                                 DZStrA atmp(fpInfo->spec->Base->FullPath(ffilename));
  127.                                 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, atmp, NULL);
  128.                         }
  129. #else
  130.                         SHChangeNotify(SHCNE_DELETE, SHCNF_PATH,
  131.                                 fpInfo->spec->Base->FullPath(ffilename), NULL);
  132. #endif
  133.                         if (Verbose) // vflag)
  134.                                 Notify(0, _T("Deleted pre-existing file %s"),
  135.                                 ffilename.c_str());
  136.                 }
  137.  
  138.                 if (Is_Drv(ffilename) < 0)
  139.                         fUnzOutfile = new ZStream(this, ffilename);
  140.                 else
  141.                         fUnzOutfile = new ZFile(this, ffilename, GENERIC_WRITE, 0, NULL,
  142.                         CREATE_NEW, FILE_ATTRIBUTE_NORMAL);
  143.         }
  144.         if (!fUnzOutfile->IsOpen())
  145.         {
  146.                 if (Verbose)
  147.                         Notify(0, _T("Error [%s] opening file %s for write"),
  148.                         SysMsg().c_str(), ffilename.c_str());
  149.                 else
  150.                         Notify(0, _T("Error opening file %s for write"), ffilename.c_str());
  151.                 return PK_DISK;
  152.         }
  153.         // EWE SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, GetFullPath(ffilename), NULL);
  154.         if (Verbose < 0)
  155.                 Notify(ITRACE,
  156.                 _T("open_outfile:  CreateFile(%s) for writing succeeded"),
  157.                 ffilename.c_str());
  158.  
  159.         return PK_OK;
  160. }
  161. /* end function open_outfile() */
  162.  
  163.  
  164. /* ===========================================================================
  165. *                  function undefer_input()
  166. * These functions allow NEXTBYTE to function without needing two bounds
  167. * checks.  Call defer_leftover_input() if you ever have filled finbuf
  168. * by some means other than readbyte(), and you then want to start using
  169. * NEXTBYTE.  When going back to processing bytes without NEXTBYTE, call
  170. * undefer_input().  For example, extract_or_test_member brackets its
  171. * central section that does the decompression with these two functions.
  172. * If you need to check the number of bytes remaining in the current
  173. * file while using NEXTBYTE, check (fcsize + fincnt), not fcsize. */
  174. void UnzSup::undefer_input(void)
  175. {
  176.         if (fincnt > 0)
  177.                 fcsize += fincnt;
  178.         if (fincnt_leftover > 0)
  179.         {
  180.                 /* We know that "(fcsize < MAXINT)" so we can cast fcsize to int:
  181.                  * This condition was checked when fincnt_leftover was set > 0 in
  182.                  * defer_leftover_input(), and it is NOT allowed to touch fcsize
  183.                  * before calling undefer_input() when (fincnt_leftover > 0)
  184.                  * (single exception: see read_byte()'s  "fcsize <= 0" handling) !! */
  185.                 fincnt = fincnt_leftover + (int)fcsize;
  186.                 finptr = finptr_leftover - (int)fcsize;
  187.                 fincnt_leftover = 0;
  188.         }
  189.         else if (fincnt < 0)
  190.                 fincnt = 0;
  191. }
  192.  
  193. /* ===========================================================================
  194. *              function defer_leftover_input() */
  195. void UnzSup::defer_leftover_input(void)
  196. {
  197.         if (fcsize < MAXINT && (long)fincnt > (long)fcsize)
  198.         {
  199.                 /* (fcsize < MAXINT), we can safely cast it to int !! */
  200.                 if (fcsize < 0L)
  201.                         fcsize = 0L;
  202.                 finptr_leftover = finptr + (int)fcsize;
  203.                 fincnt_leftover = fincnt - (int)fcsize;
  204.                 fincnt = (int)fcsize;
  205.         }
  206.         else
  207.                 fincnt_leftover = 0;
  208.         fcsize -= fincnt;
  209. }
  210.  
  211.  
  212. /* ===========================================================================
  213. *                      Function readbuf()
  214. * Return number of bytes read into buf. */
  215. unsigned __fastcall UnzSup::readbuf(char * buf, unsigned size)
  216. {
  217.         register unsigned count;
  218.         unsigned n;
  219.  
  220.         n = size;
  221.         while (size)
  222.         {
  223.                 if (fincnt <= 0)
  224.                 {
  225.                         if ((fincnt = vclRead((char*)finbuf, INBUFSIZ)) == 0)
  226.                                 return(n - size);
  227.                         else if (fincnt < 0)
  228.                         {
  229.                                 Notify(0, _T("Error reading ZIP file"));
  230.                                 return 0;
  231.                                 /* discard some data - better than lock-up */
  232.                         }
  233.                         if (InProgress)
  234.                                 CB->UserProgress(fincnt);
  235.                         /* buffer ALWAYS starts on a block boundary: */
  236.                         fcur_zipfile_bufstart += INBUFSIZ;
  237.                         finptr = finbuf;
  238.                 }
  239.                 count = MIN(size, (unsigned)fincnt);
  240.                 memcpy(buf, finptr, count);
  241.                 buf += count;
  242.                 finptr += count;
  243.                 fincnt -= count;
  244.                 size -= count;
  245.         }
  246.         // Trace(("returning %u from readbuf", n));
  247.         return n;
  248. }
  249. /* end function readbuf() */
  250.  
  251.  
  252. /* ===========================================================================
  253. *                      Function readbyte()
  254. * Refill inbuf and return a byte if available, else EOF. */
  255. int UnzSup::readbyte(void)
  256. {
  257.         if (fcsize <= 0)
  258.         {
  259.                 fcsize = -1;
  260.                 /* for tests done after exploding */
  261.                 fincnt = 0;
  262.                 return EOF;
  263.         }
  264.         if (fincnt <= 0)
  265.         {
  266.                 if ((fincnt = vclRead((char*)finbuf, INBUFSIZ)) == 0)
  267.                 {
  268.                         fincnt = 0;
  269.                         /* do not allow negative value to affect stuff */
  270.                         return EOF;
  271.                 }
  272.                 else if (fincnt < 0)
  273.                 {
  274.                         /* "fail" (abort, retry, ...) returns this */
  275.                         Notify(0, _T("Error reading from ZIP file"));
  276.                         throw DZException(DZ_ERM_ERROR_READ);
  277.                 }
  278.                 if (InProgress)
  279.                         CB->UserProgress(fincnt);
  280.                 fcur_zipfile_bufstart += INBUFSIZ; // always starts on block bndry
  281.                 finptr = finbuf;
  282.                 defer_leftover_input(); // decrements fcsize
  283.         }
  284.         if (Encrypted)
  285.         {
  286.                 uch * p;
  287.                 int n;
  288.  
  289.                 /* This was previously set to decrypt one byte beyond fcsize, when
  290.                  * incnt reached that far.  GRR said, "but it's required:  why?"  This
  291.                  * was a bug in fillinbuf() -- was it also a bug here? */
  292.                 for (n = fincnt, p = finptr; n--; p++)
  293.                         * p = (uch)zdecode(*p, fkeys);
  294.         }
  295.         --fincnt;
  296.         return * finptr++;
  297. }
  298. /* end function readbyte() */
  299.  
  300.  
  301. /* ===========================================================================
  302. *                     Function flush()
  303. * cflag => always 0; 50 if write error */
  304. int UnzSup::part_flush(uch * rawbuf, ulg size, int unshrink)
  305. {
  306.         register uch *p, *q;
  307.         uch *transbuf;
  308.         unsigned long k;
  309.  
  310.         if (size)
  311.         {
  312.                 // restrict size blowouts
  313.                 if (size > fMax_Write)
  314.                 {
  315.                         size = fMax_Write;
  316.                         if (Verbose < 0)
  317.                                 Notify(IWARNING, _T("File size overrun"));
  318.                 }
  319.                 fMax_Write -= size;
  320.                 if (!InProgress)
  321.                         CB->UserProgress(size);
  322.                 fBytesWritten += size;
  323.         }
  324.         /* ---------------------------------------------------------------------------
  325.          * Compute the CRC first; if testing or if disk is full, that's it.
  326.          *--------------------------------------------------------------------------- */
  327.         fcrc32val = crc32(fcrc32val, rawbuf, (::extent)size);
  328.  
  329.         if (ftflag || !size) // testing or nothing to write:  all done
  330.                         return 0;
  331.         if (fdisk_full)
  332.                 return PK_DISKFULL; // disk already full:  ignore rest of file
  333.         if (!fpInfo->textmode)
  334.         {
  335.                 /* write raw binary data */
  336.                 if ((!fUnzOutfile->Write(rawbuf, size, &k) || k != size))
  337.                         return disk_error();
  338.                 return 0;
  339.         }
  340.  
  341.         /* ---------------------------------------------------------------------------
  342.          * Write the bytes rawbuf[0..size-1] to the output device, first converting
  343.          * end-of-lines and ASCII/EBCDIC as needed.  If SMALL_MEM or MED_MEM are NOT
  344.          * defined, outbuf is assumed to be at least as large as rawbuf and is not * necessarily checked for overflow.
  345.          *--------------------------------------------------------------------------- */
  346. //      if (!fpInfo->textmode)
  347. //      {
  348. //              /* write raw binary data */
  349. //              if ((!fUnzOutfile->Write(rawbuf, size, &k) || k != size))
  350. //                      return disk_error();
  351. //      }
  352. //      else
  353. //      {
  354.         if (unshrink)
  355.         {
  356.                 /* rawbuf = outbuf */
  357.                 transbuf = foutbuf2;
  358.         }
  359.         else
  360.         {
  361.                 /* rawbuf = slide */
  362.                 transbuf = foutbuf;
  363.         }
  364.         if (fnewfile)
  365.         {
  366.                 fTextLast = 0;
  367.                 /* no previous buffers written */
  368.                 fnewfile = false;
  369.         }
  370.         p = rawbuf;
  371.         if (*p == LF && fTextLast == CR)
  372.                 ++p;
  373.  
  374.         /* -----------------------------------------------------------------------
  375.          * Algorithm:  CR/LF => native; lone CR => native; lone LF => native.
  376.          * This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
  377.          * stream-oriented files, not record-oriented).
  378.          *----------------------------------------------------------------------- */
  379.         q = transbuf;
  380.         fTextLast = 0;
  381.         for (; p < rawbuf + (unsigned)size; ++p)
  382.         {
  383.                 if (*p == CR)
  384.                 {
  385.                         /* lone CR or CR/LF: EOL either way */
  386.                         *q++ = CR;
  387.                         *q++ = LF;
  388.                         if (p == rawbuf + (unsigned)size - 1) /* last char in buffer */
  389.                                         fTextLast = CR;
  390.                         else if (p[1] == LF) /* get rid of accompanying LF */
  391.                                         ++p;
  392.                 }
  393.                 else if (*p == LF)
  394.                 {
  395.                         /* lone LF */
  396.                         *q++ = CR;
  397.                         *q++ = LF;
  398.                 }
  399.                 else
  400.                 {
  401.                         *q++ = *p;
  402.                 }
  403.         }
  404.  
  405.         /* -----------------------------------------------------------------------
  406.          * Done translating:  write whatever we've got to file
  407.          *----------------------------------------------------------------------- */
  408.         if (Verbose < 0)
  409.                 Notify(ITRACE,
  410.                 _T("p - rawbuf = %u   q-transbuf = %u   size = %lu"),
  411.                 (unsigned)(p - rawbuf), (unsigned)(q - transbuf), size);
  412.         if (q > transbuf)
  413.         {
  414.                 unsigned long k, sz = (unsigned)(q - transbuf);
  415.                 if ((!fUnzOutfile->Write(transbuf, sz, &k) || k != sz))
  416.                         return disk_error();
  417.         }
  418. //      }
  419.         return 0;
  420. }
  421. /* end function flush() */
  422.  
  423.  
  424. int UnzSup::flush(uch * rawbuf, ulg size, int unshrink)
  425. {
  426.   int ret;
  427.   while (size > 0x8000L)
  428.   {
  429.     ret = part_flush(rawbuf, 0x8000L, unshrink);
  430.     if (DZ_ERR(ret)) //ret != PK_OK)
  431.       return ret;
  432.     size -= 0x8000L;
  433.     rawbuf += (::extent)0x8000;
  434.   }
  435.   return part_flush(rawbuf, size, unshrink);
  436. }
  437. /* ===========================================================================
  438. *        Function disk_error() */
  439. int UnzSup::disk_error(void)
  440. {
  441.   DZError(DZ_ERM_ERROR_WRITE);
  442.   return PK_DISK;
  443.   /* disk is full */
  444. }
  445.  
  446.  
  447. /* ===========================================================================
  448. *           Function handler()
  449. * Upon interrupt, turn on echo and exit cleanly. */
  450.  
  451. /*void handler(int signal) { #ifdef SIGSEGV if (signal == SIGSEGV) { EXIT(PK_BADERR); } #endif
  452. /* probably ctrl-C EXIT(PK_ERR); } */
  453.  
  454. #ifndef timezone
  455. #  define timezone _timezone
  456. #endif
  457.  
  458. #define YRBASE  1970
  459.  
  460. /* ===========================================================================
  461. *        Function dos_to_unix_time()
  462. * only used for freshening/updating */
  463. time_t dos_to_unix_time(unsigned ddate, unsigned dtime)
  464. {
  465.         time_t m_time;
  466.         int yr, mo, dy, hh, mm, ss;
  467.         static short yday[] =
  468.         {
  469.                 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  470.         };
  471.         int leap;
  472.         unsigned days;
  473.         struct tm * lt; // RP - add
  474.  
  475.         /* dissect date */
  476.         yr = ((ddate >> 9) & 0x7f) + (1980 - YRBASE);
  477.         mo = ((ddate >> 5) & 0x0f) - 1;
  478.         dy = (ddate & 0x1f) - 1;
  479.  
  480.         /* dissect time */
  481.         hh = (dtime >> 11) & 0x1f;
  482.         mm = (dtime >> 5) & 0x3f;
  483.         ss = (dtime & 0x1f) * 2;
  484.  
  485.         /* leap = # of leap yrs from YRBASE up to but not including current year */
  486.         leap = ((yr + YRBASE - 1) / 4);
  487.         /* leap year base factor */
  488.  
  489.         /* calculate days from BASE to this year and add expired days this year */
  490.         days = (yr * 365) + (leap - 492) + yday[mo];
  491.  
  492.         /* if year is a leap year and month is after February, add another day */
  493.         if ((mo > 1) && ((yr + YRBASE) % 4 == 0) && ((yr + YRBASE) != 2100))
  494.                 ++days;
  495.         /* OK through 2199 */
  496.  
  497.         /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
  498.         m_time = (time_t)((long)(days + dy) * 86400L + (long)hh * 3600L + (long)
  499.                 (mm * 60 + ss));
  500.         /* - 1;   MS-DOS times always rounded up to nearest even second */
  501.  
  502.         /* ---------------------------------------------------------------------------
  503.          *    Adjust for local standard timezone offset.
  504.          *------------------------------------------------------------------------- */
  505.         {
  506.                 TIME_ZONE_INFORMATION tzinfo;
  507.                 DWORD res = GetTimeZoneInformation(&tzinfo);
  508.  
  509.                 /* account for timezone differences */
  510.                 if (res != TIME_ZONE_ID_UNKNOWN)
  511.                         m_time += (60 * tzinfo.Bias);
  512.         }
  513.  
  514.         /* ---------------------------------------------------------------------------
  515.          *    Adjust for local daylight savings (summer) time.
  516.          *------------------------------------------------------------------------- */
  517.         if ((ddate >= (unsigned)DOSDATE_2038_01_18) && (m_time < (time_t)
  518.                         0x70000000L))
  519.                 m_time = U_TIME_T_MAX;
  520.         /* saturate in case of (unsigned) overflow */
  521.         if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
  522.                         m_time = S_TIME_T_MAX;
  523.         /* -> saturate at max signed time_t value */
  524.         lt = localtime((time_t*) & m_time); // RP - added
  525.         if (lt && lt->tm_isdst) // RP - changed
  526.                 m_time -= (60L * 60L);
  527.  
  528.         if ((ddate >= (unsigned)DOSDATE_2038_01_18) && (m_time < (time_t)
  529.                         0x70000000L))
  530.                 m_time = U_TIME_T_MAX;
  531.         /* saturate in case of (unsigned) overflow */
  532.         if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
  533.                         m_time = S_TIME_T_MAX;
  534.         /* -> saturate at max signed time_t value */
  535.  
  536.         return m_time;
  537. }
  538. /* end function dos_to_unix_time() */
  539.  
  540.  
  541. /* ===========================================================================
  542. *       Function check_for_newer()
  543. * Used for overwriting/freshening/updating.
  544. * Return 1 if existing file is newer.
  545. *
  546. *filename :: Or equal; 0 if older; -1 if doesn't exist yet. */
  547. int UnzOpr::check_for_newer(const DZStrW& filename)
  548. {
  549.         time_t existing, archive;
  550.         DZStrW tmp(filename);
  551.         if (tmp.LastChar() == BSLASH)
  552.                 tmp = tmp.Left(tmp.length() - 1); // remove
  553.         if (_tstati64(tmp, &fstatbuf))
  554.         {
  555.                 if (Verbose < 0)
  556.                         Notify(ITRACE, _T("check_for_newer:  stat(%s) error: %s"),
  557.                         filename.c_str(), SysMsg().c_str());
  558.                 return DOES_NOT_EXIST;
  559.         }
  560.         // Trace(("check_for_newer:  stat(%s) returns 0:  file exists", filename));
  561.         /* round up existing filetime to nearest 2 seconds for comparison */
  562.         existing = fstatbuf.st_mtime & 1 ? fstatbuf.st_mtime +
  563.                 1 : fstatbuf.st_mtime;
  564.         archive = dos_to_unix_time(flrec.last_mod_file_date,
  565.                 flrec.last_mod_file_time);
  566.  
  567.         if (Verbose < 0)
  568.                 Notify(ITRACE, _T(
  569.                         "check_for_newer:  existing %ld, archive %ld, Result %d"),
  570.                 existing, archive, existing >= archive);
  571.         return(existing >= archive);
  572. }
  573. /* end function check_for_newer() */
  574.  
  575.  
  576. /* ===========================================================================
  577. *            Function do_string()
  578. * Return PK-type error code. len    :: Without prototype, ush converted to this.
  579. option :: SKIP, DISPLAY, DS_FN or EXTRA_FIELD */
  580. int UnzOpr::do_string(unsigned int len, int option)
  581. {
  582.         int error = PK_OK;
  583.         ush extra_len;
  584.  
  585.         /* ---------------------------------------------------------------------------
  586.          * This function processes arbitrary-length (well, usually) strings.  Four
  587.          * options are allowed:  SKIP, wherein the string is skipped (pretty logical,
  588.          * eh?); DISPLAY, wherein the string is printed to standard output after un-
  589.          * dergoing any necessary or unnecessary character conversions; DS_FN,
  590.          * wherein the string is put into the filename[] array after undergoing ap-
  591.          * propriate conversions (including case-conversion, if that is indicated:
  592.          * see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
  593.          * `string' is assumed to be an extra field and is copied to the (freshly
  594.          * malloced) buffer fextra_field.  The third option should be OK since
  595.          * filename is dimensioned at 1025, but we check anyway.
  596.          *
  597.          * The string, by the way, is assumed to start at the current file-pointer
  598.          * position; its length is given by len.  So start off by checking length
  599.          * of string:  if zero, we're already done.
  600.          *--------------------------------------------------------------------------- */
  601.         if (!len)
  602.                 return PK_COOL;
  603.  
  604.         switch(option)
  605.         {
  606.                 /* * Second case:  read string into filename[] array.  The filename should
  607.                  * never ever be longer than FILNAMSIZ - 1 (1024), but for now we'll check,
  608.                  * just to be sure. */
  609.         case DS_FN:
  610.                 extra_len = 0;
  611.                 if (len >= FILNAMSIZ)
  612.                 {
  613.                         Notify(IWARNING, _T(" filename too long; truncated"));
  614.                         error = PK_WARN;
  615.                         extra_len = (ush)(len - FILNAMSIZ + 1);
  616.                         len = FILNAMSIZ - 1;
  617.                 }
  618.                 {
  619.                         file_name.Empty();
  620.                         if (readbuf(file_name.GetBuffer(len), len) == 0)
  621.                                 return PK_EOF;
  622.                         file_name.ReleaseBuffer(len);
  623.                 }
  624.  
  625.                 if (fpInfo->vollabel && len > 8 && ffilename[8] == _T('.'))
  626.                 {
  627.                         ffilename.Delete(8, 1);
  628.                         /* disk label, and 8th char is dot:  remove dot */
  629.                 }
  630.  
  631.                 if (!extra_len)
  632.                         break;
  633.                 /* we're done here */
  634.  
  635.                 /* * We truncated the filename, so fall * through to the SKIP routine. */
  636.                 len = extra_len;
  637.  
  638.                 /* FALL THROUGH... */
  639.                 /* * Third case:  skip string, adjusting readbuf's internal variables
  640.                  * as necessary (and possibly skipping to and reading a new block of data). */
  641.         case SKIP:
  642.                 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
  643.                  * correct for it twice: */
  644.                 zlseek(fcur_zipfile_bufstart - fextra_bytes + (finptr - finbuf) + len);
  645.                 break;
  646.  
  647.                 /* * Fourth case:  assume we're at the start of an "extra field"; malloc
  648.                  * storage for it and read data into the allocated space. */
  649.         case EXTRA_FIELD:
  650.                 extra_field.Empty();
  651.                 if (readbuf((char*)extra_field.GetBuffer(len), len) == 0)
  652.                         return PK_EOF;
  653.                 extra_field.SetLength(len);
  654.                 getZip64Data(extra_field);
  655.                 break;
  656.         } /* end switch (option) */
  657.  
  658.         return error;
  659. }
  660. /* end function do_string() */
  661.  
  662. int UnzSup::vclRead(void * buf, unsigned LenToRead)
  663. {
  664.         unsigned long cnt;
  665.         if (!fUnzInfile->Read(buf, LenToRead, &cnt))
  666.                 return 0;
  667.         return cnt;
  668. }
  669.  
  670.  
  671. int UnzSup::zlseek(ZInt64 abs_offset)
  672. {
  673.         ZInt64 request = (abs_offset) + fextra_bytes;
  674.         ZInt64 inbuf_offset = request % INBUFSIZ;
  675.         ZInt64 bufstart = request - inbuf_offset;
  676.  
  677.         if (request < abs_offset && fextra_bytes > 0)
  678.         {
  679.                 return(PK_BADERR);
  680.         }
  681.         else if (bufstart != fcur_zipfile_bufstart)
  682.         {
  683.                 fcur_zipfile_bufstart = fUnzInfile->SetPosition(bufstart, SEEK_SET);
  684.                 if ((fincnt = vclRead((char*)finbuf, INBUFSIZ)) <= 0)
  685.                         return(PK_EOF);
  686.                 finptr = finbuf + (int)inbuf_offset;
  687.                 fincnt -= (int)inbuf_offset;
  688.         }
  689.         else
  690.         {
  691.                 fincnt += (finptr - finbuf) - (int)inbuf_offset;
  692.                 finptr = finbuf + (int)inbuf_offset;
  693.         }
  694.  
  695.         return 0;
  696. }
  697.