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 <windows.h>
4
 
5
/* ZStrings.cpp
6
 Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
7
 
8
   This file is part of TZipMaster Version 1.9.
9
 
10
    TZipMaster is free software: you can redistribute it and/or modify
11
    it under the terms of the GNU Lesser General Public License as published by
12
    the Free Software Foundation, either version 3 of the License, or
13
    (at your option) any later version.
14
 
15
    TZipMaster is distributed in the hope that it will be useful,
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU Lesser General Public License for more details.
19
 
20
    You should have received a copy of the GNU Lesser General Public License
21
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
22
 
23
    contact: problems@delphizip.org (include ZipMaster in the subject).
24
    updates: http://www.delphizip.org
25
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
26
************************************************************************/
27
 
28
#include "delzip.h"
29
//#include "common.h"
30
#include "ZStrings.h"
31
#include "dz_errs.h"
32
 
33
#undef _DZ_FILE_
34
#define _DZ_FILE_ DZ_ZSTRINGS_CPP
35
//---------------------------------------------------------------------------
36
 
37
DZStrW __fastcall StrIncSep(const DZStrW &p)
38
{
39
    if (!p.IsEmpty() && p.LastChar() != _T('\\') && p.LastChar() != _T(':'))
40
        return p + _T('\\');
41
 
42
    return p;
43
}
44
 
45
DZStrW __fastcall StrExcSep(const DZStrW &p)
46
{
47
    if (!p.IsEmpty() && p.LastChar() == _T('\\'))
48
        return p.Left(p.length() - 1);
49
 
50
    return p;
51
}
52
 
53
DZStrW __fastcall StrIntSep(const DZStrW &str)
54
{
55
    DZStrW tmp(str);
56
    if (!str)
57
        return tmp;
58
    wchar_t *buf = tmp.GetBuffer();
59
    while (*buf)
60
    {
61
        if (*buf == L'\\')
62
            *buf = L'/';
63
        buf++;
64
    }
65
    return tmp;
66
}
67
 
68
DZStrA __fastcall StrIntSep(const DZStrA &str)
69
{
70
    DZStrA tmp(str);
71
    if (!str)
72
        return tmp;
73
    char *buf = tmp.GetBuffer();
74
    while (*buf)
75
    {
76
        if (*buf == '\\')
77
            *buf = '/';
78
        buf++;
79
    }
80
    return tmp;
81
}
82
 
83
DZStrW __fastcall StrExtSep(const DZStrW &str)
84
{
85
    DZStrW tmp(str);
86
    if (!str)
87
        return tmp;
88
    wchar_t *buf = tmp.GetBuffer();
89
    while (*buf)
90
    {
91
        if (*buf == L'/')
92
            *buf = L'\\';
93
        buf++;
94
    }
95
    return tmp;
96
}
97
 
98
DZStrA __fastcall StrExtSep(const DZStrA &str)
99
{
100
    DZStrA tmp(str);
101
    if (!str)
102
        return tmp;
103
    char *buf = tmp.GetBuffer();
104
    while (*buf)
105
    {
106
        if (*buf == '/')
107
            *buf = '\\';
108
        buf++;
109
    }
110
    return tmp;
111
}
112
 
113
//DZStrA __fastcall StrSafe(const DZStrA &str)
114
//{
115
//    DZStrA tmp(str);
116
//    if (!str)
117
//        return tmp;
118
//    char *buf = tmp.GetBuffer();
119
//    while (*buf)
120
//    {
121
//        if (*buf < 0x20)
122
//            *buf = '_';
123
//        if (Is_InA("<>|:;*?\"\'", *buf))
124
//            *buf = '_';
125
//        buf++;
126
//    }
127
//    return tmp;
128
//}
129
 
130
 
131
 
132
const char hx[16] = "0123456789ABCDEF";
133
 
134
DZStrA __fastcall toHex(unsigned val, unsigned cnt)
135
{
136
    DZStrA tmp;
137
    char* bp = tmp.GetBuffer(cnt) + cnt;
138
    int x = cnt;
139
    while (val && x-- > 0)
140
    {
141
        *--bp = hx[val & 0x0f];
142
        val >>= 4;
143
    }
144
    while (x-- > 0)
145
        *--bp = '0';
146
    tmp.ReleaseBuffer(cnt);
147
    return tmp;
148
}
149
 
