Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include "dz_errs.h"
  4.  
  5. #undef _DZ_FILE_
  6. #define _DZ_FILE_ DZ_UNZWIN32_CPP
  7. /* This version modified by Chris Vleghert and Eric W. Engler
  8.  * for BCB/Delphi Zip, Jun 18, 2000.
  9.  
  10.   Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
  11.  
  12.   See the accompanying file LICENSE, version 2007-Mar-4 or later
  13.   (the contents of which are also included in zip.h) for terms of use.
  14.   If, for some reason, all these files are missing, the Info-ZIP license
  15.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  16.  
  17.   parts Copyright (C) 1997 Mike White, Eric W. Engler
  18. ************************************************************************
  19.  Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
  20.  
  21.    This file is part of TZipMaster Version 1.9.
  22.  
  23.     TZipMaster is free software: you can redistribute it and/or modify
  24.     it under the terms of the GNU Lesser General Public License as published by
  25.     the Free Software Foundation, either version 3 of the License, or
  26.     (at your option) any later version.
  27.  
  28.     TZipMaster is distributed in the hope that it will be useful,
  29.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.     GNU Lesser General Public License for more details.
  32.  
  33.     You should have received a copy of the GNU Lesser General Public License
  34.     along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
  35.  
  36.     contact: problems@delphizip.org (include ZipMaster in the subject).
  37.     updates: http://www.delphizip.org
  38.     DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
  39. ************************************************************************/
  40.  
  41. /* WARNING: Don't pull any OS/2 or HPFS code without great care.  Much of
  42.  * it is also used for NTFS, although it doesn't always have comments to
  43.  * that effect. */
  44.  
  45. // MBCS update 17 Dec 2006
  46. /*---------------------------------------------------------------------------
  47.  * win32.c
  48.  * 32-bit Windows-specific (NT/95) routines for use with Info-ZIP's UnZip 5.2
  49.  * and later.  (Borrowed, pilfered and plundered code from OS/2 and MS-DOS
  50.  * versions and from ZIP; modified as necessary.)
  51.  * Contains:  GetLoadPath()
  52.  *            Opendir()
  53.  *            Readdir()
  54.  *            Closedir()
  55.  *            mapattr()
  56.  *            getNTfiletime()
  57.  *            close_outfile()
  58.  *            isfloppy()
  59.  *            IsVolumeOldFAT()   RCV Removed.
  60.  *            IsFileNameValid()
  61.  *            map2fat()
  62.  *            checkdir()
  63.  *            do_wild()
  64.  *            mapname()
  65.  *            version()
  66.  *---------------------------------------------------------------------------*/
  67. //#include "unzip.h"
  68. #include "UnzOp.h"
  69. //#include <windows.h>            /* must be AFTER unzip.h to avoid struct G problems */
  70. #include <shlobj.h>
  71. #include <direct.h>
  72.  
  73. /* ===========================================================================
  74.  *                 Function mapattr()
  75.  * Identical to MS-DOS, OS/2 versions.
  76.  * However, NT has a lot of extra permission stuff, so this function should
  77.  *  probably be extended in the future.
  78.  */
  79. int UnzOpr::mapattr(void)
  80. {
  81.     /* Set archive bit (file is not backed up): */
  82.     fpInfo->file_attr =
  83.         (unsigned)(fcrec.external_file_attributes | 32)  & 0xff;
  84.     return 0;
  85. }                               /* end function mapattr() */
  86.  
  87.  
  88. /* ===========================================================================
  89.  *             Function getNTfiletime()
  90.  * Get the file time in a format that can be used by SetFileTime() in NT.
  91.  */
  92. int UnzOpr::getNTfiletime(FILETIME * ft)
  93. {
  94.     FILETIME lft;                 /* 64-bit value made up of two 32 bit [low & high] */
  95.     WORD wDOSDate;                /* for converting from DOS date to Windows NT      */
  96.         WORD wDOSTime;
  97.  
  98.     wDOSTime = (WORD)  flrec.last_mod_file_time;
  99.     wDOSDate = (WORD)  flrec.last_mod_file_date;
  100.  
  101.     /* The DosDateTimeToFileTime() function converts a DOS date/time    */
  102.     /* into a 64 bit Windows NT file time                               */
  103.     if (!DosDateTimeToFileTime(wDOSDate, wDOSTime, &lft))
  104.         {
  105.         Notify(0,  _T("DosDateTime failed: %s"), SysMsg().c_str());
  106.         return false;
  107.     }
  108.  
  109.     if (!LocalFileTimeToFileTime(&lft, ft))
  110.         {
  111.         Notify(0,  _T("LocalFileTime failed: %s"), SysMsg().c_str());
  112.         *ft = lft;
  113.     }
  114.     return true;
  115. }
  116.  
  117.  
  118. /* ===========================================================================
  119.  *        Function close_outfile()
  120.  */
  121. void UnzOpr::close_outfile(void)
  122. {
  123.     FILETIME ft;                  /* File time type defined in NT */
  124.     int gotTime;
  125.  
  126.     if (!fUnzOutfile || !fUnzOutfile->IsFile)
  127.         return;
  128.  
  129.     /* don't set the time stamp on standard output */
  130.     if (fUnzOutfile)
  131.     {
  132.         ZStreamIO *tmp = fUnzOutfile;
  133.         fUnzOutfile = NULL;
  134.         delete tmp;
  135.     }
  136.  
  137.     gotTime = getNTfiletime(&ft);
  138.  
  139.     /* Close the file and then re-open it using the Win32
  140.      * CreateFile call, so that the file can be created
  141.      * with GENERIC_WRITE access, otherwise the SetFileTime
  142.      * call will fail. */
  143.     if (gotTime || fpInfo->ntfs_data)
  144.     {
  145.         if (Verbose < 0)
  146.             Notify(ITRACE, _T("setting date/time in close_outfile"));
  147.  
  148.         ZFile tmpz(this, ffilename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
  149.                                    FILE_ATTRIBUTE_NORMAL);
  150.         if (!tmpz.IsOpen())
  151.             Notify(0, _T("CreateFile error [%s] when trying set filetime"), SysMsg().c_str());
  152.         else
  153.         {
  154.             XNTFSData times;
  155.             memset(&times, 0, sizeof(XNTFSData));
  156.             times.MTime = ft;
  157.             if (fpInfo->ntfs_data)
  158.                 memcpy(&times, fpInfo->ntfs_data, sizeof(XNTFSData));
  159.             if (!tmpz.SetTime(&times.CTime, &times.ATime, &times.MTime))// &ft))
  160.                 Notify(0,  _T("SetFileTime failed: %s"), SysMsg().c_str());
  161.         }
  162.  
  163.     }
  164.  
  165.     /* HG: I think this could be done in the CreateFile call above - just  */
  166.     /*     replace 'FILE_ATTRIBUTE_NORMAL' with 'fpInfo->file_attr & 0x7F'  */
  167.     if (!SetFileAttributes(ffilename, fpInfo->file_attr & 0x7F))
  168.         Notify(IWARNING, _T("Could not set file attributes [%s]"), SysMsg().c_str());
  169.     else                                                
  170. #if defined(UNICODE) && defined(ALLOW_WIN98)
  171.         if (IsNTorAbove)
  172.             SHChangeNotify(SHCNE_ATTRIBUTES, SHCNF_PATH,
  173.                 fpInfo->spec->Base->FullPath(ffilename), NULL);
  174.         else
  175.         {
  176.             DZStrA atmp(fpInfo->spec->Base->FullPath(ffilename));
  177.             SHChangeNotify(SHCNE_ATTRIBUTES, SHCNF_PATH, atmp, NULL);
  178.         }
  179. #else
  180.         SHChangeNotify(SHCNE_ATTRIBUTES, SHCNF_PATH,
  181.             fpInfo->spec->Base->FullPath(ffilename), NULL);
  182. #endif
  183.  
  184.     return;
  185. }                               /* end function close_outfile() */
  186.  
  187.  
  188. /* ===========================================================================
  189.  *                    Function isfloppy()
  190.  * more precisely, is it removable?
  191.  */
  192. static int isfloppy(int nDrive)
  193. {
  194.     /* 1 == A:, 2 == B:, etc. */
  195.     DZStrW root;
  196.     TCHAR c = (TCHAR)(_T('A') + nDrive - 1);    /* build the root path */
  197.     root += c;
  198.     root += _T(":\\");      
  199.         return(GetDriveType(root)  == DRIVE_REMOVABLE);
  200. }                               /* end function isfloppy() */
  201.  
  202. /* ===========================================================================
  203.  *             Function mapname()
  204.  * There are presently two possibilities in OS/2:  the output filesystem is
  205.  * FAT, or it is HPFS.  If the former, we need to map to FAT, obviously, but
  206.  * we *also* must map to HPFS and store that version of the name in extended
  207.  * attributes.  Either way, we need to map to HPFS, so the main mapname
  208.  * routine does that.  In the case that the output file system is FAT, an
  209.  * extra filename-mapping routine is called in checkdir().  While it should
  210.  * be possible to determine the filesystem immediately upon entry to mapname(),
  211.  * it is conceivable that the DOS APPEND utility could be added to OS/2 some-
  212.  * day, allowing a FAT directory to be APPENDed to an HPFS drive/path.  There-
  213.  * fore we simply check the filesystem at each path component.
  214.  *
  215.  * Note that when alternative IFS's become available/popular, everything will
  216.  * become immensely more complicated.  For example, a Minix filesystem would
  217.  * have limited filename lengths like FAT but no extended attributes in which
  218.  * to store the longer versions of the names.  A BSD Unix filesystem would
  219.  * support paths of length 1024 bytes or more, but it is not clear that FAT
  220.  * EAs would allow such long .LONGNAME fields or that OS/2 would properly
  221.  * restore such fields when moving files from FAT to the new filesystem.
  222.  *
  223.  * GRR:  some or all of the following chars should be checked in either
  224.  *       mapname (HPFS) or map2fat (FAT), depending:  ,=^+'"[]<>|\t&
  225.  *
  226.  * return 0 if no error, 1 if caution (filename trunc),
  227.         renamed :: 2 if warning (skip file because dir doesn't exist),
  228.                    3 if error (skip file), 10 if no memory (skip file),
  229.                    IZ_VOL_LABEL if can't do vol label, IZ_CREATED_DIR
  230.  */
  231. int UnzOpr::mapname(int renamed)
  232. {
  233.         DZStrW build;
  234.     int fposn;          // possition in ffilename
  235.  
  236.     /*---------------------------------------------------------------------------
  237.      *    Initialize various pointers and counters and stuff.
  238.      *---------------------------------------------------------------------------*/
  239.     /* can create path as long as not just freshening, or if user told us */
  240.     fcreate_dirs = (!ffflag || renamed);
  241.  
  242.         fcreated_dir = false;      /* not yet */
  243.         bool isAbs = false;
  244.     fposn = 0;
  245.  
  246.     if (renamed)
  247.     {
  248.         if (fpInfo->vollabel)
  249.         {
  250.             int drv;
  251.                         /* use root or renamed path, but don't store */
  252.                         if (ffilename[1]  == _T(':'))
  253.             {
  254.                 TCHAR d = (TCHAR) _totlower(ffilename[0]);
  255.                 drv = d - (_T('a') + 1);
  256.             }
  257.             else
  258.                         {
  259.                 int l = GetFullPathName(_T("."), MAX_PATH, build.GetBuffer(MAX_PATH), NULL);
  260.                 if (l)
  261.                 {
  262.                     TCHAR d = (TCHAR) _totlower(ffilename[0]);
  263.                     drv = d - (_T('a') + 1);
  264.                                 }
  265.             }
  266.             if (fvolflag == 0 || drv < 0 || drv > 25  /* no labels/bogus? */
  267.                     || (fvolflag == 1 && !isfloppy(drv)))
  268.             {
  269.                 /* !fixed */
  270.                 return IZ_VOL_LABEL;    /* skipping with message */
  271.             }
  272.             fnLabelDrive = drv;
  273.         }
  274.         else
  275.                 {
  276.             fposn = DriveLen(ffilename);
  277.             if (fposn < 0)
  278.                 return 4;   // invalid renamed stream
  279.             if (fposn > 0)
  280.             {
  281. //                if (ffilename[fposn] == BSLASH)
  282. //                                      fposn++;
  283. //                build = ffilename.Left(fposn);
  284.                                 isAbs = true;  // is absolute path
  285.                                 fposn = 0;              // want all of it
  286.             }
  287.             else
  288.                 if (ffilename[0] == BSLASH)
  289.                 {
  290.                                         ffilename = ffilename.Mid(1);
  291.                                 }
  292.         }
  293.     }
  294.  
  295.         /* pathcomp is ignored unless renamed is true: */
  296.     if (!renamed)
  297.     {
  298.         /* cp already set if renamed */
  299.         if (fjflag)               /* junking directories */
  300.         {
  301.                         fposn = ffilename.ReverseFind(BSLASH);
  302.         if (fposn < 0)
  303.             fposn = 0;
  304.         else
  305.             fposn++;
  306.                 }
  307.         }
  308.         if (fposn > 0)
  309.                 ffilename = ffilename.Mid(fposn);
  310.         DZStrW ftemp;
  311.         int cperr = CleanPath(ffilename, ftemp);
  312.         if (cperr != 0)
  313.         {
  314.                 Notify(IWARNING, _T("mapname: rejecting invalid filename: %s [err:%d]"), ffilename.c_str(), cperr);
  315.                 return DZ_ERM_INVAL_NAME;
  316.         }
  317. //      if (isAbs)
  318. //              ffilename = build + ftemp;
  319. ////            ffilename = build = ftemp;
  320. //      else
  321. //              ffilename = fpInfo->spec->Base->FullPath(ftemp);
  322.         if (isAbs)
  323.                 ffilename = ftemp;
  324.         else
  325.                 ffilename = fpInfo->spec->Base->FullPath(ftemp);
  326.  
  327.         DZStrW dir = ExtractFilePath(ffilename);
  328.         // no such dir - check filename
  329.         if (!DirExists(dir))
  330.         {
  331.                 /* path doesn't exist   // v1.6025 */
  332.                 if (!fcreate_dirs)
  333.                 {
  334.                         /* told not to create (freshening) */
  335.                         return IZ_SKIP_DIR;               // path doesn't exist:  nothing to do
  336.                 }
  337.  
  338.                 if (!ForceDirectories(dir, -1))
  339.                 {
  340.                         /* create the directory   // v1.6025 */
  341.                         Notify(0, _T("can't create %s [%s], unable to process %s."),
  342.                                 dir.c_str(), SysMsg().c_str(), ffilename.c_str());
  343.                         return DZ_ERM_ERROR_CREATE;     // path didn't exist, tried to create, failed
  344.                 }
  345.                 fcreated_dir = true;
  346.         }
  347.  
  348.          if (ffilename.LastChar() == BSLASH)
  349.          {
  350.                 if (fcreated_dir)
  351.                 {
  352. //          Notify(0,  _T("   created: %s"), ffilename);
  353.           /* HG: are we setting the date & time on a newly created   */
  354.           /*     dir?  Not quite sure how to do this.  It does not   */
  355.           /*     seem to be done in the MS-DOS version of mapname(). */
  356.           return IZ_CREATED_DIR;    /* dir time already set */
  357.         }
  358.                 return IZ_SKIP_DIR; /* dir existed already; don't look for data to extract */
  359.  
  360.      }
  361.      return 0;
  362. }
  363.  
  364.