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
/*
4
 
5
  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
6
 
7
  See the accompanying file LICENSE, version 2007-Mar-4 or later
8
  (the contents of which are also included in zip.h) for terms of use.
9
  If, for some reason, all these files are missing, the Info-ZIP license
10
  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
11
 
12
  parts Copyright (C) 1997 Mike White, Eric W. Engler
13
************************************************************************
14
 Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
15
 
16
   This file is part of TZipMaster Version 1.9.
17
 
18
    TZipMaster is free software: you can redistribute it and/or modify
19
    it under the terms of the GNU Lesser General Public License as published by
20
    the Free Software Foundation, either version 3 of the License, or
21
    (at your option) any later version.
22
 
23
    TZipMaster is distributed in the hope that it will be useful,
24
    but WITHOUT ANY WARRANTY; without even the implied warranty of
25
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
    GNU Lesser General Public License for more details.
27
 
28
    You should have received a copy of the GNU Lesser General Public License
29
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
30
 
31
    contact: problems@delphizip.org (include ZipMaster in the subject).
32
    updates: http://www.delphizip.org
33
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
34
************************************************************************/
35
#include <stdio.h>
36
#include <shellapi.h>
37
#include <sys\stat.h>
38
//#ifndef __BORLANDC__
39
//#define stati64 _stati64
40
//#endif
41
#include "common.h"
42
#include "ZStrings.h"
43
#include "dzframe.h"
44
#include "DZOper.h"
45
#include "version.h"
46
#include "helpers.h"
47
#include "dz_errs.h"
48
 
49
#undef _DZ_FILE_
50
#define _DZ_FILE_ DZ_DZOPER_CPP
51
//---------------------------------------------------------------------------
52
 
53
DZStrW SystemMsg(DWORD Error, const TCHAR* arg1)
54
{
55
    LPVOID lpMsgBuf;
56
 
57
    DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM;
58
    void *mdl = 0;
59
 
60
    if (Error & (DWORD)0x40000000L)
61
        {
62
        flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE;
63
        mdl = ModuleInst;
64
    }                          
65
#if defined(UNICODE) && defined(ALLOW_WIN98)
66
    FormatMessageA(flags, mdl, Error, 0, (LPSTR) &lpMsgBuf, 1000, NULL);  
67
    DZStrW t((const char *)lpMsgBuf);
68
#else
69
    FormatMessage(flags, mdl, Error, 0, (LPTSTR) &lpMsgBuf, 1000, NULL);
70
    DZStrW t((const TCHAR *)lpMsgBuf);
71
#endif
72
    if (t[t.Length() -2] == '\r')
73
                t.Delete(t.Length()-2, 2);
74
 
75
    // Free the buffer.
76
    LocalFree(lpMsgBuf);
77
    DZStrW tmp;
78
    tmp.Format(t, arg1);
79
 
80
        return tmp;
81
}
82
 
83
DZStrW LastSystemMsg(void)
84
{
85
    DWORD err = GetLastError();
86
    return SystemMsg(err);
87
}
88
 
89
void DZOp::SendInfo(unsigned err, const DZStrW& info)
90
{
91
        int     typ = 0;
92
        DZStrW buf;
93
 
94
    if (err > 0)
95
    {
96
        typ = DZ_MSGTYP(err);
97
 
98
        if (typ == DZM_Trace)
99
            buf = _T("Trace: ");
100
        else
101
            if (typ == DZM_Verbose)
102
                buf = _T("Info: ");
103
 
104
        buf += info;
105
    }
106
    else
107
        buf = info;
108
 
109
//#ifdef DZ_LOGGING
110
//    if (LogName && *(LogName))
111
//        LogString(err, buf);
112
//#endif
113
    CB->UserMsg(err, buf);
114
 
115
    if ((IERROR & typ) && Verbose < -10)
116
    {
117
        Verbose++;
118
        MsgBox(buf, true);
119
    }
120
}
121
 
122
DZOp::DZOp(const DllCommands *C): DZFrame((OperKeys)C,
123
                C->fOptions.OpIsZip || C->fOptions.OpIsZip), Command(C)
124
{
125
    Verbose = C->fVerbosity;
126
 
127
    if (Verbose > 1)
128
        Verbose = -1;
129
 
130
    fEncodedAs = C->fEncodedAs;
131
    fQuiet = C->fOptions.Quiet;
132
    fglobal_error_code = 0;
133
    fdll_handles_errors = 0;
134
    fuser_notified_of_abort = 0;
135
        CallerVersion = C->fVersion;
136
    fNTFSStamps = C->fOptions.NTFSStamps;
137
 
138
    fFromPage = C->fFromPage;
139
    fSS = C->fSS;         // used stream-stream
140
        Abort_Flag = 0;
141
//      NoSkipping = C->fOptions.NoSkip;   //<<
142
 
143
    // Copy the window handle and context of caller to our global vars
144
    global_handle = C->fHandle;
145
    global_caller = C->fCaller;
146
 
147
    // point to the C++Builder/Delphi callback function
148
    callb = C->ZCallbackFunc;
149
    ZStreamFunc = C->ZStreamFunc;
150
    ZSData.Check = STREAM_CHECK;
151
    ZSData.Caller = global_caller; // object instance pointer of caller
152
    CB = new UserCallback(this, C->fOptions.OpIsZip || C->fOptions.OpIsZip);
153
 
154
    CurPW = NULL;
155
    CurBase = NULL;
156
    fBytesWritten = 0;
157
}
158
 