150
DZStrA __fastcall StrToOEM(const DZStrW &str)
151
{
152
    DZStrA ret;
153
 
154
//    if (!HasExtended(str))
155
        if (!str.BadDOS())
156
    {
157
        ret = str;
158
        return ret;
159
    }
160
 
161
    DZStrW s(str);
162
 
163
//    int mx = 3 + str.length() * 4;   // allow worst case - all double
164
    CharToOem(s, ret.GetBuffer(s.length()));
165
    ret.ReleaseBuffer();
166
    return ret;
167
}
168
 
169
DZStrA __fastcall StrToOEM(const DZStrA &str)
170
{
171
    DZStrA ret;
172
 
173
//    if (!HasExtended(str))
174
        if (!str.BadDOS())
175
    {
176
        ret = str;
177
        return ret;
178
    }
179
 
180
    DZStrW s(str);
181
 
182
//    int mx = 3 + s.length() * 4;   // allow worst case - all double
183
    CharToOem(s, ret.GetBuffer(s.length()));
184
    ret.ReleaseBuffer();
185
    return ret;
186
}
187
 
188
DZStrA __fastcall StrToUTF8(const DZStrW &str)
189
{
190
    DZStrA ret;
191
    //  Convert to required
192
    int cnt = WideCharToMultiByte(CP_UTF8, 0, str, str.length(), NULL, 0, NULL, NULL);
193
 
194
    if (cnt < 1)
195
        return ret;  // invalid
196
    char* bf = ret.GetBuffer(cnt);
197
    cnt = WideCharToMultiByte(CP_UTF8, 0, str, str.length(), bf, cnt, NULL, NULL);
198
    bf[cnt] = 0;
199
    ret.ReleaseBuffer();
200
 
201
    if (cnt < 1)
202
        ret.Empty();
203
 
204
    return ret;
205
}
206
 
207
//DZStrW __fastcall ToStrW(const char *str, int len, UINT cp)
208
//{
209
//    DZStrW retval;
210
//
211
//    // convert to Unicode
212
//    int wcnt = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
213
//
214
//    if (wcnt > 0)
215
//    {
216
//        wchar_t *bf = retval.GetBuffer(wcnt);
217
//        wcnt = MultiByteToWideChar(cp, 0, str, len, bf, wcnt);
218
//        bf[wcnt] = 0;
219
//        retval.ReleaseBuffer();
220
//    }
221
//
222
//    if (wcnt < 1)
223
//        retval.Empty();
224
//
225
//    return retval;
226
//}
227
 
228
 
229
//DZStrW __fastcall UTF8ToStr(const char *str, int len)
230
//{
231
////    return ToStrW(str, len, CP_UTF8);
232
//      return DZStrW(CP_UTF8, str, len);
233
//}
234
 
235
 
