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