159
DZOp::~DZOp(void)
160
{
161
 
162
    PWRec *tp, *tmpp = CurPW;
163
    CurPW = NULL;
164
 
165
    while (tmpp)
166
    {
167
        tp = tmpp;
168
        tmpp = tmpp->Next;
169
        delete tp;
170
    }
171
 
172
    BaseRec *tb, *tmpb = CurBase;
173
    CurBase = NULL;
174
 
175
    while (tmpb)
176
    {
177
        tb = tmpb;
178
        tmpb = tmpb->Next;
179
        delete tb;
180
    }
181
 
182
    delete CB;
183
}
184
 
185
int DZOp::Init(void) // after construction
186
{
187
    // do active initialisation    
188
    if (Command->fVersion != DZ_VER_VERSION)
189
    {
190
        // see version.h
191
        DZStrW tmp;
192
        tmp.Format(_T("Warning: %s version %s is %s than required (%i.%i.%i) - Please use correct version!"),
193
            _T(DLLNAME), _T(DZ_VER), (Command->fVersion < DZ_VER_VERSION) ? _T("newer") : _T("older"),
194
            Command->fVersion / 100, (Command->fVersion / 10) % 10, Command->fVersion % 10);
195
 
196
        // This message won't appear if user did pass us a zero Window handle.
197
        if (!Command->fOptions.Quiet)
198
            MsgBox(tmp, true);
199
 
200
        // Also report this fact via the C++Builder/Delphi callback.
201
        Notify(IERROR, tmp);
202
        return DZ_ERM_BAD_OPTIONS;
203
    }
204
    return 0;
205
}
206
 
207
void DZOp::ShowSysMsg(DWORD Error)
208
{
209
    if (Verbose)
210
    {
211
        Notify(0, _T("System Error (%lX) %s"), Error, SystemMsg(Error).c_str());
212
    }
213
}
214
 
215
// If we do not have a full path then FOF_ALLOWUNDO does not work!
216
int DZOp::EraseFile(const DZStrW &Fname, bool safe)
217
{                            
218
    SHFILEOPSTRUCT  fop;
219
    TCHAR           *sb;
220
    int             ls,
221
    r;
222
    if (Fname.IsEmpty())  
223
        return ENOENT;
224
 
225
    if (Verbose < 0)
226
        Notify(IVERBOSE, _T("destroying '%s'"), Fname.c_str());
227
    else
228
      CB->UserCB(zacTick);  // take a little time
229
    if (GetFileAttrs(Fname) == (DWORD) - 1)
230
    {
231
        if (Verbose < 0)
232
            Notify(IVERBOSE, _T("did not exist '%s'"), Fname.c_str());
233
        return DZ_ERR_GOOD;
234
    }
235
    fop.hwnd = global_handle;
236
    fop.wFunc = FO_DELETE;
237
    fop.pTo = NULL;
238
    fop.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NORECURSION;
239
    if (safe)
240
        fop.fFlags |= FOF_ALLOWUNDO;
241
    fop.fAnyOperationsAborted = 0;
242
    fop.hNameMappings = NULL;
243
    fop.lpszProgressTitle = NULL;
244
    DZStrW tmp(Fname);
245
    ls = tmp.length();
246
    sb = tmp.GetBuffer(ls + 2);
247
    sb[ls + 1] = 0;
248
    fop.pFrom = sb;
249
    r = SHFileOperation(&fop);
250
    if (r)
251
    {
252
        Notify(DZ_ERM_TEMP_FAILED, _T(" DestroyFile: Delete failed [%X]"), GetLastError());
253
        return -1;
254
    }
255
 
256
    return DZ_ERR_GOOD;
257
}
258
 
259
// cached call to 'stat' - return true if not found
260
bool DZOp::ZStat(const DZStrW &fn, struct stati64 *res)
261
{
262
    if (lastStatName && ZMatch(lastStatName, fn))
263
//      if (!fn.Compare(lastStatName.c_str()))
264
        {
265
        memcpy(res, &lastStat, sizeof(struct stati64));
266
                return false;
267
    }
268
 
269
    lastStatName.empty();
270
 
271
    bool ok;
272
 
273
        int drv = Is_Drv(fn);
274
    if (drv < 0)
275
    {
276
                memset(res, 0, sizeof(struct stati64));
277
        ZSData.Number = (-drv) - 2;   // stream number
278
        ZSData.OpCode = zsaIdentify;
279
        int r = StreamCB();
280
        ok = (r == CALLBACK_TRUE);
281
 
282
        if (ok)
283
        {
284
            res->st_size = ZSData.ArgLL;
285
            res->st_atime = res->st_mtime = res->st_ctime = dos2unixtime(ZSData.ArgD);
286
            long attr = ZSData.ArgA;
287
            res->st_mode = S_IREAD;
288
 
289
            if (attr & FILE_ATTRIBUTE_DIRECTORY)
290
                res->st_mode |= (S_IFDIR | S_IWRITE | S_IEXEC) ;
291
            else
292
            {
293
                res->st_mode |= (mode_t)S_IFREG;
294
                if ((attr & FILE_ATTRIBUTE_READONLY) == 0)
295
                    res->st_mode |= S_IWRITE;
296
            }
297
 
298
            res->st_nlink = 1;
299
        }
300
    }
301
    else
302
        ok = !_tstati64(fn, res);
303
 
304
    if (ok)
305
    {
306
        lastStatName = fn;
307
        memcpy(&lastStat, res, sizeof(struct stati64));
308
    }
309
 
310
    return ok ? false : true;
311
}
312
 
