Subversion Repositories autosfx

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 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