236
DZStrW __fastcall OEMToStr(const char *str)
237
{
238
    DZStrW tmp;
239
    OemToChar(str, tmp.GetBuffer(strlen(str) * 5));
240
    tmp.ReleaseBuffer();
241
    DZStrW ret = tmp;
242
    return ret;
243
}
244
/*
245
bool __fastcall HasExtended(const TCHAR* str)
246
{
247
    TCHAR c;
248
    if (!str)
249
        return false;
250
 
251
    for (const TCHAR* p = str; *p; p++)
252
        if ((c = *p) < 0x20 || (c > 0x7e))
253
            return true;
254
 
255
    return false;
256
}
257
 
258
bool __fastcall HasExtended(const DZStrA& str)
259
{
260
    char c;
261
    if (!str)
262
        return false;
263
 
264
    for (const char* p = str.c_str(); *p; p++)
265
        if ((c = *p) < 0x20 || (c > 0x7e))
266
            return true;
267
 
268
    return false;
269
}
270
 
271
bool __fastcall HasExtended(const DZStrW& str)
272
{
273
    wchar_t c;
274
 
275
    if (!str)
276
        return false;
277
    for (const wchar_t* p = str.c_str(); *p; p++)
278
        if ((c = *p) < 0x20 || (c > 0x7e))
279
            return true;
280
 
281
    return false;
282
}
283
*/
284
int __fastcall UTF8SeqLen(char u8)
285
{
286
    if (u8 >= 0) //< 0x80)
287
        return 0;
288
 
289
    if (((unsigned char)u8 & 0xFE) == 0xFC)
290
        return 6;
291
 
292
    if (((unsigned char)u8 & 0xFC) == 0xF8)
293
        return 5;
294
 
295
    if (((unsigned char)u8 & 0xF8) == 0xF0)
296
        return 4;
297
 
298
    if (((unsigned char)u8 & 0xF0) == 0xE0)
299
        return 3;
300
 
301
    if (((unsigned char)u8 & 0xE0) == 0xC0)
302
        return 2;
303
 
304
    return -1;  // trailing byte - invalid
305
}
306
/*
307
// test for valid UTF8 character(s)  > 0 _ some, 0 _ none, < 0 _ invalid
308
int __fastcall ValidUTF8(const char *str, int len)
309
{
310
    int ret = 0;
311
    char ch;
312
 
313
    if (len < 0)
314
        len = strlen(str);
315
 
316
    int i = 0;
317
 
318
    while (i++ < len)
319
    {
320
        if ((ch = *str++) == 0)
321
            return -2;
322
 
323
        int ul = UTF8SeqLen(ch);
324
 
325
        if (ul)
326
        {
327
            if (ul < 0)
328
                return -1;
329
 
330
            // first in seq
331
            while (i++ < len && ul-- > 1)
332
            {
333
                if ((*(const unsigned char*)str++ & 0xC0) != 0x80)
334
                    return -1;
335
            }
336
 
337
            ret++;
338
        }
339
    }
340
 
341
    return ret;
342
}
343
 */
344
// test for valid UTF8 character(s)  > 0 _ some, 0 _ none, < 0 _ invalid
345
int __fastcall ValidUTF8(const DZStrA &str)
346
{
347
        int ret = 0;
348
        char ch;
349
 
350
        if (!str)
351
                return 0;//ret;
352
//      return ValidUTF8(str.c_str());
353
        const char* p = str.c_str();
354
    const char* endp = p + str.length();
355
 
356
    while (p < endp)
357
    {
358
        if ((ch = *p++) == 0)
359
            return -1;      // invalid
360
 
361
        int ul = UTF8SeqLen(ch);
362
 
363
        if (ul)
364
        {
365
            if (ul < 0)
366
                return -1;
367
 
368
            // first in seq
369
            while (ul-- > 1)
370
            {
371
                if (p >= endp)
372
                    return -1;
373
 
374
                ch = *p++;
375
                if (((unsigned char)ch & 0xC0) != 0x80)
376
                    return -1;
377
            }
378
 
379
            ret++;
380
        }
381
    }
382
 
383
        return ret;
384
}
385
 
386
 
387
// return >0 has drive, 0 no drive, -1 stream, -2 autostream
388
int __fastcall Is_Drv(const DZStrW &spec)
389
{
390
    if (spec.length() < 2)
391
        return 0;
392
 
393
    int colon = spec.Find(_T(':'));
394
    if (colon < 1)
395
        return 0;
396
 
397
    TCHAR c = spec[0];
398
    if (colon == 1 && _istalpha(c))
399
      return 1;
400
 
401
    int sno = 0;
402
    for (int i = 0; i < colon; i++)
403
    {
404
        if (!_istdigit(spec[i]))
405
            return 0; // invalid
406
        sno = (sno * 10) + (spec[i] & 15);
407
    }
408
    return -(sno + 2);
409
}
410
 
411
// return >0 has drive, 0 no drive, -1 stream, -2 autostream
412
int __fastcall Is_DrvEx(const DZStrW &spec)
413
{
414
    int r = Is_Drv(spec);
415
 
416
    if (r)
417
        return r;
418
 
419
    if (spec.length() >= 2)
420
    {
421
        TCHAR c = spec[0];
422
 
423
        if ((c == BSLASH && spec[1] == BSLASH) ||
424
                (c == SLASH && spec[1] == SLASH))
425
            return 2;
426
    }
427
 
428
    return 0;
429
}
430
 