313
void DZOp::GiveTime(void)
314
{
315
    SYSTEMTIME SystemT;
316
 
317
    if (!Verbose)
318
        return;
319
 
320
    GetSystemTime(& SystemT);
321
 
322
    Notify(IVERBOSE, _T("Time Hour %d, min %d, sec %d msec %d"),
323
           SystemT.wHour, SystemT.wMinute, SystemT.wSecond, SystemT.wMilliseconds);
324
}
325
 
326
 
327
const char* DZOp::AddPW(const DZStrA& pw, bool toFront)
328
{
329
    PWRec *prv, *t, *root = CurPW;
330
    prv = NULL;
331
    t = root;
332
        // find it
333
    while (t)
334
    {
335
        if (!t->Passw && pw.IsEmpty())
336
            break;   // same
337
 
338
        if (t->Passw && !pw.Compare(t->Passw))
339
            break;   // found
340
 
341
        prv = t;
342
        t = t->Next;
343
    }
344
 
345
    if (!t)
346
    {
347
        // new entry
348
        t = new PWRec(pw);
349
 
350
        if (toFront || !prv)
351
        {
352
            t->Next = root;
353
                        CurPW = t;
354
        }
355
        else
356
            prv->Next = t;  // append it
357
    }
358
    else
359
        if (toFront && prv)
360
        {
361
            // move it
362
            prv->Next = t->Next;
363
            t->Next = root;
364
                        CurPW = t;
365
        }
366
 
367
    return t->Passw;
368
}
369
 
370
const BaseRec* DZOp::AddBase(const DZStrW& base, bool toFront)
371
{
372
    DZStrW tmp = base;
373
 
374
    if (tmp.LastChar() != BSLASH)
375
        tmp += BSLASH;
376
 
377
    BaseRec *prv, *t, *root = CurBase;
378
    prv = NULL;
379
    t = root;
380
    // find it
381
    while (t)
382
    {
383
        if (!tmp.CompareNoCase(t->Base))
384
            break;   // found
385
 
386
        prv = t;
387
        t = t->Next;
388
    }
389
 
390
    if (!t)
391
    {
392
        // new entry
393
        t = new BaseRec(tmp);
394
 
395
        if (toFront || !prv)
396
        {
397
            t->Next = root;
398
            CurBase = t;
399
//            root = t;
400
        }
401
        else
402
            prv->Next = t;  // append it
403
    }
404
    else
405
        if (toFront && prv)
406
        {
407
            // move it
408
            prv->Next = t->Next;
409
            t->Next = root;
410
                        CurBase = t;
411
        }
412
 
413
        return (const BaseRec*)t;
414
}
415
 
416
DZStrW __fastcall DZOp::FullPath(const DZStrW &Filename, const BaseRec* base) const
417
{
418
    return base->FullPath(Filename);
419
}
420
 
421
DZStrW __fastcall DZOp::GetFullPath(const DZStrW &Filename) const
422
{
423
    return CurBase->FullPath(Filename);
424
}
425
 
426
/* ===================================================================== */
427
void DZOp::MsgBox(const DZStrW& msg, bool CanCancel)
428
{
429
    DZStrW tmp;
430
        tmp.Format(_T("Message From DelZip dll (%s)"), TypStr());
431
    HWND wHandle = global_handle;
432
 
433
    /* Did the user pass us a good window handle? if not, we can't pop-up a box. */
434
    if (!wHandle)
435
        wHandle = GetDesktopWindow(); // v1.6021
436
 
437
    unsigned int flg = CanCancel ? MB_OKCANCEL | MB_ICONEXCLAMATION : MB_OK;
438
 
439
    /* bring up a dialog box */
440
    if (MessageBox(wHandle, msg, tmp, flg) == IDCANCEL && CanCancel)
441
        Abort_Flag |= GA_CANCEL;  // abort
442
}
443
 
444
 
