Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | daniel-mar | 1 | #include "stdafx.h" |
2 | #pragma hdrstop |
||
3 | |||
4 | #include "ZipOp.h" |
||
5 | //--------------------------------------------------------------------------- |
||
6 | |||
7 | #include "enter.h" |
||
8 | #include "dz_errs.h" |
||
9 | |||
10 | #undef _DZ_FILE_ |
||
11 | #define _DZ_FILE_ DZ_ZIPOP_CPP |
||
12 | |||
13 | /* ZGlobals.c |
||
14 | * Copyright (C) 1990-1996 Mark Adler, Richard B. Wales, Jean-loup Gailly, |
||
15 | * Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko. |
||
16 | * Permission is granted to any individual or institution to use, copy, or |
||
17 | * redistribute this software so long as all of the original files are included, |
||
18 | * that it is not sold for profit, and that this copyright notice is retained. |
||
19 | * This version modified by Chris Vleghert for BCB/Delphi Zip. |
||
20 | ** distributed under LGPL license ** see license.txt for details |
||
21 | |||
22 | Copyright (c) 1990-2007 Info-ZIP. All rights reserved. |
||
23 | |||
24 | See the accompanying file LICENSE, version 2007-Mar-4 or later |
||
25 | (the contents of which are also included in zip.h) for terms of use. |
||
26 | If, for some reason, all these files are missing, the Info-ZIP license |
||
27 | also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html |
||
28 | |||
29 | parts Copyright (C) 1997 Mike White, Eric W. Engler |
||
30 | ************************************************************************ |
||
31 | Copyright (C) 2009, 2010 by Russell J. Peters, Roger Aelbrecht |
||
32 | |||
33 | This file is part of TZipMaster Version 1.9. |
||
34 | |||
35 | TZipMaster is free software: you can redistribute it and/or modify |
||
36 | it under the terms of the GNU Lesser General Public License as published by |
||
37 | the Free Software Foundation, either version 3 of the License, or |
||
38 | (at your option) any later version. |
||
39 | |||
40 | TZipMaster is distributed in the hope that it will be useful, |
||
41 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
42 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
43 | GNU Lesser General Public License for more details. |
||
44 | |||
45 | You should have received a copy of the GNU Lesser General Public License |
||
46 | along with TZipMaster. If not, see <http://www.gnu.org/licenses/>. |
||
47 | |||
48 | contact: problems@delphizip.org (include ZipMaster in the subject). |
||
49 | updates: http://www.delphizip.org |
||
50 | DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip |
||
51 | ************************************************************************/ |
||
52 | |||
53 | ZipOp::ZipOp(const DllCommands *C): ZipFunc(C) |
||
54 | { |
||
55 | fnoisy = 1; |
||
56 | |||
57 | fuser_notified_of_abort = 0; |
||
58 | fdll_handles_errors = 1; // By dflt, this DLL will generate error msg boxes |
||
59 | |||
60 | fvolume_label = 0; |
||
61 | fhidden_files = 0; |
||
62 | ffix = 0; |
||
63 | |||
64 | if (C->fOptions.System) // include system and hidden files -S |
||
65 | fhidden_files = 1; |
||
66 | |||
67 | if (C->fOptions.Volume) // Include volume label -$ |
||
68 | fvolume_label = 1; |
||
69 | |||
70 | if (C->fOptions.Quiet || !C->fHandle) |
||
71 | { |
||
72 | // quiet operation -q |
||
73 | fnoisy = 0; // shut us up! |
||
74 | fdll_handles_errors = 0; // All error msgs passed to caller via callback function |
||
75 | } |
||
76 | |||
77 | if (Verbose) |
||
78 | fnoisy = 1; |
||
79 | // give the component the 'key' |
||
80 | CB->Arg1 = ((unsigned)this) >> 2; |
||
81 | Set_Oper(this, ZIPOPER); // add to 'active' list |
||
82 | CB->UserCB(zacKey); |
||
83 | } |
||
84 | |||
85 | ZipOp::~ZipOp(void) |
||
86 | { |
||
87 | Set_Oper(this, 0); // remove from list |
||
88 | CB->Arg1 = 0; |
||
89 | CB->UserCB(zacKey); |
||
90 | // ZipCleanup(); // something may have failed |
||
91 | } |
||
92 | |||
93 | |||
94 | // Add (or exclude) the name of an existing disk file. Return an error code |
||
95 | // in the ZEN_ class. Return DZ_ERR_GOOD if OK. n :: Name to add (or exclude). |
||
96 | // nSize :: Size of the file or dir(0). |
||
97 | int ZipOp::newname(const DZStrW &nme, ZInt64 nSize) |
||
98 | { |
||
99 | FndItem *f; // where in found, or new found entry |
||
100 | ZipItem *z; // where in zfiles (if found) |
||
101 | int dosflag; // force 8x3? |
||
102 | int ErrMsg = DZ_ERR_GOOD; |
||
103 | int levl; // required compression |
||
104 | bool noext = false; // don't ignore extension |
||
105 | |||
106 | DZStrW name, undosm, tmp; |
||
107 | DZStrW iname; |
||
108 | DZStrW m; |
||
109 | // ArgSplitter splitter; |
||
110 | // if (Verbose) |
||
111 | // Notify(IVERBOSE, _T("adding file %s to found list"), nme.c_str()); |
||
112 | int r = CleanPath(nme, name);//, fEncodeAs == zeoNone); |
||
113 | |||
114 | if (r) |
||
115 | { |
||
116 | if (Verbose) |
||
117 | Notify(IERROR, _T("invalid new name %s"), nme.c_str()); |
||
118 | |||
119 | return DZ_ERM_INVAL_NAME; |
||
120 | } |
||
121 | |||
122 | levl = flevel; |
||
123 | do |
||
124 | { |
||
125 | // Just one loop, with this w'll get a better error handling. RCV: 1.605 |
||
126 | dosflag = (fEncodeAs == zeoOEM) ? 3 : 0; |
||
127 | |||
128 | // if (fdosify) |
||
129 | // dosflag = 1; |
||
130 | |||
131 | m = ex2IntForm(name, false); |
||
132 | // Discard directory names with zip -rj |
||
133 | if (m.IsEmpty()) |
||
134 | { |
||
135 | // If extensions needs to be swapped, we will have empty directory |
||
136 | // names instead of the original directory. For example, zipping 'c.', |
||
137 | // 'c.main' should zip only 'main.c' while 'c.' will be converted to |
||
138 | // '\0' by ex2in. |
||
139 | if (fpathput) |
||
140 | throw DZException(DZ_ERM_LOGIC_ERROR); |
||
141 | |||
142 | // ziperr(ZEN_LOGIC05); |
||
143 | break; |
||
144 | } |
||
145 | |||
146 | undosm = m; |
||
147 | |||
148 | if (dosflag || !fpathput) |
||
149 | { |
||
150 | // use default settings |
||
151 | undosm = ex2IntForm(name, true); |
||
152 | if (undosm.IsEmpty()) |
||
153 | undosm = m; |
||
154 | } |
||
155 | |||
156 | // check excluded before going further |
||
157 | if (fpcount && ZMatch(fExcludes, undosm)) |
||
158 | { |
||
159 | // Do not clear z->mark if "exclude", because, when "dosify || |
||
160 | // !pathput" is in effect, two files with different filter options |
||
161 | // may hit the same z entry. |
||
162 | if (Verbose) |
||
163 | Notify(IVERBOSE, _T("excluding %s"), name.c_str()); |
||
164 | |||
165 | break; |
||
166 | } |
||
167 | |||
168 | // **** start of rename check |
||
169 | // Give the user a chance to change the internal name |
||
170 | if (Is_DrvEx(name)) |
||
171 | tmp = name; |
||
172 | else |
||
173 | tmp = GetFullPath(name); // uses current root |
||
174 | |||
175 | CB->Msg2 = tmp;// full path/name |
||
176 | CB->Msg = undosm;// proposed name |
||
177 | if (CB->UserCB(zacNewName) == CALLBACK_TRUE) // changed |
||
178 | { |
||
179 | int nerr;// = 0; |
||
180 | tmp = CB->Msg; |
||
181 | unsigned index = 0; |
||
182 | DZStrW fs; |
||
183 | |||
184 | DZStrW arg = GetArg(tmp, index, false); |
||
185 | nerr = CleanPath(arg, fs); |
||
186 | if (!nerr) |
||
187 | { |
||
188 | if (arg.IsEmpty()) |
||
189 | { |
||
190 | if (Verbose) |
||
191 | Notify(IVERBOSE, _T("caller excluding %s"), tmp.c_str()); |
||
192 | |||
193 | break; |
||
194 | } |
||
195 | // any switches issued |
||
196 | while (!nerr && tmp[index] == '/') |
||
197 | { |
||
198 | // process switches |
||
199 | arg = GetArg(tmp, ++index, false); |
||
200 | if (arg.length() < 1) |
||
201 | continue; |
||
202 | TCHAR ch = arg[0]; // the switch |
||
203 | if (arg.length() == 3 && arg[1] == _T(':') && |
||
204 | (ch == _T('c') || ch == _T('C')) && _istdigit(arg[2])) |
||
205 | { |
||
206 | // new compression level |
||
207 | levl = arg[2] - _T('0'); |
||
208 | noext = true; |
||
209 | continue; |
||
210 | } |
||
211 | nerr = 55; |
||
212 | // if (Verbose) |
||
213 | // Notify(IVERBOSE, _T("invalid switch %s ignored"), arg.c_str()); |
||
214 | } |
||
215 | if (tmp[index] == ZPasswordFollows) |
||
216 | { |
||
217 | nerr = 66; |
||
218 | } |
||
219 | } |
||
220 | if (nerr)// < 0) |
||
221 | { |
||
222 | nerr = DZ_ERM_INVAL_NAME; |
||
223 | Notify(nerr, _T("invalid new name %s"), tmp.c_str()); |
||
224 | return nerr; |
||
225 | } |
||
226 | // prepare the new name |
||
227 | m = ex2IntForm(fs, false); |
||
228 | |||
229 | // Discard directory names with zip -rj |
||
230 | if (m.IsEmpty()) |
||
231 | { |
||
232 | // If extensions needs to be swapped, we will have empty directory |
||
233 | // names instead of the original directory. For example, zipping 'c.', |
||
234 | // 'c.main' should zip only 'main.c' while 'c.' will be converted to |
||
235 | // '\0' by ex2in. |
||
236 | if (fpathput) |
||
237 | throw DZException(DZ_ERM_LOGIC_ERROR); |
||
238 | break; |
||
239 | } |
||
240 | |||
241 | if (dosflag || !fpathput) |
||
242 | { |
||
243 | undosm = ex2IntForm(name, true); |
||
244 | if (undosm.IsEmpty()) |
||
245 | undosm = m; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | // Search for name in zip file. If there, mark it, else add to list of |
||
250 | // new names to do (or remove from that list). |
||
251 | // if ((z = zsearch(undosm)) != NULL) |
||
252 | if ((z = zsearch(m)) != NULL) |
||
253 | { |
||
254 | z->mark = 1; |
||
255 | z->XName = name; |
||
256 | z->Passw = fkey; // p RP 173 current password |
||
257 | z->Base = CurBase->Base; |
||
258 | z->options.keepver = fversion ? 1 : 0; |
||
259 | #ifdef FORCE_NEWNAME |
||
260 | z->IName = m;//undosm; |
||
261 | #endif |
||
262 | |||
263 | // Better keep the old name. Useful when updating on MSDOS a zip |
||
264 | // file made on Unix. |
||
265 | z->options.dosflag = dosflag & 3; // want OEM |
||
266 | #ifdef _ZDEBUG |
||
267 | Notify(ITRACE, _T("newname 1: %s dosflag %i"), z->iname, z->options.dosflag); |
||
268 | #endif |
||
269 | |||
270 | if (Verbose) |
||
271 | Notify(IVERBOSE, _T("including %s"), name.c_str()); |
||
272 | |||
273 | if (name == flabel) |
||
274 | flabel = z->iname; |
||
275 | } |
||
276 | else |
||
277 | { |
||
278 | // not in zipfile already - add to or remove from list |
||
279 | // if (!pcount || filter(undosm, pG)) RP cannot get here if excluded |
||
280 | // Check that we are not adding the zip file to itself. This catches |
||
281 | // cases like "zip -m foo ../dir/foo.zip". SLASH |
||
282 | if (SameNameExt(fzipfile, name)) // check likely same |
||
283 | { |
||
284 | |||
285 | struct stati64 statb; |
||
286 | |||
287 | if (fzipstate == -1) |
||
288 | { |
||
289 | fzipstate = /*fzipfile.CompareExact(_T("-")) &&*/ |
||
290 | _tstati64(fzipfile, &fzipstatb) == 0; |
||
291 | } |
||
292 | |||
293 | if (fzipstate == 1 |
||
294 | && (statb = fzipstatb, ZStat(GetFullPath(name), &statb) == 0 |
||
295 | && fzipstatb.st_mode == statb.st_mode |
||
296 | && fzipstatb.st_ino == statb.st_ino |
||
297 | && fzipstatb.st_dev == statb.st_dev |
||
298 | && fzipstatb.st_uid == statb.st_uid |
||
299 | && fzipstatb.st_gid == statb.st_gid |
||
300 | && fzipstatb.st_size == statb.st_size |
||
301 | && fzipstatb.st_mtime == statb.st_mtime |
||
302 | && fzipstatb.st_ctime == statb.st_ctime |
||
303 | )) |
||
304 | { |
||
305 | // Don't compare a_time since we are reading the file |
||
306 | break; // is same |
||
307 | } |
||
308 | } |
||
309 | |||
310 | // allocate space and add to list |
||
311 | f = new FndItem; |
||
312 | *(ffnxt) = f; |
||
313 | // f->lst = ffnxt; |
||
314 | f->nxt = NULL; |
||
315 | ffnxt = &f->nxt; |
||
316 | ffcount++; |
||
317 | f->xname = name; |
||
318 | f->Passw = fkey; // p 173 |
||
319 | f->Base = CurBase->Base; |
||
320 | f->options.keepver = fversion ? 1 : 0; |
||
321 | f->IName = m;//undosm; |
||
322 | f->options.dosflag = dosflag & 3; // want OEM |
||
323 | f->options.level = levl & 15; |
||
324 | f->options.noext = (noext || fNoExtChk) ? 1 : 0; |
||
325 | f->len = nSize; // RCV added. |
||
326 | if (name == flabel) |
||
327 | flabel = f->iname; |
||
328 | #ifdef _ZDEBUG |
||
329 | Notify(ITRACE, _T("newname 2: %s dosflag %i"), f->xname, f->options.dosflag); |
||
330 | #endif |
||
331 | } |
||
332 | |||
333 | break; |
||
334 | } |
||
335 | while (true); |
||
336 | |||
337 | return ErrMsg; |
||
338 | } |
||
339 | |||
340 | #define PATHCUT _T('\\') |
||
341 | // If the file name *s has a dot (other than the first char), or if the -A |
||
342 | // option is used (adjust self-extracting file) then return the name, |
||
343 | // otherwise append .zip to the name. Allocate the space for the name in |
||
344 | // either case. Return a pointer to the new name, or NULL if malloc() fails. |
||
345 | // s :: File name to force to zip. |
||
346 | DZStrW ZipOp::ziptyp(const DZStrW &s) |
||
347 | { |
||
348 | DZStrW tmp; |
||
349 | |||
350 | if (s.IsEmpty()) |
||
351 | return tmp; |
||
352 | |||
353 | unsigned res = GetFullPathName(s, MAX_PATH, tmp.GetBuffer(MAX_PATH), NULL); |
||
354 | |||
355 | tmp.ReleaseBuffer(res); |
||
356 | |||
357 | if (tmp.IsEmpty() || !fadjust) |
||
358 | return tmp; |
||
359 | |||
360 | int sp = tmp.ReverseFind(BSLASH); |
||
361 | |||
362 | if (tmp.ReverseFind(_T('.')) <= sp) |
||
363 | tmp += _T(".zip"); |
||
364 | |||
365 | return tmp; |
||
366 | } |
||
367 | |||
368 | |||
369 | |||
370 | DZOp *MakeZipper(const DllCommands *C) |
||
371 | { |
||
372 | return new ZipOp(C); |
||
373 | } |
||
374 | |||
375 | int ZEN_Rank(int err) |
||
376 | { |
||
377 | int t = DZ_ERR(err); |
||
378 | if (t == DZ_ERR_MISS || t == DZ_ERR_INVAL_NAME) |
||
379 | return -1; |
||
380 | return t; |
||
381 | } |