431
const TCHAR * __fastcall Is_In(const TCHAR *p, TCHAR c)
432
{
433
    for (; *p; p++)
434
    {
435
        if (*p == c)
436
            return p;
437
    }
438
 
439
    return NULL;
440
}
441
 
442
const char * __fastcall Is_InA(const char *p, char c)
443
{
444
    for (; *p; p++)
445
    {
446
        if (*p == c)
447
            return p;
448
    }
449
 
450
    return NULL;
451
}
452
 
453
//const int Z_BAD_DRIVE = 1;
454
//const int Z_BAD_SEP = 2;
455
//const int Z_BAD_SPACE = 4;      // lead/trail space
456
//const int Z_BAD_CLEN = 8;       // component too long
457
//const int Z_BAD_CHAR = 16;      // invalid char
458
//const int Z_BAD_PARENT = 32;    // attempt to back below root
459
int __fastcall CheckComponent(const DZStrW& c)
460
{
461
    int clen = c.length();
462
 
463
    if (clen < 1)
464
        return Z_BAD_SEP;
465
 
466
    if (_istspace(c[0]) || _istspace(c.LastChar()))
467
        return Z_BAD_SPACE;      // leading/trailing blanks not allowed
468
 
469
    if (clen > 255) //= MAX_PATH-3)
470
        return Z_BAD_CLEN;
471
 
472
#ifdef UNICODE
473
    for(int i=0;i<clen;i++)
474
        if (c[i] < ' ')
475
            return Z_BAD_CHAR;
476
#else
477
    for(int i=0;i<clen;i++)
478
        if (c[i] < ' ' && c[i] >= 0)
479
            return Z_BAD_CHAR;
480
#endif
481
 
482
    if (c.FindOneOf(_T("<>:\"|"))  >= 0)
483
        return Z_BAD_CHAR;
484
 
485
    if (!c.Compare(_T(".")))
486
        return Z_IS_THIS;
487
 
488
    if (!c.Compare(_T("..")))
489
        return Z_IS_PARENT;
490
 
491
//    if (c.Find(_T("..")) >= 0)
492
//        return Z_BAD_CHAR;
493
 
494
    if (Is_In(_T("AaCcLlNnPp"), c[0]))
495
    {
496
        // check invalid names
497
        int dt = c.Find(DOT);
498
 
499
        if (clen >= 3 && (dt > 3 || dt < 0))
500
        {
501
            DZStrW bads(_T("COM,LPT,AUX,CON,NUL,PRN"));
502
            DZStrW f3(c, 3);
503
            f3.ToUpper();
504
            int m = bads.Find(f3);
505
 
506
            if (m >= 0 && !(m & 3))
507
            {
508
                // starts with bad
509
                if (m > 7 && (clen == 3 || c[3] == DOT))
510
                    return Z_BAD_NAME;
511
 
512
                if (clen > 3 && Is_In(_T("123456789"), c[3]) &&
513
                        (clen == 4 || c[4] == DOT))
514
                    return Z_BAD_NAME;
515
            }
516
        }
517
    }
518
 
519
    return 0; // good
520
}
521
 