445
int __fastcall DZOp::DZError(int err, const TCHAR *msg)
446
{
447
    DZStrW errmsg;
448
 
449
    if (fuser_notified_of_abort)
450
        return err;
451
 
452
    fuser_notified_of_abort = 1;
453
    int eno = err & 0xff;
454
    fglobal_error_code = eno;
455
    if (fdll_handles_errors)
456
    {
457
        /* I'm passing the error via the callback just to get it logged in
458
        * the status box - I'm sending it in with a 0 error code to avoid
459
        * a dialog box from the application program. */
460
        if (err & DZM_MessageBit)
461
        {
462
            if (msg)
463
                DZErrMsg = msg;
464
 
465
            errmsg = DZErrMsg;
466
        }
467
        else    // load from resources
468
            errmsg = SystemMsg((DZ__GOOD + eno), msg);
469
 
470
        Notify(0, errmsg);
471
        errmsg.AppendFormat(_T("  code=%x"), err);
472
        MsgBox(errmsg, false);
473
    }
474
    else
475
    {
476
        if (err & DZM_MessageBit)
477
            errmsg = DZErrMsg;
478
 
479
        Notify(err, errmsg);
480
    }
481
 
482
    /* Only application program handles errors. */
483
    return err;
484
}
485
 
486
//#define DZ_ERR_CANCELLED  1
487
//#define DZ_ERR_ABORT   2
488
//#define DZ_ERR_CALLBACK  3
489
//// abort flag values
490
//#define GA_NONE 0               // no error
491
//#define GA_ERROR 1              // processing error
492
//#define GA_CANCEL 2             // callback signalled cancel
493
//#define GA_ABORT 4              // Abort requested
494
//#define GA_EXCEPT 0x10          // callback caught exception
495
//#define GA_EXCEPT2 0x20         // callback caused exception
496
int __fastcall DZOp::Fatal(int err, unsigned flag, bool raise)
497
{
498
    const TCHAR* errs[3] = {_T("User cancelled"), _T("User Abort"), _T("Callback exception")};
499
    const TCHAR* erm = 0;
500
    int e = DZ_ERR(err);
501
    if (e && e <= DZ_ERR_CALLBACK)
502
    {
503
        if (e <= DZ_ERR_CALLBACK)
504
        {
505
            if (!flag)
506
                flag = Abort_Flag;
507
            e = DZ_ERR_CANCELLED;
508
            if (flag & 4)
509
                e = DZ_ERR_ABORT;
510
            if (flag > 4)
511
                e = DZ_ERR_CALLBACK;
512
            err &= ~3;
513
            err |= e;
514
            erm = errs[--e];
515
        }
516
    }
517
    DZError(err, erm);
518
    if (raise)
519
        throw DZException(err, erm);
520
    return err;
521
}
522
 
523
/* ===========================================================================
524
 * This calls the application program and passes status info.
525
 */
526
int __fastcall DZOp::StreamCB(void)
527
{
528
    int ret;
529
 
530
    if (ZStreamFunc)
531
    {
532
        ZSData.Check = STREAM_CHECK;
533
        ZSData.Caller = global_caller; // object instance pointer of caller
534
        try
535
        {
536
            ret = ZStreamFunc(&ZSData);  // call user's program
537
        }
538
        __except(1)
539
        {
540
            Abort_Flag = GA_EXCEPT2;
541
        }
542
    }
543
 
544
    return ret;
545
}
546
 
547
bool DZOp::Skipping(const DZStrW& fn, int err, int typ)
548
{
549
 
550
        CB->Arg1 = err;
551
        CB->Arg2 = typ;
552
        return CB->UserCB(zacSkipped, fn) == CALLBACK_TRUE;
553
//      int usr = CB->UserCB(zacSkipped, fn);
554
//      return /*NoSkipping ? true :*/ usr == CALLBACK_TRUE;   //<<
555
}
556
 
557
/*
558
  Encoded as OEM for
559
        DOS (default)                       FS_FAT
560
        OS/2                                FS_HPFS
561
        Win95/NT with Nico Mak's WinZip     FS_NTFS && host = 5.0
562
  UTF8 is flag is set
563
  except (someone always has to be different)
564
        PKZIP (Win) 2.5, 2.6, 4.0 - mark as FS_FAT but local is Windows ANSI (1252)
565
        PKZIP (Unix) 2.51 - mark as FS_FAT but are current code page
566
*/
567
unsigned __fastcall DZOp::IsEncoded(ush made, unsigned utf) const
568
{
569
const WZIP = (FS_NTFS * 256) + 50;
570
        if (fEncodedAs == zeoAuto)
571
        {
572
                if (utf)
573
                        return zeoUTF8;
574
 
575
                if (!(made & 0xff00) || (made & 0xff00) == 0x0600 || made == WZIP)
576
                        return zeoOEM; // FAT OS/2 or WinZip 5.0
577
 
578
                return zeoNone;
579
        }
580
 
581
        return fEncodedAs;
582
}
583
 
584
ZFilter::ZFilter(DZStrW &spec)
585
{
586
    fspec = spec;
587
    flevel = 0;
588
    fnext = NULL;
589
}
590
 
591
ZFilter::~ZFilter()
592
{
593
    if (fnext)
594
        delete fnext;
595
}
596
 
597
bool __fastcall ZFilter::ISEmpty(void) const
598
{
599
    return fspec.IsEmpty();
600
}
601
 
