• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //
18 // Zip archive entries.
19 //
20 // The ZipEntry class is tightly meshed with the ZipFile class.
21 //
22 #ifndef __LIBS_ZIPENTRY_H
23 #define __LIBS_ZIPENTRY_H
24 
25 #include <utils/Errors.h>
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 
30 namespace android {
31 
32 class ZipFile;
33 
34 /*
35  * ZipEntry objects represent a single entry in a Zip archive.
36  *
37  * You can use one of these to get or set information about an entry, but
38  * there are no functions here for accessing the data itself.  (We could
39  * tuck a pointer to the ZipFile in here for convenience, but that raises
40  * the likelihood of using ZipEntry objects after discarding the ZipFile.)
41  *
42  * File information is stored in two places: next to the file data (the Local
43  * File Header, and possibly a Data Descriptor), and at the end of the file
44  * (the Central Directory Entry).  The two must be kept in sync.
45  */
46 class ZipEntry {
47 public:
48     friend class ZipFile;
49 
ZipEntry(void)50     ZipEntry(void)
51         : mDeleted(false), mMarked(false)
52         {}
~ZipEntry(void)53     ~ZipEntry(void) {}
54 
55     /*
56      * Returns "true" if the data is compressed.
57      */
isCompressed(void)58     bool isCompressed(void) const {
59         return mCDE.mCompressionMethod != kCompressStored;
60     }
getCompressionMethod(void)61     int getCompressionMethod(void) const { return mCDE.mCompressionMethod; }
62 
63     /*
64      * Return the uncompressed length.
65      */
getUncompressedLen(void)66     off_t getUncompressedLen(void) const { return mCDE.mUncompressedSize; }
67 
68     /*
69      * Return the compressed length.  For uncompressed data, this returns
70      * the same thing as getUncompresesdLen().
71      */
getCompressedLen(void)72     off_t getCompressedLen(void) const { return mCDE.mCompressedSize; }
73 
74     /*
75      * Return the offset of the local file header.
76      */
getLFHOffset(void)77     off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
78 
79     /*
80      * Return the absolute file offset of the start of the compressed or
81      * uncompressed data.
82      */
getFileOffset(void)83     off_t getFileOffset(void) const {
84         return mCDE.mLocalHeaderRelOffset +
85                 LocalFileHeader::kLFHLen +
86                 mLFH.mFileNameLength +
87                 mLFH.mExtraFieldLength;
88     }
89 
90     /*
91      * Return the data CRC.
92      */
getCRC32(void)93     unsigned long getCRC32(void) const { return mCDE.mCRC32; }
94 
95     /*
96      * Return file modification time in UNIX seconds-since-epoch.
97      */
98     time_t getModWhen(void) const;
99 
100     /*
101      * Return the archived file name.
102      */
getFileName(void)103     const char* getFileName(void) const { return (const char*) mCDE.mFileName; }
104 
105     /*
106      * Application-defined "mark".  Can be useful when synchronizing the
107      * contents of an archive with contents on disk.
108      */
getMarked(void)109     bool getMarked(void) const { return mMarked; }
setMarked(bool val)110     void setMarked(bool val) { mMarked = val; }
111 
112     /*
113      * Some basic functions for raw data manipulation.  "LE" means
114      * Little Endian.
115      */
getShortLE(const unsigned char * buf)116     static inline unsigned short getShortLE(const unsigned char* buf) {
117         return buf[0] | (buf[1] << 8);
118     }
getLongLE(const unsigned char * buf)119     static inline unsigned long getLongLE(const unsigned char* buf) {
120         return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
121     }
putShortLE(unsigned char * buf,short val)122     static inline void putShortLE(unsigned char* buf, short val) {
123         buf[0] = (unsigned char) val;
124         buf[1] = (unsigned char) (val >> 8);
125     }
putLongLE(unsigned char * buf,long val)126     static inline void putLongLE(unsigned char* buf, long val) {
127         buf[0] = (unsigned char) val;
128         buf[1] = (unsigned char) (val >> 8);
129         buf[2] = (unsigned char) (val >> 16);
130         buf[3] = (unsigned char) (val >> 24);
131     }
132 
133     /* defined for Zip archives */
134     enum {
135         kCompressStored     = 0,        // no compression
136         // shrunk           = 1,
137         // reduced 1        = 2,
138         // reduced 2        = 3,
139         // reduced 3        = 4,
140         // reduced 4        = 5,
141         // imploded         = 6,
142         // tokenized        = 7,
143         kCompressDeflated   = 8,        // standard deflate
144         // Deflate64        = 9,
145         // lib imploded     = 10,
146         // reserved         = 11,
147         // bzip2            = 12,
148     };
149 
150     /*
151      * Deletion flag.  If set, the entry will be removed on the next
152      * call to "flush".
153      */
getDeleted(void)154     bool getDeleted(void) const { return mDeleted; }
155 
156 protected:
157     /*
158      * Initialize the structure from the file, which is pointing at
159      * our Central Directory entry.
160      */
161     status_t initFromCDE(FILE* fp);
162 
163     /*
164      * Initialize the structure for a new file.  We need the filename
165      * and comment so that we can properly size the LFH area.  The
166      * filename is mandatory, the comment is optional.
167      */
168     void initNew(const char* fileName, const char* comment);
169 
170     /*
171      * Initialize the structure with the contents of a ZipEntry from
172      * another file.
173      */
174     status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry);
175 
176     /*
177      * Add some pad bytes to the LFH.  We do this by adding or resizing
178      * the "extra" field.
179      */
180     status_t addPadding(int padding);
181 
182     /*
183      * Set information about the data for this entry.
184      */
185     void setDataInfo(long uncompLen, long compLen, unsigned long crc32,
186         int compressionMethod);
187 
188     /*
189      * Set the modification date.
190      */
191     void setModWhen(time_t when);
192 
193     /*
194      * Set the offset of the local file header, relative to the start of
195      * the current file.
196      */
setLFHOffset(off_t offset)197     void setLFHOffset(off_t offset) {
198         mCDE.mLocalHeaderRelOffset = (long) offset;
199     }
200 
201     /* mark for deletion; used by ZipFile::remove() */
setDeleted(void)202     void setDeleted(void) { mDeleted = true; }
203 
204 private:
205     /* these are private and not defined */
206     ZipEntry(const ZipEntry& src);
207     ZipEntry& operator=(const ZipEntry& src);
208 
209     /* returns "true" if the CDE and the LFH agree */
210     bool compareHeaders(void) const;
211     void copyCDEtoLFH(void);
212 
213     bool        mDeleted;       // set if entry is pending deletion
214     bool        mMarked;        // app-defined marker
215 
216     /*
217      * Every entry in the Zip archive starts off with one of these.
218      */
219     class LocalFileHeader {
220     public:
LocalFileHeader(void)221         LocalFileHeader(void) :
222             mVersionToExtract(0),
223             mGPBitFlag(0),
224             mCompressionMethod(0),
225             mLastModFileTime(0),
226             mLastModFileDate(0),
227             mCRC32(0),
228             mCompressedSize(0),
229             mUncompressedSize(0),
230             mFileNameLength(0),
231             mExtraFieldLength(0),
232             mFileName(NULL),
233             mExtraField(NULL)
234         {}
~LocalFileHeader(void)235         virtual ~LocalFileHeader(void) {
236             delete[] mFileName;
237             delete[] mExtraField;
238         }
239 
240         status_t read(FILE* fp);
241         status_t write(FILE* fp);
242 
243         // unsigned long mSignature;
244         unsigned short  mVersionToExtract;
245         unsigned short  mGPBitFlag;
246         unsigned short  mCompressionMethod;
247         unsigned short  mLastModFileTime;
248         unsigned short  mLastModFileDate;
249         unsigned long   mCRC32;
250         unsigned long   mCompressedSize;
251         unsigned long   mUncompressedSize;
252         unsigned short  mFileNameLength;
253         unsigned short  mExtraFieldLength;
254         unsigned char*  mFileName;
255         unsigned char*  mExtraField;
256 
257         enum {
258             kSignature      = 0x04034b50,
259             kLFHLen         = 30,       // LocalFileHdr len, excl. var fields
260         };
261 
262         void dump(void) const;
263     };
264 
265     /*
266      * Every entry in the Zip archive has one of these in the "central
267      * directory" at the end of the file.
268      */
269     class CentralDirEntry {
270     public:
CentralDirEntry(void)271         CentralDirEntry(void) :
272             mVersionMadeBy(0),
273             mVersionToExtract(0),
274             mGPBitFlag(0),
275             mCompressionMethod(0),
276             mLastModFileTime(0),
277             mLastModFileDate(0),
278             mCRC32(0),
279             mCompressedSize(0),
280             mUncompressedSize(0),
281             mFileNameLength(0),
282             mExtraFieldLength(0),
283             mFileCommentLength(0),
284             mDiskNumberStart(0),
285             mInternalAttrs(0),
286             mExternalAttrs(0),
287             mLocalHeaderRelOffset(0),
288             mFileName(NULL),
289             mExtraField(NULL),
290             mFileComment(NULL)
291         {}
~CentralDirEntry(void)292         virtual ~CentralDirEntry(void) {
293             delete[] mFileName;
294             delete[] mExtraField;
295             delete[] mFileComment;
296         }
297 
298         status_t read(FILE* fp);
299         status_t write(FILE* fp);
300 
301         // unsigned long mSignature;
302         unsigned short  mVersionMadeBy;
303         unsigned short  mVersionToExtract;
304         unsigned short  mGPBitFlag;
305         unsigned short  mCompressionMethod;
306         unsigned short  mLastModFileTime;
307         unsigned short  mLastModFileDate;
308         unsigned long   mCRC32;
309         unsigned long   mCompressedSize;
310         unsigned long   mUncompressedSize;
311         unsigned short  mFileNameLength;
312         unsigned short  mExtraFieldLength;
313         unsigned short  mFileCommentLength;
314         unsigned short  mDiskNumberStart;
315         unsigned short  mInternalAttrs;
316         unsigned long   mExternalAttrs;
317         unsigned long   mLocalHeaderRelOffset;
318         unsigned char*  mFileName;
319         unsigned char*  mExtraField;
320         unsigned char*  mFileComment;
321 
322         void dump(void) const;
323 
324         enum {
325             kSignature      = 0x02014b50,
326             kCDELen         = 46,       // CentralDirEnt len, excl. var fields
327         };
328     };
329 
330     enum {
331         //kDataDescriptorSignature  = 0x08074b50,   // currently unused
332         kDataDescriptorLen  = 16,           // four 32-bit fields
333 
334         kDefaultVersion     = 20,           // need deflate, nothing much else
335         kDefaultMadeBy      = 0x0317,       // 03=UNIX, 17=spec v2.3
336         kUsesDataDescr      = 0x0008,       // GPBitFlag bit 3
337     };
338 
339     LocalFileHeader     mLFH;
340     CentralDirEntry     mCDE;
341 };
342 
343 }; // namespace android
344 
345 #endif // __LIBS_ZIPENTRY_H
346