522
int __fastcall CleanPath(const DZStrW& pathin, DZStrW& pathout)
523
{
524
    int posn = DriveLen(pathin);
525
 
526
    if (posn < 0)
527
        return Z_BAD_DRIVE;
528
 
529
    pathout = pathin.Left(posn);
530
 
531
//      if (posn > 2)
532
                pathout = StrExtSep(pathout);
533
//    else
534
//    {
535
                TCHAR ch = pathin[posn];
536
 
537
                if (ch == BSLASH || ch == SLASH)
538
        {
539
            pathout += BSLASH;
540
            posn++;
541
        }
542
//    }
543
 
544
    int len = pathin.length();
545
 
546
    if (len < 1)
547
        return 0;
548
 
549
        int root = pathout.length() - 1;
550
        int components = 0;
551
 
552
    while (posn < len)
553
    {
554
                // find end of component
555
                int eoc = pathin.FindOneOf(_T("\\/"), posn);
556
        DZStrW c;
557
 
558
        if (eoc < 0)
559
            c = pathin.Mid(posn);  // rest of string
560
        else
561
        {
562
            c = pathin.Mid(posn, eoc - posn);
563
            posn = eoc + 1;    // next component
564
        }
565
 
566
        int r = CheckComponent(c);
567
                if (r == Z_IS_THIS && !components)
568
                        r = 0;
569
 
570
        if (r < 0)
571
        {
572
            if (r > Z_BAD_PARENT)
573
                return r;   // bad
574
 
575
                        if (r == Z_IS_THIS)
576
                                continue;   // '.'
577
 
578
            // backup
579
            int pc = pathout.ReverseFind(BSLASH, pathout.length() - 2);
580
 
581
                        if (pc < 0 && pathout[root] != BSLASH)
582
                pc = root;
583
 
584
            if (pc < root)
585
                return Z_BAD_PARENT;
586
 
587
            pathout = pathout.Left(pc + 1);   // truncate
588
            continue;
589
        }
590
 
591
        pathout += c;
592
 
593
        if (eoc < 0)
594
            break;
595
 
596
                pathout += BSLASH;
597
                components++;
598
    }
599
 
600
    if (pathout.FindOneOf(_T("*?")) >= 0)
601
    {
602
        return Z_WILD;
603
    }
604
 
605
    return 0;
606
}
607
 
608
// return length drive or //host/share/   return < 0 if invalid
609
int __fastcall DriveLen(const DZStrW &fspec)
610
{
611
    int d = Is_DrvEx(fspec);
612
 
613
    if (d == 1)
614
        return 2;
615
 
616
    if (!d)
617
        return 0;
618
 
619
    if (d == -1)
620
        return 2; // default stream
621
 
622
    if (d < 0)
623
    {   // stream
624
        d = 0;
625
        while (_istdigit(fspec[d]))
626
          d++;
627
                return fspec[d] == ':' ? d + 1 : 0;
628
    }
629
 
630
    TCHAR c = fspec[0];
631
    int eoh = fspec.Find(c, 2);
632
 
633
    if (eoh < 0)
634
        return -1;  // invalid
635
 
636
    if (eoh == 4 && fspec[2] == _T('?'))
637
    {
638
        eoh = fspec.Find(c, 2);
639
 
640
                if (eoh < 0)
641
            return 4;  // nothing follows
642
    }
643
 
644
    // find end of host
645
    int eos = fspec.Find(c, eoh + 1);
646
 
647
    if (eos < 0)
648
        return 0;//-2;  // no share
649
 
650
//      return ++eos; // count trailing slash
651
        return eos; // don't count trailing slash
652
}
653
 
654
DWORD __fastcall GetFileAttrs(const DZStrW& p)
655
{
656
    WIN32_FIND_DATA fdata;
657
    HANDLE          fh;
658
    DWORD           ret = -1; // no_file indicator
659
 
660
    fh = FindFirstFile(p, &fdata);
661
 
662
    if (fh != INVALID_HANDLE_VALUE)
663
    {
664
        ret = fdata.dwFileAttributes;
665
        FindClose(fh);
666
    }
667
 
668
    return ret;
669
}
670
 
671
bool __fastcall IsWild(const DZStrW& p)
672
{
673
    int t = p.FindOneOf(_T("?*"));
674
    return t >= 0;
675
}
676
 
677
bool __fastcall Is_AbsPath(const DZStrW& pth)
678
{
679
    return Is_DrvEx(pth) == 0;
680
}
681
TCHAR __fastcall LastChar(const TCHAR *p)
682
{
683
    TCHAR ret = 0;
684
 
685
    if (p)
686
    {
687
        for (; *p; p = _tcsinc(p))
688
            ret = *p;
689
    }
690
 
691
    return ret;
692
}
693
 