602
ZFilter * __fastcall ZFilter::Find(const DZStrW &spec)
603
{
604
    ZFilter *l = this;
605
    if (!l || spec.IsEmpty())
606
        return NULL;
607
    while (l)
608
    {
609
        if (ZMatch(l->fspec, spec))
610
            return l;
611
        l = l->Next;
612
    }
613
    return NULL;
614
};
615
 
616
 
617
PWRec::PWRec(const DZStrA &pw)
618
{
619
    fpw = DupStr(pw);
620
    fnext = NULL;
621
}
622
 
623
PWRec::~PWRec()
624
{
625
    delete[] fpw;
626
}
627
 
628
BaseRec::BaseRec(const DZStrW &base)
629
{
630
    DZStrW tmp(base);
631
    TCHAR lc = tmp.LastChar();
632
 
633
    if (lc != _T(':') && lc != BSLASH)
634
        tmp += BSLASH;
635
 
636
    fbase = DupStr(tmp);
637
 
638
    fnext = NULL;
639
}
640
 
641
BaseRec::~BaseRec()
642
{
643
    delete[] fbase;
644
}
645
 
646
DZStrW __fastcall BaseRec::FullPath(const DZStrW& filename) const
647
{
648
    if (!Is_DrvEx(filename))
649
    {
650
        DZStrW tmp(fbase);
651
        tmp += filename;
652
        return tmp;
653
    }
654
 
655
    return filename;
656
}
657
 
658
UserCallback::UserCallback(DZOp *theOwner, bool OpIsZip) : Owner(theOwner)
659
{
660
    callb = Owner->callb;
661
    CBData.HaveWide = 0;
662
    CBData.Caller = Owner->global_caller; // object instance pointer of caller
663
    CBData.Version = DZ_VER_VERSION;
664
    CBData.IsOperationZip = OpIsZip;
665
}
666
 
667
UserCallback::~UserCallback(void)
668
{
669
 
670
}
671
 
672
DZStrA __fastcall UserCallback::GetZCmnt(void) const
673
{
674
    DZStrA tmp;
675
    if (CBData.HaveWide == 0)
676
    {
677
        const char* p = (const char*)CBData.MsgP;
678
        if (p && *p)
679
                {
680
            char *buf = tmp.GetBuffer(CBData.Arg1);
681
            memmove(buf, p, CBData.Arg1);
682
            tmp.ReleaseBuffer(CBData.Arg1);
683
        }
684
    }
685
    return tmp;
686
}
687
 
688
DZStrW __fastcall UserCallback::RetMsg(const void *_msg) const
689
{
690
    DZStrW tmp;
691
    if (CBData.HaveWide == 1)
692
    {
693
        const wchar_t* wp = (const wchar_t*)_msg;
694
        if (wp && *wp)
695
            tmp = wp;
696
        return tmp;
697
    }
698
    const char* p = (const char*)_msg;
699
    if (p && *p)
700
    {
701
        if (CBData.HaveWide == 2)
702
                        tmp = DZStrW(CP_UTF8, p, -1);
703
//            tmp = UTF8ToStr(p, -1);
704
        else
705
            tmp = p;
706
    }
707
    return tmp;
708
}
709
 
710
DZStrW __fastcall UserCallback::GetMsg(void) const
711
{
712
    return RetMsg(CBData.MsgP);
713
}
714
 
715
void __fastcall UserCallback::SetMsg(const DZStrW& value)
716
{
717
    hold = value;
718
    CBData.MsgP = hold.c_str();
719
#ifdef UNICODE
720
    CBData.HaveWide = 1;
721
#else
722
    CBData.HaveWide = 0;
723
#endif;
724
}
725
 
726
DZStrW __fastcall UserCallback::GetMsg2(void) const
727
{
728
    return RetMsg(CBData.MsgP2);
729
}
730
 
731
void __fastcall UserCallback::SetMsg2(const DZStrW& value)
732
{
733
    hold2 = value;
734
    CBData.MsgP2 = hold2.c_str();
735
#ifdef UNICODE
736
    CBData.HaveWide = 1;
737
#else
738
    CBData.HaveWide = 0;
739
#endif;
740
}
741
 
742
 
