1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF) */
3 /* (C) Copyright IBM Corp. 2004, 2005 */
4 /* */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
6 /*****************************************************************************/
7
8 #include "STAF.h"
9 #include "STAFString.h"
10 #include "STAFTrace.h"
11 #include "STAFMutexSem.h"
12 #include "STAFCommandParser.h"
13 #include "STAFServiceInterface.h"
14 #include "STAFUtil.h"
15 #include "STAFFileSystem.h"
16
17 #include <vector>
18 #include <map>
19
20 #include "zlib.h"
21
22 #include "STAFZip.h"
23 #include "STAFZipUtil.h"
24 #include "STAFZipFileHeader.h"
25 #include "STAFZipFileAttribute.h"
26 #include "STAFZipCentralDirExtension.h"
27 #include "STAFZipLocalFileHeader.h"
28 #include "STAFZipCentralDirEndRecord.h"
29 #include "STAFZipCentralDir.h"
30 #include "STAFZipFile.h"
31 #include "STAFZipMutexLock.h"
32
33
34
35 // STAFZip Service Data
36 struct STAFZipServiceData
37 {
38 unsigned int fDebugMode; // Debug Mode flag
39 STAFString fShortName; // Short service name
40 STAFString fName; // Registered service name
41 STAFString fLocalMachineName; // Logical identifier for the local
42 // machine
43 STAFHandlePtr fHandlePtr; // STAFZip service's STAF handle
44 STAFCommandParserPtr fAddParser; // STAFZip ADD command parser
45 STAFCommandParserPtr fUnzipParser; // STAFZip UNZIP command parser
46 STAFCommandParserPtr fListParser; // STAFZip LIST command parser
47 STAFCommandParserPtr fDeleteParser; // STAFZip DELETE command parser
48 STAFCommandParserPtr fHelpParser; // STAFZip HELP command parser
49 STAFCommandParserPtr fVersionParser; // STAFZip VERSION command parser
50 };
51
52 // static STAFZipMutexLock class
53 static STAFZipMutexLock zipLock;
54
55
56 // Static Variables
57
58 static STAFString sHelpMsg;
59 static STAFString sLineSep;
60 static const STAFString sVersionInfo("3.4.1");
61 // 3.0.0 Original release
62 // 3.0.1 Bug 1012202: Can't read permission info in the latest InfoZip archive
63 // 3.0.2 Bug 1033654: Error inflate file
64 // 3.0.3 Feature 1055682: Improve unzip's performance on large files
65 // 3.0.4 Bug 1076948: zero bytes when unzipping JAR archives
66 // 3.0.5 Feature 1084669: Move Zip archive handling out of STAFZipFile class
67 // Bug 1084676: unable to unzip symbolic link on SuSE Linux
68 // 3.3.0 Feature 2637949: Provides support for zip files >= 2G
69 // ...
70 // 3.4.1 Bug 3530590: Zip service does not preserve all files' permissions
71 // on Unix 64-bit systems when using the RESTOREPERMISSIONS option
72
73 static const STAFString sLocal("local");
74 static const STAFString sHelp("help");
75 static const STAFString sVar("var");
76 static const STAFString sResStrResolve("RESOLVE REQUEST ");
77 static const STAFString sString(" STRING ");
78 static const STAFString sLeftCurlyBrace(kUTF8_LCURLY);
79
80 // Prototypes
81
82 static STAFResultPtr handleAdd(STAFServiceRequestLevel30 *,
83 STAFZipServiceData *, STAFString *);
84 static STAFResultPtr handleUnzip(STAFServiceRequestLevel30 *,
85 STAFZipServiceData *, STAFString *);
86 static STAFResultPtr handleList(STAFServiceRequestLevel30 *,
87 STAFZipServiceData *, STAFString *);
88 static STAFResultPtr handleDelete(STAFServiceRequestLevel30 *,
89 STAFZipServiceData *, STAFString *);
90 static STAFResultPtr handleHelp(STAFServiceRequestLevel30 *,
91 STAFZipServiceData *);
92 static STAFResultPtr handleVersion(STAFServiceRequestLevel30 *,
93 STAFZipServiceData *);
94
95 static STAFResultPtr resolveStr(STAFServiceRequestLevel30 *pInfo,
96 STAFZipServiceData *pData,
97 const STAFString &theString);
98
99 static STAFResultPtr resolveOp(STAFServiceRequestLevel30 *pInfo,
100 STAFZipServiceData *pData,
101 STAFCommandParseResultPtr &parsedResult,
102 const STAFString &fOption,
103 unsigned int optionIndex = 1);
104
105 STAFResultPtr resolveOpLocal(STAFZipServiceData *pData,
106 STAFCommandParseResultPtr &parsedResult,
107 const STAFString &fOption,
108 unsigned int optionIndex = 1);
109
110 static void registerHelpData(STAFZipServiceData *pData,
111 unsigned int errorNumber,
112 const STAFString &shortInfo,
113 const STAFString &longInfo);
114
115 static void unregisterHelpData(STAFZipServiceData *pData,
116 unsigned int errorNumber);
117
118
119 // Begin implementation
120
STAFServiceGetLevelBounds(unsigned int levelID,unsigned int * minimum,unsigned int * maximum)121 STAFRC_t STAFServiceGetLevelBounds(unsigned int levelID,
122 unsigned int *minimum,
123 unsigned int *maximum)
124 {
125 switch (levelID)
126 {
127 case kServiceInfo:
128 {
129 *minimum = 30;
130 *maximum = 30;
131 break;
132 }
133 case kServiceInit:
134 {
135 *minimum = 30;
136 *maximum = 30;
137 break;
138 }
139 case kServiceAcceptRequest:
140 {
141 *minimum = 30;
142 *maximum = 30;
143 break;
144 }
145 case kServiceTerm:
146 case kServiceDestruct:
147 {
148 *minimum = 0;
149 *maximum = 0;
150 break;
151 }
152 default:
153 {
154 return kSTAFInvalidAPILevel;
155 }
156 }
157
158 return kSTAFOk;
159 }
160
161
STAFServiceConstruct(STAFServiceHandle_t * pServiceHandle,void * pServiceInfo,unsigned int infoLevel,STAFString_t * pErrorBuffer)162 STAFRC_t STAFServiceConstruct(STAFServiceHandle_t *pServiceHandle,
163 void *pServiceInfo, unsigned int infoLevel,
164 STAFString_t *pErrorBuffer)
165 {
166 STAFRC_t rc = kSTAFUnknownError;
167
168 try
169 {
170 if (infoLevel != 30) return kSTAFInvalidAPILevel;
171
172 STAFServiceInfoLevel30 *pInfo =
173 reinterpret_cast<STAFServiceInfoLevel30 *>(pServiceInfo);
174
175 STAFZipServiceData data;
176 data.fDebugMode = 0;
177 data.fShortName = pInfo->name;
178 data.fName = "STAF/Service/";
179 data.fName += pInfo->name;
180
181 for (unsigned int i = 0; i < pInfo->numOptions; ++i)
182 {
183 if (STAFString(pInfo->pOptionName[i]).upperCase() == "DEBUG")
184 {
185 data.fDebugMode = 1;
186 }
187 else
188 {
189 STAFString optionError(pInfo->pOptionName[i]);
190 *pErrorBuffer = optionError.adoptImpl();
191 return kSTAFServiceConfigurationError;
192 }
193 }
194
195 // Set service handle
196
197 *pServiceHandle = new STAFZipServiceData(data);
198
199 return kSTAFOk;
200 }
201 catch (STAFException &e)
202 {
203 STAFString result;
204
205 result += STAFString("In STAFZip.cpp: STAFServiceConstruct")
206 + kUTF8_SCOLON;
207
208 result += STAFString("Name: ") + e.getName() + kUTF8_SCOLON;
209 result += STAFString("Location: ") + e.getLocation() + kUTF8_SCOLON;
210 result += STAFString("Text: ") + e.getText() + kUTF8_SCOLON;
211 result += STAFString("Error code: ") + e.getErrorCode() + kUTF8_SCOLON;
212
213 *pErrorBuffer = result.adoptImpl();
214 }
215 catch (...)
216 {
217 STAFString error("STAFZip.cpp: STAFServiceConstruct: "
218 "Caught unknown exception");
219 *pErrorBuffer = error.adoptImpl();
220 }
221
222 return kSTAFUnknownError;
223 }
224
225
STAFServiceInit(STAFServiceHandle_t serviceHandle,void * pInitInfo,unsigned int initLevel,STAFString_t * pErrorBuffer)226 STAFRC_t STAFServiceInit(STAFServiceHandle_t serviceHandle,
227 void *pInitInfo, unsigned int initLevel,
228 STAFString_t *pErrorBuffer)
229 {
230 STAFRC_t retCode = kSTAFUnknownError;
231
232 try
233 {
234 if (initLevel != 30) return kSTAFInvalidAPILevel;
235
236 STAFZipServiceData *pData =
237 reinterpret_cast<STAFZipServiceData *>(serviceHandle);
238
239 STAFServiceInitLevel30 *pInfo =
240 reinterpret_cast<STAFServiceInitLevel30 *>(pInitInfo);
241
242 retCode = STAFHandle::create(pData->fName, pData->fHandlePtr);
243
244 if (retCode != kSTAFOk)
245 return retCode;
246
247
248 //ADD options
249 pData->fAddParser = STAFCommandParserPtr(new STAFCommandParser,
250 STAFCommandParserPtr::INIT);
251 pData->fAddParser->addOption("ADD", 1,
252 STAFCommandParser::kValueNotAllowed);
253 // This option has been deprecated
254 pData->fAddParser->addOption("ZIP", 1,
255 STAFCommandParser::kValueNotAllowed);
256 pData->fAddParser->addOption("ZIPFILE", 1,
257 STAFCommandParser::kValueRequired);
258 pData->fAddParser->addOption("FILE", 1,
259 STAFCommandParser::kValueRequired);
260 pData->fAddParser->addOption("DIRECTORY", 1,
261 STAFCommandParser::kValueRequired);
262 pData->fAddParser->addOption("RELATIVETO", 1,
263 STAFCommandParser::kValueRequired);
264 pData->fAddParser->addOption("RECURSE", 1,
265 STAFCommandParser::kValueNotAllowed);
266
267 pData->fAddParser->addOptionNeed("ADD", "ZIPFILE");
268 pData->fAddParser->addOptionNeed("RELATIVETO", "ADD");
269 pData->fAddParser->addOptionNeed("RELATIVETO", "ZIPFILE");
270 pData->fAddParser->addOptionNeed("RELATIVETO", "ADD");
271 pData->fAddParser->addOptionNeed("RECURSE", "ADD");
272 pData->fAddParser->addOptionNeed("RECURSE", "ZIPFILE");
273 pData->fAddParser->addOptionNeed("RECURSE", "DIRECTORY");
274 pData->fAddParser->addOptionNeed("ADD", "FILE DIRECTORY");
275 pData->fAddParser->addOptionNeed("FILE DIRECTORY", "ADD");
276 pData->fAddParser->addOptionGroup("FILE DIRECTORY", 0, 1);
277
278 //UNZIP options
279 pData->fUnzipParser = STAFCommandParserPtr(new STAFCommandParser,
280 STAFCommandParserPtr::INIT);
281 pData->fUnzipParser->addOption("UNZIP", 1,
282 STAFCommandParser::kValueNotAllowed);
283 pData->fUnzipParser->addOption("ZIPFILE", 1,
284 STAFCommandParser::kValueRequired);
285 pData->fUnzipParser->addOption("FILE", 0,
286 STAFCommandParser::kValueRequired);
287 pData->fUnzipParser->addOption("DIRECTORY", 0,
288 STAFCommandParser::kValueRequired);
289 pData->fUnzipParser->addOption("TODIRECTORY", 1,
290 STAFCommandParser::kValueRequired);
291 pData->fUnzipParser->addOption("REPLACE", 1,
292 STAFCommandParser::kValueNotAllowed);
293 pData->fUnzipParser->addOption("RESTOREPERMISSION", 1,
294 STAFCommandParser::kValueNotAllowed);
295
296 pData->fUnzipParser->addOptionNeed("UNZIP", "ZIPFILE");
297 pData->fUnzipParser->addOptionNeed("UNZIP", "TODIRECTORY");
298 pData->fUnzipParser->addOptionNeed("FILE DIRECTORY", "UNZIP");
299 pData->fUnzipParser->addOptionNeed("FILE DIRECTORY", "ZIPFILE");
300 pData->fUnzipParser->addOptionNeed("FILE DIRECTORY", "TODIRECTORY");
301
302 pData->fUnzipParser->addOptionNeed("REPLACE", "UNZIP");
303 pData->fUnzipParser->addOptionNeed("REPLACE", "ZIPFILE");
304 pData->fUnzipParser->addOptionNeed("REPLACE", "TODIRECTORY");
305
306 pData->fUnzipParser->addOptionNeed("RESTOREPERMISSION", "UNZIP");
307 pData->fUnzipParser->addOptionNeed("RESTOREPERMISSION", "ZIPFILE");
308 pData->fUnzipParser->addOptionNeed("RESTOREPERMISSION", "TODIRECTORY");
309
310
311 //LIST options
312 pData->fListParser = STAFCommandParserPtr(new STAFCommandParser,
313 STAFCommandParserPtr::INIT);
314 pData->fListParser->addOption("LIST", 1,
315 STAFCommandParser::kValueNotAllowed);
316 pData->fListParser->addOption("ZIPFILE", 1,
317 STAFCommandParser::kValueRequired);
318 pData->fListParser->addOptionNeed("LIST", "ZIPFILE");
319
320
321 //DELETE options
322 pData->fDeleteParser = STAFCommandParserPtr(new STAFCommandParser,
323 STAFCommandParserPtr::INIT);
324 pData->fDeleteParser->addOption("DELETE", 1,
325 STAFCommandParser::kValueNotAllowed);
326 pData->fDeleteParser->addOption("ZIPFILE", 1,
327 STAFCommandParser::kValueRequired);
328 pData->fDeleteParser->addOption("FILE", 0,
329 STAFCommandParser::kValueRequired);
330 pData->fDeleteParser->addOption("CONFIRM", 1,
331 STAFCommandParser::kValueNotAllowed);
332 pData->fDeleteParser->addOptionNeed("DELETE", "ZIPFILE");
333 pData->fDeleteParser->addOptionNeed("DELETE", "FILE");
334 pData->fDeleteParser->addOptionNeed("DELETE", "CONFIRM");
335
336
337 //HELP options
338 pData->fHelpParser = STAFCommandParserPtr(new STAFCommandParser,
339 STAFCommandParserPtr::INIT);
340 pData->fHelpParser->addOption("HELP", 1,
341 STAFCommandParser::kValueNotAllowed);
342
343 //VERSION options
344 pData->fVersionParser = STAFCommandParserPtr(new STAFCommandParser,
345 STAFCommandParserPtr::INIT);
346 pData->fVersionParser->addOption("VERSION", 1,
347 STAFCommandParser::kValueNotAllowed);
348
349 // Get line separator
350
351 STAFResultPtr result = pData->fHandlePtr->submit(
352 "local", "VAR", "RESOLVE STRING {STAF/Config/Sep/Line}");
353 if (result->rc != 0)
354 {
355 *pErrorBuffer = result->result.adoptImpl();
356 return result->rc;
357 }
358 else sLineSep = result->result;
359
360 // Get local machine name (logical identifier)
361
362 result = pData->fHandlePtr->submit(
363 "local", "VAR", "RESOLVE STRING {STAF/Config/Machine}");
364
365 if (result->rc != 0)
366 {
367 *pErrorBuffer = result->result.adoptImpl();
368 return result->rc;
369 }
370 else pData->fLocalMachineName = result->result;
371
372 // Assign the help text string for the service
373
374 sHelpMsg = STAFString("*** ") + pData->fShortName + " Service Help ***" +
375 sLineSep + sLineSep +
376 "UNZIP ZIPFILE <Name> TODIRECTORY <Name>" +
377 sLineSep +
378 " [FILE <Name>]... [DIRECTORY <Name>]..." +
379 sLineSep +
380 " [RESTOREPERMISSION] [REPLACE]" +
381 sLineSep + sLineSep +
382 "ADD ZIPFILE <Name> < FILE <Name> | DIRECTORY <Name> [RECURSE] >" +
383 sLineSep +
384 " [RELATIVETO <Directory>]" +
385 sLineSep + sLineSep +
386 "DELETE ZIPFILE <Name> FILE <Name> [FILE <Name>]... CONFIRM" +
387 sLineSep + sLineSep +
388 "LIST ZIPFILE <Name>" +
389 sLineSep + sLineSep +
390 "VERSION" +
391 sLineSep + sLineSep +
392 "HELP";
393
394 // Note: The ADD request syntax is preferred over the ZIP ADD request
395 // syntax (so only documented the ADD request in the above help text).
396
397 // Register help information for service errors
398
399 registerHelpData(pData, kZIPGeneralZipError,
400 STAFString("General Zip Error"),
401 STAFString("ZIP service returns a general error "));
402
403 registerHelpData(pData, kZIPNotEnoughMemory,
404 STAFString("Not Enought Memory"),
405 STAFString("There is not enough memory in system "));
406
407 registerHelpData(pData, kZIPChangeFileSizeError,
408 STAFString("Change File Size Error"),
409 STAFString("Change file size is unsuccessful "));
410
411 registerHelpData(pData, kZIPErrorCreatingDir,
412 STAFString("Error Creating Dir"),
413 STAFString("Creating dir is unsuccessful "));
414
415 registerHelpData(pData, kZIPInvalidZipFile,
416 STAFString("Invalid Zip File"),
417 STAFString("The Zip archive has an invalid format "));
418
419 registerHelpData(pData, kZIPBadCRC,
420 STAFString("Bad CRC"),
421 STAFString("Bad CRC in the Zip archive "));
422
423 registerHelpData(pData, kZIPInvalidOwnerGroup,
424 STAFString("Invalid Owner Group"),
425 STAFString("Owner or Group does not exist in system "));
426
427 registerHelpData(pData, kZIPInvalidFileMode,
428 STAFString("Invalid File Mode"),
429 STAFString("Cannot set the file's mode (permission) in system "));
430
431 }
432 catch (STAFException &e)
433 {
434 STAFString result;
435
436 result += STAFString("In STAFZip.cpp: STAFServiceInit")
437 + kUTF8_SCOLON;
438
439 result += STAFString("Name: ") + e.getName() + kUTF8_SCOLON;
440 result += STAFString("Location: ") + e.getLocation() + kUTF8_SCOLON;
441 result += STAFString("Text: ") + e.getText() + kUTF8_SCOLON;
442 result += STAFString("Error code: ") + e.getErrorCode() + kUTF8_SCOLON;
443
444 *pErrorBuffer = result.adoptImpl();
445 }
446 catch (...)
447 {
448 STAFString error("STAFZip.cpp: STAFServiceInit: "
449 "Caught unknown exception");
450 *pErrorBuffer = error.adoptImpl();
451 }
452
453 return retCode;
454 }
455
456
STAFServiceAcceptRequest(STAFServiceHandle_t serviceHandle,void * pRequestInfo,unsigned int reqLevel,STAFString_t * pResultBuffer)457 STAFRC_t STAFServiceAcceptRequest(STAFServiceHandle_t serviceHandle,
458 void *pRequestInfo, unsigned int reqLevel,
459 STAFString_t *pResultBuffer)
460 {
461 if (reqLevel != 30) return kSTAFInvalidAPILevel;
462
463 STAFRC_t retCode = kSTAFUnknownError;
464
465 STAFString mutexName("STAFZIPMUTEX:");
466
467 try
468 {
469 STAFResultPtr result(new STAFResult(),
470 STAFResultPtr::INIT);
471
472 STAFServiceRequestLevel30 *pInfo =
473 reinterpret_cast<STAFServiceRequestLevel30 *>(pRequestInfo);
474
475 STAFZipServiceData *pData =
476 reinterpret_cast<STAFZipServiceData *>(serviceHandle);
477
478 STAFString request(pInfo->request);
479 STAFString action = request.subWord(0, 1).toLowerCase();
480
481 // Call functions for the request
482
483 if (action == "add" || action == "zip")
484 result = handleAdd(pInfo, pData, &mutexName);
485 else if (action == "unzip")
486 result = handleUnzip(pInfo, pData, &mutexName);
487 else if (action == "list")
488 result = handleList(pInfo, pData, &mutexName);
489 else if (action == "delete")
490 result = handleDelete(pInfo, pData, &mutexName);
491 else if (action == "help")
492 result = handleHelp(pInfo, pData);
493 else if (action == "version")
494 result = handleVersion(pInfo, pData);
495 else
496 {
497 STAFString errMsg = STAFString("'") + request.subWord(0, 1) +
498 "' is not a valid command request for the " +
499 pData->fShortName + " service" + sLineSep + sLineSep +
500 sHelpMsg;
501
502 result = STAFResultPtr(new STAFResult(
503 kSTAFInvalidRequestString, errMsg), STAFResultPtr::INIT);
504 }
505
506 *pResultBuffer = result->result.adoptImpl();
507 retCode = result->rc;
508 }
509 catch (STAFException &e)
510 {
511 retCode = e.getErrorCode();
512
513 STAFString result;
514
515 result += STAFString("In STAFZip.cpp: STAFServiceAcceptRequest")
516 + kUTF8_SCOLON;
517
518 result += STAFString("Name: ") + e.getName() + kUTF8_SCOLON;
519 result += STAFString("Location: ") + e.getLocation() + kUTF8_SCOLON;
520 result += STAFString("Text: ") + e.getText() + kUTF8_SCOLON;
521 result += STAFString("Error code: ") + e.getErrorCode() + kUTF8_SCOLON;
522
523 *pResultBuffer = result.adoptImpl();
524 }
525 catch (...)
526 {
527 STAFString error("STAFZip.cpp: STAFServiceAcceptRequest: "
528 "Caught unknown exception");
529 *pResultBuffer = error.adoptImpl();
530 }
531
532 if (mutexName.length() > STAFString("STAFZIPMUTEX:").length())
533 {
534 // release the mutex
535 zipLock.release(mutexName);
536 }
537
538 return retCode;
539 }
540
541
STAFServiceTerm(STAFServiceHandle_t serviceHandle,void * pTermInfo,unsigned int termLevel,STAFString_t * pErrorBuffer)542 STAFRC_t STAFServiceTerm(STAFServiceHandle_t serviceHandle,
543 void *pTermInfo, unsigned int termLevel,
544 STAFString_t *pErrorBuffer)
545 {
546 if (termLevel != 0) return kSTAFInvalidAPILevel;
547
548 STAFRC_t retCode = kSTAFUnknownError;
549
550 try
551 {
552 retCode = kSTAFOk;
553
554 STAFZipServiceData *pData =
555 reinterpret_cast<STAFZipServiceData *>(serviceHandle);
556
557 // Unregister help data
558
559 unregisterHelpData(pData, kZIPGeneralZipError);
560 unregisterHelpData(pData, kZIPNotEnoughMemory);
561 unregisterHelpData(pData, kZIPChangeFileSizeError);
562 unregisterHelpData(pData, kZIPErrorCreatingDir);
563 unregisterHelpData(pData, kZIPInvalidZipFile);
564 unregisterHelpData(pData, kZIPBadCRC);
565 unregisterHelpData(pData, kZIPInvalidOwnerGroup);
566 unregisterHelpData(pData, kZIPInvalidFileMode);
567
568 }
569 catch (STAFException &e)
570 {
571 STAFString result;
572
573 result += STAFString("In STAFZip.cpp: STAFServiceTerm")
574 + kUTF8_SCOLON;
575
576 result += STAFString("Name: ") + e.getName() + kUTF8_SCOLON;
577 result += STAFString("Location: ") + e.getLocation() + kUTF8_SCOLON;
578 result += STAFString("Text: ") + e.getText() + kUTF8_SCOLON;
579 result += STAFString("Error code: ") + e.getErrorCode() + kUTF8_SCOLON;
580
581 *pErrorBuffer = result.adoptImpl();
582 }
583 catch (...)
584 {
585 STAFString error("STAFZip.cpp: STAFServiceTerm: "
586 "Caught unknown exception");
587 *pErrorBuffer = error.adoptImpl();
588 }
589
590 return retCode;
591 }
592
593
STAFServiceDestruct(STAFServiceHandle_t * serviceHandle,void * pDestructInfo,unsigned int destructLevel,STAFString_t * pErrorBuffer)594 STAFRC_t STAFServiceDestruct(STAFServiceHandle_t *serviceHandle,
595 void *pDestructInfo, unsigned int destructLevel,
596 STAFString_t *pErrorBuffer)
597 {
598 if (destructLevel != 0) return kSTAFInvalidAPILevel;
599
600 STAFRC_t retCode = kSTAFUnknownError;
601
602 try
603 {
604 STAFZipServiceData *pData =
605 reinterpret_cast<STAFZipServiceData *>(*serviceHandle);
606
607 delete pData;
608 *serviceHandle = 0;
609
610 retCode = kSTAFOk;
611 }
612 catch (STAFException &e)
613 {
614 STAFString result;
615
616 result += STAFString("In STAFZip.cpp: STAFServiceDestruct")
617 + kUTF8_SCOLON;
618
619 result += STAFString("Name: ") + e.getName() + kUTF8_SCOLON;
620 result += STAFString("Location: ") + e.getLocation() + kUTF8_SCOLON;
621 result += STAFString("Text: ") + e.getText() + kUTF8_SCOLON;
622 result += STAFString("Error code: ") + e.getErrorCode() + kUTF8_SCOLON;
623
624 *pErrorBuffer = result.adoptImpl();
625 }
626 catch (...)
627 {
628 STAFString error("STAFZip.cpp: STAFServiceDestruct: "
629 "Caught unknown exception");
630 *pErrorBuffer = error.adoptImpl();
631 }
632
633 return retCode;
634 }
635
636
637 // Handles Add (and Zip Add) requests
638
handleAdd(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData,STAFString * mutexName)639 STAFResultPtr handleAdd(STAFServiceRequestLevel30 *pInfo,
640 STAFZipServiceData *pData, STAFString *mutexName)
641 {
642 STAFString result;
643 STAFString resultBuffer;
644
645 char zipFile[MAXFILENAME + 1] = "";
646 char entry[MAXFILENAME + 1] = "";
647 char excludePrefix[MAXFILENAME + 1] = "";
648 char zipFileBackup[MAXFILENAME + 1] = "";
649
650 unsigned int entryLength = 0;
651 unsigned int prefixLength = 0;
652
653 int replace = 0, recursive = 0;
654
655 STAFZipFile *zf;
656 STAFZipUtil util = STAFZipUtil(pData->fHandlePtr);
657
658 FILE *file;
659
660 STAFRC_t rc = kSTAFOk;
661
662 // An ADD request is equivalent to a ZIP ADD request (except for
663 // slightly different parsers). The ADD request syntax is preferred
664 // over the ZIP ADD request syntax, since ZIP ADD has been deprecated.
665
666 // Check if the deprecated ZIP ADD command was specified
667
668 STAFString requestType = "ADD";
669 STAFString request = STAFString(pInfo->request);
670
671 if (request.subWord(0, 1).toLowerCase() == "zip")
672 requestType = "ZIP";
673
674 // Verify the requester has at least trust level 4
675
676 VALIDATE_TRUST(4, pData->fShortName, requestType, pData->fLocalMachineName);
677
678 // Parse the request
679
680 STAFCommandParseResultPtr parsedResult = pData->fAddParser->
681 parse(pInfo->request);
682
683 if (parsedResult->rc != kSTAFOk)
684 {
685 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
686 parsedResult->errorBuffer), STAFResultPtr::INIT);
687 }
688
689 if (requestType == "ZIP")
690 {
691 // Log a deprecated tracepoint message
692
693 STAFString errorBuffer = STAFString(
694 "STAFZip::handleAdd() - The ZIP service has deprecated the "
695 "ZIP ADD request. Use the ADD request instead.");
696
697 STAFTrace::trace(kSTAFTraceDeprecated, errorBuffer);
698 }
699
700 // get "ZIPFILE" parameter value
701
702 STAFResultPtr resultPtr = resolveOp(pInfo, pData, parsedResult, "ZIPFILE");
703 if (resultPtr->rc != 0) return resultPtr;
704
705 if (resultPtr->result.length() <= MAXFILENAME)
706 {
707 util.convertSTAFStringBuffer(resultPtr->result.toCurrentCodePage(), zipFile);
708 }
709 else
710 {
711 return STAFResultPtr(new STAFResult(kSTAFInvalidValue,
712 STAFString("STAFZip::handleAdd: ZIPFILE [")
713 + zipFile
714 + "] file name length exceeds "
715 + MAXFILENAME
716 + " charactors.\n"),
717 STAFResultPtr::INIT);
718 }
719
720 resultPtr->result = resultPtr->result.replace(kUTF8_BSLASH, kUTF8_SLASH);
721
722 // use zip file name to construct the mutex name
723
724 *mutexName += resultPtr->result;
725 *mutexName = (*mutexName).toUpperCase();
726
727 // obtain mutex semphore on the zipfile
728
729 zipLock.request(*mutexName);
730
731 // get "RELATIVETO" parameter value
732
733 resultPtr = resolveOp(pInfo, pData, parsedResult, "RELATIVETO");
734 if (resultPtr->rc != 0) return resultPtr;
735
736 resultPtr->result = resultPtr->result.replace(kUTF8_BSLASH, kUTF8_SLASH);
737 prefixLength = resultPtr->result.length();
738
739 if (prefixLength > 0)
740 {
741 if (prefixLength <= MAXFILENAME)
742 {
743 util.convertSTAFStringBuffer(resultPtr->result.toCurrentCodePage(), excludePrefix);
744
745 if (excludePrefix[prefixLength - 1] != '/')
746 {
747 excludePrefix[prefixLength] = '/';
748 excludePrefix[prefixLength + 1] = kUTF8_NULL;
749
750 prefixLength++;
751 }
752 }
753 else
754 {
755 return STAFResultPtr(new STAFResult(kSTAFInvalidValue,
756 STAFString("STAFZip::handleAdd:"
757 " RELATIVETO [")
758 + excludePrefix
759 + "] file name length exceeds "
760 + MAXFILENAME
761 + " charactors.\n"),
762 STAFResultPtr::INIT);
763 }
764 }
765
766 // get "RECURSE" parameter value
767
768 if (parsedResult->optionTimes("RECURSE"))
769 {
770 recursive = 1;
771 }
772
773 // make a backup copy of the current zip file
774
775 int fileExist = util.checkFileExist(zipFile);
776
777 STAFString zipFileName;
778
779 if (fileExist)
780 {
781 strcpy(zipFileBackup, zipFile);
782 strcat(zipFileBackup, ".ZIP");
783
784 if(util.copyFile(zipFile, zipFileBackup) != kSTAFOk)
785 {
786 return STAFResultPtr(new STAFResult(kZIPGeneralZipError,
787 STAFString("STAFZip::handleAdd:"
788 " Can't create file [")
789 + zipFile
790 + ".ZIP].\n"),
791 STAFResultPtr::INIT);
792 }
793
794 // open the file for reading and writing
795
796 if ((file = fopen(zipFileBackup, "r+b")) == NULL)
797 {
798 result = STAFString("STAFZip::handleAdd_CP1.1: ")
799 + "ZipFile [" + zipFileBackup + "] does not exist.\n";
800 rc = kSTAFDoesNotExist;
801 }
802 }
803 else
804 {
805 // create a new file
806
807 if ((file = fopen(zipFile, "wb")) == NULL)
808 {
809 result = STAFString("STAFZipFile::STAFZipFile: ")
810 + STAFString("Can't create file [")
811 + zipFile + STAFString("].\n");
812 rc = kZIPGeneralZipError;
813 }
814 }
815
816 // Assign the zipFileName in the STAFZipFile class to a name where
817 // any backslashes have been converted to a forward slash. The
818 // zipFileName will be used by the STAFZipFile class to ignore zipping
819 // up the zip file or backup zip file being created or updated.
820
821 zipFileName = STAFString(zipFile);
822
823 try
824 {
825 STAFFSPath fsPath(zipFileName);
826
827 // Do so that any \\ will be converted to a \ and any // are converted
828 // to a /, etc, and so that any trailing slashes are removed
829 fsPath.setRoot(fsPath.root());
830
831 // Convert backslashes to forward slashes, if any, in the file name
832 zipFileName = fsPath.getEntry()->path().asString().replace(
833 kUTF8_BSLASH, kUTF8_SLASH);
834 }
835 catch (STAFBaseOSErrorException)
836 {
837 zipFileName = zipFileName.replace(kUTF8_BSLASH, kUTF8_SLASH);
838 }
839
840 // get number of entries for FILE or DIRECTORY option
841
842 unsigned int numFilesToAdd = parsedResult->optionTimes("FILE");
843 unsigned int numDirsToAdd = parsedResult->optionTimes("DIRECTORY");
844
845 // zipping the files
846
847 for (unsigned int i = 1; i <= numFilesToAdd && rc == kSTAFOk; i++)
848 {
849 // resolve variables
850
851 STAFString thisEntry = parsedResult->optionValue("FILE", i);
852
853 resultPtr = resolveStr(pInfo, pData, thisEntry);
854
855 if (resultPtr->rc != 0)
856 {
857 rc = resultPtr->rc;
858 result = resultPtr->result;
859
860 break;
861 }
862
863 thisEntry = resultPtr->result;
864
865 // replace all backward slashes with forward slashes
866
867 thisEntry = thisEntry.replace(kUTF8_BSLASH, kUTF8_SLASH);
868 entryLength = thisEntry.length();
869
870 if (entryLength <= MAXFILENAME)
871 {
872 util.convertSTAFStringBuffer(thisEntry.toCurrentCodePage(), entry);
873 }
874 else
875 {
876 result = STAFString("STAFZip::handleAdd: FILE [")
877 + entry
878 + "] file name length exceeds "
879 + MAXFILENAME
880 + " charactors.\n";
881 rc = kSTAFInvalidValue;
882
883 break;
884 }
885
886 if (prefixLength != 0)
887 {
888 // check if excludeprefix is shorter than entry name
889
890 if (prefixLength > strlen(entry))
891 {
892 result = STAFString("STAFZip::handleAdd: The length of"
893 " RELATIVETO [")
894 + excludePrefix
895 + "] exceeds the length of FILE ["
896 + entry
897 + "].\n";
898 rc = kSTAFInvalidValue;
899
900 break;
901 }
902
903 // save the char of entry at the prefixLength
904
905 char c = *(entry + prefixLength);
906
907 // truncate the entry to be a identical c string as excludeprefix
908
909 entry[prefixLength] = kUTF8_NULL;
910
911 // check if excludeprefix is a part of the entry name
912
913 if (util.myStrCmp(entry, excludePrefix))
914 {
915 result = STAFString("STAFZip::handleAdd: RELATIVETO [")
916 + excludePrefix
917 + "] is not a leading sub-string of FILE ["
918 + entry
919 + "].\n";
920 rc = kSTAFInvalidValue;
921
922 break;
923 }
924
925 // restore the char of entry at the prefixLength
926
927 *(entry + prefixLength) = c;
928 }
929
930 zf = new STAFZipFile(pData->fHandlePtr, file,
931 &rc, &resultBuffer, fileExist,
932 -1, -1, zipFileName);
933
934 if (rc != kSTAFOk)
935 {
936 delete zf,
937 result = resultBuffer;
938
939 break;
940 }
941
942
943 if (STAFTrace::doTrace(kSTAFTraceServiceResult))
944 {
945 STAFTrace::trace(kSTAFTraceServiceResult,
946 STAFString("handleAdd_CP3")
947 + " entry ["
948 + entry
949 + "] prefixLength ["
950 + prefixLength
951 + "] recursive ["
952 + recursive
953 + "]");
954 }
955
956 // adding the entry to the zip archive
957
958 if ((rc = zf->zipFile(entry, prefixLength, recursive, &resultBuffer)) !=
959 kSTAFOk)
960 {
961 result = resultBuffer;
962 }
963
964 delete zf;
965 }
966
967 // zipping the directories
968
969 for (unsigned int j = 1; j <= numDirsToAdd && rc == kSTAFOk; j++)
970 {
971 // resolve variables
972
973 STAFString thisEntry = parsedResult->optionValue("DIRECTORY", j);
974
975 resultPtr = resolveStr(pInfo, pData, thisEntry);
976
977 if (resultPtr->rc != 0)
978 {
979 rc = resultPtr->rc;
980 result = resultPtr->result;
981
982 break;
983 }
984
985 thisEntry = resultPtr->result;
986
987 // replace all backward slashes with forward slashes
988
989 thisEntry = thisEntry.replace(kUTF8_BSLASH, kUTF8_SLASH);
990 entryLength = thisEntry.length();
991
992 if (entryLength <= MAXFILENAME)
993 {
994 util.convertSTAFStringBuffer(thisEntry.toCurrentCodePage(), entry);
995
996 // append a '/' to the end of directory name
997
998 if (entry[entryLength - 1] != '/')
999 {
1000 entry[entryLength] = '/';
1001 entry[entryLength + 1] = kUTF8_NULL;
1002 entryLength++;
1003 }
1004 }
1005 else
1006 {
1007 result = STAFString("STAFZip::handleAdd: DIRECTORY [")
1008 + entry
1009 + "] file name length exceeds "
1010 + MAXFILENAME
1011 + " charactors.\n";
1012 rc = kSTAFInvalidValue;
1013
1014 break;
1015 }
1016
1017 if (prefixLength != 0)
1018 {
1019 // check if excludeprefix is shorter than entry name
1020
1021 if (prefixLength > strlen(entry))
1022 {
1023 result = STAFString("STAFZip::handleAdd: The length of"
1024 " RELATIVETO [")
1025 + excludePrefix
1026 + "] exceeds the length of DIRECTORY ["
1027 + entry
1028 + "].\n";
1029 rc = kSTAFInvalidValue;
1030
1031 break;
1032 }
1033
1034 // save the char of entry at the prefixLength
1035
1036 char c = *(entry + prefixLength);
1037
1038 // truncate the entry to be a identical c string as excludeprefix
1039
1040 entry[prefixLength] = kUTF8_NULL;
1041
1042 // check if excludeprefix is a part of the entry name
1043 if (util.myStrCmp(entry, excludePrefix))
1044 {
1045 result = STAFString("STAFZip::handleAdd: RELATIVETO [")
1046 + excludePrefix
1047 + "] is not a leading sub-string of DIRECTORY ["
1048 + entry
1049 + "].\n";
1050 rc = kSTAFInvalidValue;
1051
1052 break;
1053 }
1054
1055 // restore the char of entry at the prefixLength
1056
1057 *(entry + prefixLength) = c;
1058 }
1059
1060 zf = new STAFZipFile(pData->fHandlePtr, file,
1061 &rc, &resultBuffer, fileExist,
1062 -1, -1, zipFileName);
1063
1064 if (rc != kSTAFOk)
1065 {
1066 delete zf,
1067 result = resultBuffer;
1068
1069 break;
1070 }
1071
1072 if (STAFTrace::doTrace(kSTAFTraceServiceResult))
1073 {
1074 STAFTrace::trace(kSTAFTraceServiceResult,
1075 STAFString("handleAdd_CP3")
1076 + " entry ["
1077 + entry
1078 + "] prefixLength ["
1079 + prefixLength
1080 + "] recursive ["
1081 + recursive
1082 + "]");
1083 }
1084
1085 // adding the entry to the zip archive
1086
1087 if ((rc = zf->zipFile(entry, prefixLength, recursive, &resultBuffer)) !=
1088 kSTAFOk)
1089 {
1090 result = resultBuffer;
1091 }
1092
1093 delete zf;
1094 }
1095
1096 // file operation is done, let's close the file handle
1097
1098 if (file != NULL)
1099 {
1100 fclose(file);
1101 }
1102
1103 if (rc == kSTAFOk)
1104 {
1105 if (fileExist)
1106 {
1107 // If appending to existing archive, remove the original zip
1108 // archive since we are working on the backup copy
1109
1110 if (remove(zipFile) != 0)
1111 {
1112 result = STAFString("STAFZip::handleAdd:"
1113 " Remove zipfile failed with OS RC ") +
1114 errno + STAFString(": [") + zipFile +
1115 STAFString("]. Failed when trying to remove the original "
1116 "zipfile before replacing it with the updated "
1117 "zipfile.\n");
1118
1119 rc = kSTAFFileDeleteError;
1120 }
1121
1122 // If the remove was successful, rename the backup copy to be the
1123 // zip archive name
1124
1125 else if (rename(zipFileBackup, zipFile) != 0)
1126 {
1127 result = STAFString("STAFZip::handleAdd: "
1128 "Rename failed with OS RC ") +
1129 errno + STAFString(": from [") + zipFileBackup +
1130 STAFString("] to [") + zipFile +
1131 STAFString("]. Failed when trying to rename the original "
1132 "zipfile with the updated zipfile.\n");
1133
1134 rc = kZIPGeneralZipError;
1135 }
1136 }
1137 }
1138
1139 if (rc != kSTAFOk)
1140 {
1141 // An error occurred
1142
1143 if (fileExist)
1144 {
1145 // If appending to existing zip archive, remove the backup copy
1146 // that we were working on and leave the original untouched
1147
1148 remove(zipFileBackup);
1149 }
1150 else
1151 {
1152 // If this is a new archive that we created just remove it since
1153 // there was an error during zipping
1154
1155 remove(zipFile);
1156 }
1157 }
1158
1159 return STAFResultPtr(new STAFResult(rc, result), STAFResultPtr::INIT);
1160 }
1161
1162
1163 // Handles Unzip requests
handleUnzip(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData,STAFString * mutexName)1164 STAFResultPtr handleUnzip(STAFServiceRequestLevel30 *pInfo,
1165 STAFZipServiceData *pData, STAFString *mutexName)
1166 {
1167 STAFString result;
1168 STAFString resultBuffer;
1169
1170 char zipFile[MAXFILENAME + 1] = "";
1171 char fileName[MAXFILENAME + 1] = "";
1172 char toDir[MAXFILENAME + 1] = "";
1173
1174 unsigned int toDirLength = 0;
1175 unsigned int fileLength = 0;
1176 int replace = 0;
1177 int restorePermission = 0;
1178
1179 STAFZipFile *zf;
1180 STAFZipUtil util = STAFZipUtil(pData->fHandlePtr);
1181
1182 STAFRC_t rc = kSTAFOk;
1183
1184 FILE *file;
1185
1186 // Verify the requester has at least trust level 4
1187
1188 VALIDATE_TRUST(4, pData->fShortName, "UNZIP", pData->fLocalMachineName);
1189
1190 // Parse the request
1191
1192 STAFCommandParseResultPtr parsedResult = pData->fUnzipParser->parse(
1193 pInfo->request);
1194
1195 if (parsedResult->rc != kSTAFOk)
1196 {
1197 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
1198 parsedResult->errorBuffer), STAFResultPtr::INIT);
1199 }
1200
1201
1202 // get "ZIPFILE" parameter value
1203
1204 STAFResultPtr resultPtr = resolveOp(pInfo, pData, parsedResult, "ZIPFILE");
1205 if (resultPtr->rc != 0) return resultPtr;
1206
1207 if (resultPtr->result.length() <= MAXFILENAME)
1208 {
1209 util.convertSTAFStringBuffer(resultPtr->result.toCurrentCodePage(), zipFile);
1210 }
1211 else
1212 {
1213 return STAFResultPtr(new STAFResult(kSTAFInvalidValue,
1214 STAFString("STAFZip::handleUnzip:"
1215 " ZIPFILE [")
1216 + zipFile
1217 + "] file name length exceeds "
1218 + MAXFILENAME
1219 + " charactors.\n"),
1220 STAFResultPtr::INIT);
1221 }
1222
1223 resultPtr->result = resultPtr->result.replace(kUTF8_BSLASH, kUTF8_SLASH);
1224
1225 // use zip file name to construct the mutex name
1226
1227 *mutexName += resultPtr->result;
1228 *mutexName = (*mutexName).toUpperCase();
1229
1230 // obtain mutex semphore on the zipfile
1231
1232 zipLock.request(*mutexName);
1233
1234 // get "TODIRECTORY" parameter value
1235
1236 resultPtr = resolveOp(pInfo, pData, parsedResult, "TODIRECTORY");
1237 if (resultPtr->rc != 0) return resultPtr;
1238
1239 resultPtr->result =
1240 STAFString(resultPtr->result.toCurrentCodePage()->buffer());
1241
1242 resultPtr->result = resultPtr->result.replace(kUTF8_BSLASH, kUTF8_SLASH);
1243 toDirLength = resultPtr->result.length();
1244
1245 if (toDirLength <= MAXFILENAME)
1246 {
1247 util.convertSTAFStringBuffer(resultPtr->result.toCurrentCodePage(), toDir);
1248
1249 if (toDir[toDirLength - 1] != '/')
1250 {
1251 toDir[toDirLength] = '/';
1252 toDir[toDirLength + 1] = kUTF8_NULL;
1253 toDirLength++;
1254 }
1255 }
1256 else
1257 {
1258 return STAFResultPtr(new STAFResult(kSTAFInvalidValue,
1259 STAFString("STAFZip::handleUnzip:"
1260 " TODIRECTORY [")
1261 + toDir
1262 + "] file name length exceeds "
1263 + MAXFILENAME
1264 + " charactors.\n"),
1265 STAFResultPtr::INIT);
1266 }
1267
1268 // get "REPLACE" parameter value
1269
1270 if (parsedResult->optionTimes("REPLACE"))
1271 {
1272 replace = 1;
1273 }
1274
1275 // get "RESTOREPERMISSION" parameter value
1276
1277 if (parsedResult->optionTimes("RESTOREPERMISSION"))
1278 {
1279 restorePermission = 1;
1280 }
1281
1282 STAFTrace::trace(kSTAFTraceServiceResult,
1283 STAFString("handleUnzip_CP1")
1284 +" zipFile ["
1285 + zipFile
1286 + "]");
1287
1288 // open the ZIP archive for reading
1289
1290 if ((file = fopen(zipFile, "rb")) == NULL)
1291 {
1292 result = STAFString("STAFZip::handleUnzip_CP1.1: ")
1293 + "ZipFile [" + zipFile + "] does not exist.\n";
1294 rc = kSTAFDoesNotExist;
1295
1296 return STAFResultPtr(new STAFResult(rc, result),
1297 STAFResultPtr::INIT);
1298 }
1299
1300 zf = new STAFZipFile(pData->fHandlePtr, file, &rc, &resultBuffer, 1,
1301 -1, -1, STAFString(zipFile));
1302
1303 if (rc != kSTAFOk)
1304 {
1305 delete zf;
1306 fclose(file);
1307
1308 return STAFResultPtr(new STAFResult(rc, resultBuffer),
1309 STAFResultPtr::INIT);
1310 }
1311
1312 unsigned int numFilesToUnzip = parsedResult->optionTimes("FILE");
1313 unsigned int numDirsToUnzip = parsedResult->optionTimes("DIRECTORY");
1314
1315 if (numFilesToUnzip == 0 && numDirsToUnzip == 0)
1316 {
1317 if (STAFTrace::doTrace(kSTAFTraceServiceResult))
1318 {
1319 STAFTrace::trace(kSTAFTraceServiceResult,
1320 STAFString("handleUnzip_CP2")
1321 + " toDir ["
1322 + toDir
1323 + "] replace ["
1324 + replace
1325 + "] restorePermission ["
1326 + restorePermission
1327 + "]");
1328 }
1329
1330 // if no FILE or DIRECTORY option is provided, unzip all files
1331 // in the archive
1332
1333 if ((rc = zf->unzipFile(toDir, replace, restorePermission,
1334 &resultBuffer)) != kSTAFOk)
1335 {
1336 result = resultBuffer;
1337 }
1338 }
1339 else
1340 {
1341 if (numFilesToUnzip > 0)
1342 {
1343 // unzip the individual files one by one
1344
1345 for (unsigned int i = 1; i <= numFilesToUnzip; i++)
1346 {
1347 // resolve variables
1348
1349 STAFString thisFile = parsedResult->optionValue("FILE", i);
1350 resultPtr = resolveStr(pInfo, pData, thisFile);
1351
1352 if (resultPtr->rc != 0)
1353 {
1354 rc = resultPtr->rc;
1355 result = resultPtr->result;
1356
1357 break;
1358 }
1359
1360 thisFile = resultPtr->result;
1361 fileLength = thisFile.length();
1362
1363 if (fileLength != 0)
1364 {
1365 if (fileLength <= MAXFILENAME)
1366 {
1367 util.convertSTAFStringBuffer(
1368 thisFile.toCurrentCodePage(), fileName);
1369 }
1370 else
1371 {
1372 result = STAFString("STAFZip::handleUnzip: FILE [") +
1373 fileName + "] file name length exceeds " +
1374 MAXFILENAME + " charactors.\n";
1375 rc = kSTAFInvalidValue;
1376
1377 break;
1378 }
1379 }
1380
1381 if (STAFTrace::doTrace(kSTAFTraceServiceResult))
1382 {
1383 STAFTrace::trace(
1384 kSTAFTraceServiceResult,
1385 STAFString("handleUnzip_CP3") +
1386 " file [" + fileName + "] toDir [" +
1387 toDir + "] replace [" + replace +
1388 "] restorePermission [" + restorePermission + "]");
1389 }
1390
1391 // unzip the file entry
1392
1393 if ((rc = zf->unzipFile(
1394 fileName, toDir, replace, restorePermission,
1395 &resultBuffer)) != kSTAFOk)
1396 {
1397 result = resultBuffer;
1398
1399 // if fails, exit the loop
1400
1401 break;
1402 }
1403 } //end for
1404 }
1405
1406 if ((numDirsToUnzip > 0) && (rc == kSTAFOk))
1407 {
1408 // unzip the individual dirs one by one
1409
1410 for (unsigned int i = 1; i <= numDirsToUnzip; i++)
1411 {
1412 // resolve variables
1413
1414 STAFString thisDirectory = parsedResult->optionValue(
1415 "DIRECTORY", i);
1416 resultPtr = resolveStr(pInfo, pData, thisDirectory);
1417
1418 if (resultPtr->rc != 0)
1419 {
1420 rc = resultPtr->rc;
1421 result = resultPtr->result;
1422
1423 break;
1424 }
1425
1426 thisDirectory = resultPtr->result;
1427 fileLength = thisDirectory.length();
1428
1429 if (fileLength != 0)
1430 {
1431 if (fileLength <= MAXFILENAME)
1432 {
1433 util.convertSTAFStringBuffer(
1434 thisDirectory.toCurrentCodePage(), fileName);
1435 }
1436 else
1437 {
1438 result = STAFString("STAFZip::handleUnzip:"
1439 " DIRECTORY [") + fileName +
1440 "] dir name length exceeds " + MAXFILENAME +
1441 " charactors.\n";
1442
1443 rc = kSTAFInvalidValue;
1444
1445 break;
1446 }
1447 }
1448
1449 if (STAFTrace::doTrace(kSTAFTraceServiceResult))
1450 {
1451 STAFTrace::trace(
1452 kSTAFTraceServiceResult,
1453 STAFString("handleUnzip_CP3") + " dir [" + fileName +
1454 "] toDir [" + toDir + "] replace [" + replace +
1455 "] restorePermission [" + restorePermission + "]");
1456 }
1457
1458 // unzip the dir entry
1459
1460 if ((rc = zf->unzipDir(
1461 fileName, toDir, replace, restorePermission,
1462 &resultBuffer)) != kSTAFOk)
1463 {
1464 result = resultBuffer;
1465
1466 // if fails, exit the loop
1467 break;
1468 }
1469 } // end for
1470
1471 } // end if
1472 }
1473
1474 delete zf;
1475
1476 if (file != NULL)
1477 {
1478 fclose(file);
1479 }
1480
1481 return STAFResultPtr(new STAFResult(rc, result),
1482 STAFResultPtr::INIT);
1483 }
1484
1485
1486 // Handles Delete requests
1487
handleDelete(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData,STAFString * mutexName)1488 STAFResultPtr handleDelete(STAFServiceRequestLevel30 *pInfo,
1489 STAFZipServiceData *pData, STAFString *mutexName)
1490 {
1491 STAFString result;
1492 STAFString resultBuffer;
1493
1494 char zipFile[MAXFILENAME + 1] = "";
1495 char deleteFile[MAXFILENAME + 1] = "";
1496 char zipFileBackup[MAXFILENAME + 1] = "";
1497
1498 STAFZipFile *zf;
1499 STAFZipUtil util = STAFZipUtil(pData->fHandlePtr);
1500
1501 STAFRC_t rc = kSTAFOk;
1502
1503 FILE *file;
1504
1505 // Verify the requester has at least trust level 4
1506
1507 VALIDATE_TRUST(4, pData->fShortName, "DELETE", pData->fLocalMachineName);
1508
1509 // Parse the request
1510
1511 STAFCommandParseResultPtr parsedResult = pData->fDeleteParser->parse(
1512 pInfo->request);
1513
1514 if (parsedResult->rc != kSTAFOk)
1515 {
1516 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
1517 parsedResult->errorBuffer), STAFResultPtr::INIT);
1518 }
1519
1520 // get "ZIPFILE" parameter value
1521
1522 STAFResultPtr resultPtr = resolveOp(pInfo, pData, parsedResult, "ZIPFILE");
1523 if (resultPtr->rc != 0) return resultPtr;
1524
1525 if (resultPtr->result.length() <= MAXFILENAME)
1526 {
1527 util.convertSTAFStringBuffer(resultPtr->result.toCurrentCodePage(), zipFile);
1528 }
1529 else
1530 {
1531 return STAFResultPtr(new STAFResult(kSTAFInvalidValue,
1532 STAFString("STAFZip::handleDelete:"
1533 " ZIPFILE [")
1534 + zipFile
1535 + "] file name length exceeds "
1536 + MAXFILENAME
1537 + " charactors.\n"),
1538 STAFResultPtr::INIT);
1539 }
1540
1541 resultPtr->result = resultPtr->result.replace(kUTF8_BSLASH, kUTF8_SLASH);
1542
1543 // use zip file name to construct the mutex name
1544
1545 *mutexName += resultPtr->result;
1546 *mutexName = (*mutexName).toUpperCase();
1547
1548 // obtain mutex semphore on the zipfile
1549
1550 zipLock.request(*mutexName);
1551
1552 int fileExist = util.checkFileExist(zipFile);
1553
1554 if (!fileExist)
1555 {
1556 return STAFResultPtr(new STAFResult(
1557 kSTAFDoesNotExist,
1558 STAFString("STAFZip::handleDelete: Zip file does not exist [") +
1559 zipFile + "].\n"), STAFResultPtr::INIT);
1560 }
1561
1562 // backup the original zip archive
1563
1564 strcpy(zipFileBackup, zipFile);
1565 strcat(zipFileBackup, ".ZIP");
1566
1567 if (util.copyFile(zipFile, zipFileBackup) != kSTAFOk)
1568 {
1569 return STAFResultPtr(new STAFResult(
1570 kZIPGeneralZipError,
1571 STAFString("STAFZip::handleDelete: Can't create file [") +
1572 zipFile + ".ZIP].\n"), STAFResultPtr::INIT);
1573 }
1574
1575 // open the ZIP archive for reading and writing
1576
1577 if ((file = fopen(zipFileBackup, "r+b")) == NULL)
1578 {
1579 return STAFResultPtr(new STAFResult(
1580 kSTAFDoesNotExist,
1581 STAFString("STAFZip::handleDelete_CP0.1: ZipFile [") +
1582 zipFileBackup + "] does not exist."), STAFResultPtr::INIT);
1583 }
1584
1585 // loop to delete file entries from zip archive
1586
1587 STAFInt64_t newsize = -1;
1588
1589 unsigned int numFilesToDelete = parsedResult->optionTimes("FILE");
1590
1591 for (unsigned int i = 1; i <= numFilesToDelete; i++)
1592 {
1593 // resolve variables
1594
1595 STAFString thisFile = parsedResult->optionValue("FILE", i);
1596 resultPtr = resolveStr(pInfo, pData, thisFile);
1597
1598 if (resultPtr->rc != 0)
1599 {
1600 rc = resultPtr->rc;
1601 result = resultPtr->result;
1602
1603 break;
1604 }
1605
1606 thisFile = resultPtr->result;
1607
1608 if (thisFile.length() <= MAXFILENAME)
1609 {
1610 util.convertSTAFStringBuffer(thisFile.toCurrentCodePage(), deleteFile);
1611 }
1612 else
1613 {
1614 result = STAFString("STAFZip::handleDelete: FILE [")
1615 + STAFString(deleteFile)
1616 + "] file name length exceeds "
1617 + MAXFILENAME
1618 + " charactors.\n";
1619 rc = kSTAFInvalidValue;
1620
1621 break;
1622 }
1623
1624 // delete a file from zip archive
1625
1626 STAFTrace::trace(kSTAFTraceServiceResult,
1627 STAFString("handleDelete_CP1")
1628 + " zipFileBackup ["
1629 + zipFileBackup
1630 + "]");
1631
1632 // open the backup zip archive
1633
1634 zf = new STAFZipFile(pData->fHandlePtr, file,
1635 &rc, &resultBuffer, 1,
1636 newsize, -1, STAFString(zipFileBackup));
1637
1638 if (rc != kSTAFOk)
1639 {
1640 delete zf;
1641 result = resultBuffer;
1642
1643 break;
1644 }
1645
1646 STAFTrace::trace(kSTAFTraceServiceResult,
1647 STAFString("handleDelete_CP2")
1648 + " deleteFile [" + deleteFile + "]");
1649
1650 // delete one entry from the zip archive
1651
1652 if ((rc = zf->deleteFile(deleteFile, (STAFInt64_t*)&newsize,
1653 &resultBuffer)) != kSTAFOk)
1654 {
1655 delete zf;
1656 result = resultBuffer;
1657
1658 break;
1659 }
1660
1661 delete zf;
1662 } // end deleting loop
1663
1664 // file operation is done, let's close the file handle
1665
1666 if (file != NULL)
1667 {
1668 fclose(file);
1669 }
1670
1671 // to reduce file size after deleting one or more file entries
1672
1673 if (newsize > 0)
1674 {
1675 // change file size to the new size after deleting the file entry
1676
1677 if ((rc = util.changeFileSize(zipFileBackup, newsize)) != 0)
1678 {
1679 result = STAFString(
1680 "STAFZip::handleDelete: Change file size fails: [") +
1681 zipFileBackup + STAFString("] to [") +
1682 STAFString(newsize) + STAFString("]");
1683
1684 rc = kZIPGeneralZipError;
1685 }
1686 }
1687
1688 if (rc == kSTAFOk && newsize > 0)
1689 {
1690 // Remove the original zip archive (since we are working on the
1691 // backup zip archive)
1692
1693 if (remove(zipFile) != 0)
1694 {
1695 result = STAFString(
1696 "STAFZip::handleDelete: Remove zipfile failed with OS RC ") +
1697 errno + STAFString(": [") + zipFile + STAFString(
1698 "]. Failed when trying to remove the original zipfile "
1699 "so can replace it with the updated zipfile.");
1700
1701 rc = kSTAFFileDeleteError;
1702
1703 // Delete the backup zip archive since won't be able to use it
1704
1705 remove(zipFileBackup);
1706 }
1707 else
1708 {
1709 // rename the backup zip archive to the original zip archive
1710 // since we are working on the backup zip archive
1711
1712 if (rename(zipFileBackup, zipFile) != 0)
1713 {
1714 result = STAFString(
1715 "STAFZip::handleDelete: Rename failed with OS RC ") +
1716 errno + STAFString(": from [") + zipFileBackup +
1717 STAFString("] to [") + zipFile + STAFString(
1718 "]. Failed when trying to rename the original "
1719 "zipfile with the updated zipfile.\n");
1720
1721 rc = kZIPGeneralZipError;
1722
1723 // Delete the backup zip archive since won't be able to use it
1724
1725 remove(zipFileBackup);
1726 }
1727 }
1728 }
1729 else // either all entries are removed or remove failed
1730 {
1731 // remove the backup zip archive that we are working on
1732
1733 remove(zipFileBackup);
1734
1735 if (newsize == 0 && rc == kSTAFOk)
1736 {
1737 // If all files in the zip archive are removed, remove the zip
1738 // archive
1739
1740 if ((rc = remove(zipFile)) != 0)
1741 {
1742 result = STAFString("STAFZip::handleDelete: "
1743 "Remove file failed with OS RC ") +
1744 errno + STAFString(": [") + STAFString(zipFile) +
1745 STAFString("]. Failed when trying to remove the "
1746 "original zipfile since all files in "
1747 "the zipfile were removed.");
1748
1749 rc = kSTAFFileDeleteError;
1750 }
1751 }
1752 }
1753
1754 return STAFResultPtr(new STAFResult(rc, result),
1755 STAFResultPtr::INIT);
1756 }
1757
1758
1759 // Handles List requests
handleList(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData,STAFString * mutexName)1760 STAFResultPtr handleList(STAFServiceRequestLevel30 *pInfo,
1761 STAFZipServiceData *pData, STAFString *mutexName)
1762 {
1763 STAFString result;
1764
1765 char zipFile[MAXFILENAME + 1] = "";
1766
1767 STAFZipFile *zf;
1768 STAFZipUtil util = STAFZipUtil(pData->fHandlePtr);
1769
1770 STAFRC_t rc = kSTAFOk;
1771
1772 FILE *file;
1773
1774 // Verify the requester has at least trust level 3
1775
1776 VALIDATE_TRUST(3, pData->fShortName, "LIST", pData->fLocalMachineName);
1777
1778 // Parse the request
1779
1780 STAFCommandParseResultPtr parsedResult =
1781 pData->fListParser->parse(pInfo->request);
1782
1783 if (parsedResult->rc != kSTAFOk)
1784 {
1785 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
1786 parsedResult->errorBuffer), STAFResultPtr::INIT);
1787 }
1788
1789 // get "ZIPFILE" parameter value
1790
1791 STAFResultPtr resultPtr = resolveOp(pInfo, pData, parsedResult, "ZIPFILE");
1792 if (resultPtr->rc != 0) return resultPtr;
1793
1794 if (resultPtr->result.length() <= MAXFILENAME)
1795 {
1796 util.convertSTAFStringBuffer(resultPtr->result.toCurrentCodePage(), zipFile);
1797 }
1798 else
1799 {
1800 return STAFResultPtr(new STAFResult(kSTAFInvalidValue,
1801 STAFString("STAFZip::handleList:"
1802 " ZIPFILE [")
1803 + zipFile
1804 +"] file name length exceeds "
1805 + MAXFILENAME
1806 + " charactors.\n"),
1807 STAFResultPtr::INIT);
1808 }
1809
1810 resultPtr->result = resultPtr->result.replace(kUTF8_BSLASH, kUTF8_SLASH);
1811
1812 // use zip file name to construct the mutex name
1813
1814 *mutexName += resultPtr->result;
1815 *mutexName = (*mutexName).toUpperCase();
1816
1817 // obtain mutex semphore on the zipfile
1818
1819 zipLock.request(*mutexName);
1820
1821 STAFTrace::trace(kSTAFTraceServiceResult,
1822 STAFString("handleList_CP1")
1823 + " zipFile ["
1824 + zipFile
1825 + "]");
1826
1827 // open the ZIP archive for reading
1828
1829 if ((file = fopen(zipFile, "rb")) == NULL)
1830 {
1831 result = STAFString("STAFZip::handleList_CP1.1: ")
1832 + "ZipFile [" + zipFile + "] does not exist.\n";
1833 rc = kSTAFDoesNotExist;
1834
1835 return STAFResultPtr(new STAFResult(rc, result),
1836 STAFResultPtr::INIT);
1837 }
1838
1839 // open the Zip archive, don't create a new one
1840
1841 zf = new STAFZipFile(pData->fHandlePtr, file, &rc, &result, 1,
1842 -1, -1, STAFString(zipFile));
1843
1844 if (rc != kSTAFOk)
1845 {
1846 delete zf;
1847 fclose(file);
1848
1849 return STAFResultPtr(new STAFResult(rc, result),
1850 STAFResultPtr::INIT);
1851 }
1852
1853 STAFTrace::trace(kSTAFTraceServiceResult,
1854 STAFString("handleList_CP2"));
1855
1856 STAFString buffer;
1857
1858 rc = zf->listFile(&buffer, &result);
1859
1860 delete zf;
1861
1862 // file operation is done, let's close the file handle
1863
1864 if (file != NULL)
1865 {
1866 fclose(file);
1867 }
1868
1869 if (rc == kSTAFOk)
1870 {
1871 result = buffer;
1872 }
1873
1874 return STAFResultPtr(new STAFResult(rc, result),
1875 STAFResultPtr::INIT);
1876 }
1877
1878
handleHelp(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData)1879 STAFResultPtr handleHelp(STAFServiceRequestLevel30 *pInfo,
1880 STAFZipServiceData *pData)
1881 {
1882 // Verify the requester has at least trust level 1
1883
1884 VALIDATE_TRUST(1, pData->fShortName, "HELP", pData->fLocalMachineName);
1885
1886 // Return help text for the service
1887
1888 return STAFResultPtr(new STAFResult(kSTAFOk, sHelpMsg),
1889 STAFResultPtr::INIT);
1890 }
1891
1892
handleVersion(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData)1893 STAFResultPtr handleVersion(STAFServiceRequestLevel30 *pInfo,
1894 STAFZipServiceData *pData)
1895 {
1896 // Verify the requester has at least trust level 1
1897
1898 VALIDATE_TRUST(1, pData->fShortName, "VERSION", pData->fLocalMachineName);
1899
1900 return STAFResultPtr(new STAFResult(kSTAFOk, sVersionInfo),
1901 STAFResultPtr::INIT);
1902 }
1903
1904
resolveOp(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData,STAFCommandParseResultPtr & parsedResult,const STAFString & fOption,unsigned int optionIndex)1905 STAFResultPtr resolveOp(STAFServiceRequestLevel30 *pInfo,
1906 STAFZipServiceData *pData,
1907 STAFCommandParseResultPtr &parsedResult,
1908 const STAFString &fOption, unsigned int optionIndex)
1909 {
1910 STAFString optionValue = parsedResult->optionValue(fOption, optionIndex);
1911
1912 if (optionValue.find(sLeftCurlyBrace) == STAFString::kNPos)
1913 {
1914 return STAFResultPtr(new STAFResult(kSTAFOk, optionValue),
1915 STAFResultPtr::INIT);
1916 }
1917
1918 return resolveStr(pInfo, pData, optionValue);
1919 }
1920
resolveStr(STAFServiceRequestLevel30 * pInfo,STAFZipServiceData * pData,const STAFString & theString)1921 STAFResultPtr resolveStr(STAFServiceRequestLevel30 *pInfo,
1922 STAFZipServiceData *pData,
1923 const STAFString &theString)
1924 {
1925 return pData->fHandlePtr->submit(sLocal, sVar, sResStrResolve +
1926 STAFString(pInfo->requestNumber) +
1927 sString +
1928 pData->fHandlePtr->wrapData(theString));
1929 }
1930
1931
registerHelpData(STAFZipServiceData * pData,unsigned int errorNumber,const STAFString & shortInfo,const STAFString & longInfo)1932 void registerHelpData(STAFZipServiceData *pData, unsigned int errorNumber,
1933 const STAFString &shortInfo, const STAFString &longInfo)
1934 {
1935 static STAFString regString("REGISTER SERVICE %C ERROR %d INFO %C "
1936 "DESCRIPTION %C");
1937
1938 pData->fHandlePtr->submit(sLocal, sHelp, STAFHandle::formatString(
1939 regString.getImpl(), pData->fShortName.getImpl(), errorNumber,
1940 shortInfo.getImpl(), longInfo.getImpl()));
1941 }
1942
1943
unregisterHelpData(STAFZipServiceData * pData,unsigned int errorNumber)1944 void unregisterHelpData(STAFZipServiceData *pData, unsigned int errorNumber)
1945 {
1946 static STAFString regString("UNREGISTER SERVICE %C ERROR %d");
1947
1948 pData->fHandlePtr->submit(sLocal, STAFString("HELP"), STAFHandle::
1949 formatString(
1950 regString.getImpl(), pData->fShortName.getImpl(), errorNumber));
1951 }
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978