694
const char* DupStr(const DZStrA& from)
695
{
696
    char *tmp = NULL;
697
 
698
    if (!from.IsEmpty())
699
    {
700
        tmp = new char[from.length()+1];
701
        strcpy(tmp, from.c_str());
702
    }
703
 
704
    return tmp;
705
}
706
 
707
const wchar_t* DupStr(const DZStrW& from)
708
{
709
    wchar_t* tmp = NULL;
710
 
711
    if (!from.IsEmpty())
712
    {
713
        tmp = new wchar_t[from.length()+1];
714
        wcscpy(tmp, from.c_str());
715
    }
716
 
717
    return tmp;
718
}
719
 
720
DZStrW __fastcall GetArg(const DZStrW &CmdLine, unsigned &idx, bool AllowPW)
721
{
722
        DZStrW ret;
723
        TCHAR ch;
724
        if (CmdLine.IsEmpty() || idx >= CmdLine.length())
725
                return ret;
726
        int Spaces = 0;
727
        const TCHAR *first = CmdLine.c_str() + idx;
728
        const TCHAR *start = first;
729
        const TCHAR *cmd = first;
730
        while (*cmd <= _T(' ') && *cmd)
731
                cmd = CharNext(cmd);
732
  // advance to next, find the length ignoring trailing space
733
        while ((ch = *cmd) != 0)
734
        {
735
                if (ch == _T('/') && Spaces)
736
                        break;  // at next switch
737
                if (AllowPW && ch == ZPasswordFollows)
738
                        break;  // at next (Comment)
739
                if (ch <= ' ')
740
                {
741
                        cmd = CharNext(cmd);
742
                        Spaces++;
743
                        continue;
744
                }
745
 
746
                if (ch == '"')
747
                {
748
                        // copy previous
749
                        ret.Append(start, cmd - start);
750
                        start = cmd;
751
                        start++; // past leading quote
752
                        // find end of quote
753
                        do
754
                        {
755
                                cmd = CharNext(cmd);
756
                        }while (*cmd != _T('"') && *cmd);
757
                        // copy between quotes
758
                        ret.Append(start, cmd - start);
759
 
760
                        start = ++cmd;    // end quote
761
                        Spaces = 0;
762
                        continue;
763
                }
764
 
765
                // just a character
766
                cmd = CharNext(cmd);
767
                Spaces = 0;
768
        }
769
        // copy previous
770
        const TCHAR *lastchar = cmd;
771
        lastchar -= Spaces;
772
        if (lastchar > start)
773
          ret.Append(start, lastchar - start);
774
        idx += cmd - first;
775
 
776
        return ret;
777
}
778
 
779
bool __fastcall DirExists(const DZStrW& path)
780
{
781
        if (path.IsEmpty())
782
                return true;
783
        DWORD Code = ::GetFileAttributes(path.c_str());
784
        return (Code != (unsigned)-1) && (FILE_ATTRIBUTE_DIRECTORY & Code);
785
}
786
 
787
DZStrW __fastcall ExtractFilePath(const DZStrW path)
788
{
789
        int npos = path.ReverseFind(BSLASH);
790
        DZStrW ret;
791
        if (npos > 0)
792
        {
793
                ret = path.Left(npos);
794
        }
795
        return ret;
796
}
797
 
798
bool __fastcall ForceDirectories(const DZStrW Dir, int minlen)
799
{
800
        // never go below the root or server
801
        if (minlen < 3)
802
        {
803
                minlen = DriveLen(Dir);
804
                if (minlen > 0 && Dir[minlen] == BSLASH)
805
                        minlen++;
806
                if (minlen < 3)
807
                        minlen = 3;
808
        }
809
        DZStrW sDir = StrExcSep(Dir);
810
        if (sDir.length() < (unsigned)minlen || DirExists(sDir))
811
                return true;
812
        DZStrW parent = ExtractFilePath(sDir);
813
        if (parent == sDir)
814
                return true; // avoid 'c:\xyz:\' problem.
815
        if (!ForceDirectories(parent, minlen))
816
                return false;
817
        // return true;
818
        return CreateDirectory(sDir.c_str(), NULL);
819
}
820