743
/* This provides the calling program with updated info on what the DLL
744
* is doing.  Regardless of the type of call being made, the user's
745
* function must have a spin of the Windows message loop.  In fact, even
746
* if user isn't using a progress bar, he should still spin the msg
747
* loop upon getting these callbacks (but he doesn't need to do anything
748
* else).  In Delphi, "Application.ProcessMessages;" or
749
*         in BCPPB   "Application->ProcessMessages(); spins the loop.
750
* Here are the types of calls:
751
*
752
*
753
*   ActionCode = 0, zacTick, just roll the loop
754
*
755
*   ActionCode = 1, zacItem,
756
*      we're starting a zip operation on a new file
757
*   (O) FileSize(u64) = filesize of file we're going to operate on
758
*   (O) MsgP = pathname of file
759
*   (O) Written (u64) = [Zip] Bytes written
760
*   IMPORTANT: The user's function must do the math for the progress
761
*   bar upon getting this call.  See the Delphi sample application.
762
*
763
*   ActionCode = 2, zacProgress,
764
*      increment the progress bar
765
*      These calls will occur after every 32K of input file has been
766
*      processed. One additional call is made at the end of each file,
767
*      just to make sure the progress bar is max'ed out - this is also
768
*      critical for files less than 32K in size (this last one will be
769
*      their only one).
770
*   (O) FileSize(u64) = filesize of file we're going to operate on
771
*   (O) Written (u64) = [Zip] Bytes written
772
*
773
*   ActionCode = 3, zacEndOfBatch,
774
*      we're done with a batch of files
775
*          - program flow will quickly return to the user's program.
776
*   NOTE: the end of a every file will always be followed by an
777
*         action of 1 or 3, so a separate call for end of one file
778
*         isn't needed.
779
*   (O) Written (u64) = [Zip] Bytes written
780
*
781
*   ActionCode = 4, zacComment, a routine message is being passed
782
*   (O) Arg1 = error_code - code corresponding to message (not widely used yet)
783
*   (O) MsgP = text of message
784
*
785
*   ActionCode = 5, zacCount,
786
*          the total number of files is being passed.
787
*   (O) Arg1 = The total number of files.
788
*
789
*   ActionCode = 6, zacSize,
790
*      the total file size is being passed.
791
*   (O) FileSize (u64) = The total file size
792
*
793
*   ActionCode = 7, zacNewName,
794
*      the internal filename is being passed.
795
*   (O) MsgP2 = pointer to full filespec
796
*   (O) MsgP = the internal filename as the dll thinks it should be.
797
*   (I) ActionCode = -1 if changed
798
*   (I) MsgP => new internal fileanme
799
//*   (I) Msg = the new internal filename
800
*
801
*   ActionCode = 8, zacPassword,
802
*      get Password
803
*   (O) Arg1 = request count
804
*   (O) MsgP = filename
805
*   (I) ActionCode = -1 if has password
806
*       (I) MsgP => password
807
//*       (I) Msg = password
808
*       (I) Arg1 = request count
809
*   (I) ActionCode = -2 if responded 'cancel'
810
*       (I) Arg1 = request count
811
*   (I) ActionCode = -3 if responded 'cancel all'
812
*       (I) Arg1 = request count
813
*
814
*   Actioncode = 9, zacCRCError,
815
*      CRC32 error during Extract
816
*   (O) Arg1 = Found CRC
817
*   (O) Arg2 = Stored/Expected CRC
818
*   (O) MsgP = File for which the CRC check went wrong.
819
*   (I) ActionCode -1 = extract quietly
820
*                  -2 = extract with warning [default]
821
*                  -3 = delete
822
*
823
*   Actioncode = 10, zacOverwrite,
824
*      Extract(UnZip) Overwrite ask.
825
*   (O) Arg3 = 'older'
826
*   (O) Arg2 = Index
827
*   (O) Arg1 = Overwrite_All
828
*   (O) MsgP = filename
829
*   (I) ActionCode -1 = overwrite
830
*          -2 = don't overwrite
831
*
832
*   Actioncode = 11, zacSkipped,
833
*      Skipped during Extract
834
*   (O) Arg1 = error code
835
*   (O) Arg2 = type
836
*   (O) MsgP = filename
837
*
838
*   Actioncode = 12, zacComment,
839
*      FileComment while adding (ZipDll only)
840
*   (O) MsgP = filename
841
*   (O) MsgP2 = old comment
842
*   (I) ActionCode = -1 if comment changed
843
*       (I) Arg1 = length of new comment
844
*       (I) MsgP = new comment
845
//*       (I) Msg = new comment
846
*
847
*   Actioncode = 13, zacStream,
848
*      Adjust unzip stream size
849
*   (O) FileSize (u64) = required size
850
*   (I) ActionCode = -1 if ok
851
*       (I) MsgP = Memory
852
//*       (I) Msg2P = Memory
853
*
854
*   Actioncode = 14, zacData,
855
*      Set Extra Data  or Compression level
856
*   (O) Arg1 = size of data
857
*   (O) Arg2 = Compression level
858
*   (O) MsgP = filename
859
*   (O) MsgP2 = pointer to data
860
*   (I) ActionCode & 0xff0f = 0xff0f if data changed
861
*       (I) Arg1 = new size of data
862
*       (I) MsgP => new data (data must remain until next callback)
863
//*       (I) Msg = new data (< 512 bytes)
864
//*       (I) MsgP2 = new data (> 512 bytes) (data must remain until next callback)
865
*   (I) ActionCode &0xff0e = 0xff0e if level changed
866
*       (I) (ActionCode & 0xf0) >> 4 = new level (0..9)
867
*
868
*   ActionCode = 15, zacXItem, we're starting a zip operation on a new file
869
*   (O) Arg1 = type - 1 = archive bit 2 = move file
870
*   (O) Filesize = filesize of file we're going to operate on
871
*   (O) MsgP = pathname of file
872
*
873
*   ActionCode = 16, zacXProgress, increment the progress bar
874
*      These calls will occur after every 32K of input file has been
875
*      processed. One additional call is made at the end of each file,
876
*      just to make sure the progress bar is max'ed out - this is also
877
*      critical for files less than 32K in size (this last one will be
878
*      their only one).
879
*   (O) Arg1 = type
880
*   (O) FileSize (u64) = size
881
*
882
*   ActionCode = 17, zacExtName,
883
*      change extract name
884
*   (O) MsgP2 = ? null
885
*   (O) MsgP = filename
886
*   (I) ActionCode = -1 if changed
887
*      (I) MsgP => new name
888
//*      (I) Msg = new name
889
*
890
*   ActionCode = 18, zacNone
891
*
892
*   ActionCode = 19, zacKey
893
*      set or clear operation key
894
*   (O) Arg1 = key
895
*
896
*   ActionCode = 20, zacArg
897
*      Get string argument
898
*
899
*   ActionCode = 21, zacWinErr
900
*      report windows error
901
*   (O) Arg1 = Operation
902
*   (O) Arg2 = Error code
903
*   (O) MsgP = target filespec
904
*   (I) return = 0, give error then abort (default)
905
*              = 1, abort without error
906
*              = 2, retry - presume error fixed
907
*
908
*/
909
 
910
/* ===========================================================================
911
 * This calls the application program and passes status info.
912
 */
913
int __fastcall UserCallback::UserCB(unsigned Action)
914
{
915
    int ret;
916
//    OutputDebugString(L"UserCB - IN");
917
 
918
    if (callb && Abort_Flag <= GA_ABORT)
919
    {
920
        CBData.Written = Owner->fBytesWritten;
921
#ifdef UNICODE
922
        CBData.HaveWide = 1;
923
#else
924
        CBData.HaveWide = 0;
925
#endif;
926
        CBData.ActionCode = Action;
927
        CBData.check = CALLBACK_CHECK;
928
        try
929
        {
930
            ret = callb(&CBData);  // call user's program
931
        }
932
        __except(1)
933
        {
934
            Abort_Flag = GA_EXCEPT2;
935
            ret = CALLBACK_EXCEPTION;
936
    OutputDebugString(L"UserCB - exception");
937
        }
938
 
939
        if (ret < CALLBACK_IGNORED)
940
        {
941
            switch (ret)
942
            {
943
 
944
                case CALLBACK_CANCEL:
945
                    Abort_Flag |= GA_CANCEL;
946
                    break;
947
 
948
                case CALLBACK_ABORT:
949
                    Abort_Flag |= GA_CANCEL;
950
                    break;
951
 
952
                case CALLBACK_EXCEPTION:
953
                    Abort_Flag |= GA_EXCEPT;
954
            }
955
        }
956
    }
957
 
958
        hold.Empty();
959
    hold2.Empty();
960
//    OutputDebugString(L"UserCB - OUT");
961
    return ret;
962
}
963
 
964
int __fastcall UserCallback::UserCB(unsigned Action, const DZStrW& msg)
965
{
966
    Msg = msg;
967
    return UserCB(Action);
968
}
969
 
970
int UserCallback::UserCB(unsigned Action, const DZStrW& msg, const DZStrW& msg2)
971
{
972
    Msg2 = msg2;
973
    Msg = msg;
974
    return UserCB(Action);
975
}
976
 
977
int __fastcall UserCallback::UserMsg(int err, const DZStrW& msg)
978
{
979
    CBData.Arg1 = err;    // error
980
    return UserCB(zacMessage, msg);
981
}
982
 
983
int __fastcall UserCallback::UserProgress(__int64 adv)
984
{
985
    CBData.FileSize = adv;
986
    return UserCB(zacProgress);
987
}
988
 
989
int UserCallback::UserItem(__int64 cnt, const DZStrW& msg)
990
{
991
    CBData.FileSize = cnt;
992
    return UserCB(zacItem, msg);
993
}
994
 
995
int UserCallback::UserXProgress(__int64 adv, int typ)
996
{
997
    CBData.Arg1 = typ;    // type
998
    CBData.FileSize = adv;
999
    return UserCB(zacXProgress);
1000
}
1001
 
1002
int UserCallback::UserXItem(__int64 cnt, int typ, const DZStrW& msg)
1003
{
1004
    CBData.Arg1 = typ;
1005
    CBData.FileSize = cnt;
1006
    return UserCB(zacXItem, msg);
1007
}
1008
 
1009
DZStrW UserCallback::UserArg(int arg, int idx, int *cnt)
1010
{
1011
    DZStrW tmp;
1012
    bool raw = arg > 0x1f;
1013
 
1014
    if (raw)
1015
        arg &= 0x1f;
1016
 
1017
    CBData.Arg1 = arg;    // type
1018
    CBData.Arg3 = idx;
1019
    int r = UserCB(zacArg);
1020
    if (r >= CALLBACK_UNHANDLED)
1021
    {
1022
        if (cnt && (arg == zcbFSpecArgs || arg == zcbFSpecArgsExcl))
1023
            *cnt = CBData.Arg3;
1024
 
1025
        if (r == CALLBACK_TRUE)
1026
        {
1027
            tmp = Msg;
1028
            if (!raw)
1029
            {
1030
                tmp.TrimLeft();  // trim trailing unless password
1031
 
1032
                if (arg != zcbPassword && !tmp.Find(ZPasswordFollows))
1033
                    tmp.TrimRight();
1034
            }
1035
        }
1036
    }
1037
 
1038
    return tmp;
1039
}
1040
 
1041
DZStrA UserCallback::UserZCmnt(void)
1042
{
1043
    DZStrA tmp;
1044
    CBData.Arg1 = zcbComment;    // type
1045
    CBData.Arg3 = 0;
1046
    int r = UserCB(zacArg);
1047
    if (r == CALLBACK_TRUE)
1048
    {
1049
        tmp = GetZCmnt();
1050
    }
1051
 
1052
    return tmp;
1053
}
1054
 
1055
void __cdecl  DZOp::Notify(unsigned err, const TCHAR* szFmt, ...)
1056
{
1057
    DZStrW ret;
1058
    va_list argList;
1059
    va_start(argList, szFmt);
1060
    ret.FormatV(szFmt, argList);
1061
    va_end(argList);
1062
    if (!ret.IsEmpty())
1063
        SendInfo(err, ret);
1064
}
1065
 
1066
DZStrW DZOp::ConvExclFilters(const DZStrW & filters)
1067
{
1068
    DZStrW exc;
1069
    if (filters.IsEmpty())
1070
        return exc;
1071
    int n = 0;
1072
    if (filters[0] == _T('|'))
1073
    {
1074
                exc = _T("|");
1075
        n++;
1076
    }
1077
    int len = filters.length();
1078
    while (n < len)
1079
    {
1080
        int nx = filters.Find(_T('|'), n+1);
1081
        if (nx < 0)
1082
            nx = len + 1;
1083
        DZStrW comp = filters.Mid(n, nx - n);
1084
        n = nx + 1;
1085
        comp.Trim();
1086
                DZStrW p = ex2IntForm(comp, true);
1087
 
1088
        if (!p.IsEmpty())
1089
        {
1090
            if (!exc.IsEmpty())
1091
                exc += _T('|');
1092
            exc += p;
1093
        }
1094
    }
1095
    return exc;
1096
}
1097
 
1098
DZStrW DZOp::MakeExclFilters(void)
1099
{
1100
    DZStrW exc;
1101
    int n = 0;
1102
    while (true)
1103
    {
1104
        DZStrW arg = CB->UserArg(zcbFSpecArgsExcl, n, 0);
1105
 
1106
        if (arg.IsEmpty())
1107
            break;
1108
 
1109
        if (!exc.IsEmpty())
1110
            exc += _T('|');
1111
        exc += arg;
1112
        n++;
1113
    }
1114
 
1115
        return ConvExclFilters(exc);
1116
}
1117
 
1118
 
1119
// Convert the external file name to an "internal" file name form,
1120
//   returning the malloc'ed string, or NULL if not enough memory.
1121
//   I.e. Strip the drive if present, strip the path
1122
//if we
1123
//   don't want one and change the name to 8.3 if needed. Not implemented, but
1124
//   also 'put in' change the short path to a long path.
1125
DZStrW DZOp::ex2IntForm(const DZStrW &exname, bool ignore)
1126
{
1127
    bool  pathput;
1128
 
1129
    if (ignore)
1130
        {
1131
        pathput = true;
1132
    }
1133
    else
1134
        {
1135
        pathput = fpathput;
1136
    }
1137
 
1138
        DZStrW XName(exname);
1139
 
1140
    if (XName.IsEmpty())
1141
        return XName;
1142
 
1143
        DZStrW nname = StrExtSep(XName);
1144
    int p = DriveLen(nname);
1145
 
1146
    int len = nname.length();
1147
    // Strip leading "\" to convert an absolute path into a relative path
1148
 
1149
    while (p < len && nname[p] == BSLASH)
1150
        p++;
1151
 
1152
    // Strip leading "./" as well as drive letter v1.6017
1153
    while ((p + 2) < len && (nname[p] == _T('.') && nname[p + 1] == BSLASH))
1154
        p += 2;
1155
 
1156
    // This is where the dirname gets stripped if user doesn't want it
1157
    if (!pathput)
1158
    {
1159
        int t = nname.ReverseFind(BSLASH);
1160
 
1161
        if (t >= p)
1162
            p = ++t;
1163
    }
1164
 
1165
    if (p)
1166
    {
1167
        nname = nname.Mid(p);
1168
    }
1169
 
1170
    if (nname.length() > MAX_PATH)
1171
    {
1172
        int t = nname.length();
1173
        XName = nname.Left(MAX_PATH);
1174
 
1175
        if (Verbose) // < 0)
1176
            Notify(IWARNING, _T("File name %s is too long [%d]. Truncated to %s"),
1177
                   nname.c_str(), t, XName.c_str());
1178
 
1179
        nname = XName;
1180
    }
1181
 
1182
    return nname;
1183
}
1184