ZipEntry.h revision 3c2c064c8791ed2d4b9d6780d7b87f406ab78f10
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
30namespace android {
31
32class 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 */
46class ZipEntry {
47public:
48    friend class ZipFile;
49
50    ZipEntry(void)
51        : mDeleted(false), mMarked(false)
52        {}
53    ~ZipEntry(void) {}
54
55    /*
56     * Returns "true" if the data is compressed.
57     */
58    bool isCompressed(void) const {
59        return mCDE.mCompressionMethod != kCompressStored;
60    }
61    int getCompressionMethod(void) const { return mCDE.mCompressionMethod; }
62
63    /*
64     * Return the uncompressed length.
65     */
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     */
72    off_t getCompressedLen(void) const { return mCDE.mCompressedSize; }
73
74    /*
75     * Return the absolute file offset of the start of the compressed or
76     * uncompressed data.
77     */
78    off_t getFileOffset(void) const {
79        return mCDE.mLocalHeaderRelOffset +
80                LocalFileHeader::kLFHLen +
81                mLFH.mFileNameLength +
82                mLFH.mExtraFieldLength;
83    }
84
85    /*
86     * Return the data CRC.
87     */
88    unsigned long getCRC32(void) const { return mCDE.mCRC32; }
89
90    /*
91     * Return file modification time in UNIX seconds-since-epoch.
92     */
93    time_t getModWhen(void) const;
94
95    /*
96     * Return the archived file name.
97     */
98    const char* getFileName(void) const { return (const char*) mCDE.mFileName; }
99
100    /*
101     * Application-defined "mark".  Can be useful when synchronizing the
102     * contents of an archive with contents on disk.
103     */
104    bool getMarked(void) const { return mMarked; }
105    void setMarked(bool val) { mMarked = val; }
106
107    /*
108     * Some basic functions for raw data manipulation.  "LE" means
109     * Little Endian.
110     */
111    static inline unsigned short getShortLE(const unsigned char* buf) {
112        return buf[0] | (buf[1] << 8);
113    }
114    static inline unsigned long getLongLE(const unsigned char* buf) {
115        return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
116    }
117    static inline void putShortLE(unsigned char* buf, short val) {
118        buf[0] = (unsigned char) val;
119        buf[1] = (unsigned char) (val >> 8);
120    }
121    static inline void putLongLE(unsigned char* buf, long val) {
122        buf[0] = (unsigned char) val;
123        buf[1] = (unsigned char) (val >> 8);
124        buf[2] = (unsigned char) (val >> 16);
125        buf[3] = (unsigned char) (val >> 24);
126    }
127
128    /* defined for Zip archives */
129    enum {
130        kCompressStored     = 0,        // no compression
131        // shrunk           = 1,
132        // reduced 1        = 2,
133        // reduced 2        = 3,
134        // reduced 3        = 4,
135        // reduced 4        = 5,
136        // imploded         = 6,
137        // tokenized        = 7,
138        kCompressDeflated   = 8,        // standard deflate
139        // Deflate64        = 9,
140        // lib imploded     = 10,
141        // reserved         = 11,
142        // bzip2            = 12,
143    };
144
145    /*
146     * Deletion flag.  If set, the entry will be removed on the next
147     * call to "flush".
148     */
149    bool getDeleted(void) const { return mDeleted; }
150
151protected:
152    /*
153     * Initialize the structure from the file, which is pointing at
154     * our Central Directory entry.
155     */
156    status_t initFromCDE(FILE* fp);
157
158    /*
159     * Initialize the structure for a new file.  We need the filename
160     * and comment so that we can properly size the LFH area.  The
161     * filename is mandatory, the comment is optional.
162     */
163    void initNew(const char* fileName, const char* comment);
164
165    /*
166     * Initialize the structure with the contents of a ZipEntry from
167     * another file.
168     */
169    status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry);
170
171    /*
172     * Add some pad bytes to the LFH.  We do this by adding or resizing
173     * the "extra" field.
174     */
175    status_t addPadding(int padding);
176
177    /*
178     * Set information about the data for this entry.
179     */
180    void setDataInfo(long uncompLen, long compLen, unsigned long crc32,
181        int compressionMethod);
182
183    /*
184     * Set the modification date.
185     */
186    void setModWhen(time_t when);
187
188    /*
189     * Set a static modification date. This only affects the standard
190     * zip modification date, not the universal time extra field.
191     */
192    void removeTimestamps();
193
194    /*
195     * Return the offset of the local file header.
196     */
197    off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
198
199    /*
200     * Set the offset of the local file header, relative to the start of
201     * the current file.
202     */
203    void setLFHOffset(off_t offset) {
204        mCDE.mLocalHeaderRelOffset = (long) offset;
205    }
206
207    /* mark for deletion; used by ZipFile::remove() */
208    void setDeleted(void) { mDeleted = true; }
209
210private:
211    /* these are private and not defined */
212    ZipEntry(const ZipEntry& src);
213    ZipEntry& operator=(const ZipEntry& src);
214
215    /* returns "true" if the CDE and the LFH agree */
216    bool compareHeaders(void) const;
217    void copyCDEtoLFH(void);
218
219    bool        mDeleted;       // set if entry is pending deletion
220    bool        mMarked;        // app-defined marker
221
222    /*
223     * Every entry in the Zip archive starts off with one of these.
224     */
225    class LocalFileHeader {
226    public:
227        LocalFileHeader(void) :
228            mVersionToExtract(0),
229            mGPBitFlag(0),
230            mCompressionMethod(0),
231            mLastModFileTime(0),
232            mLastModFileDate(0),
233            mCRC32(0),
234            mCompressedSize(0),
235            mUncompressedSize(0),
236            mFileNameLength(0),
237            mExtraFieldLength(0),
238            mFileName(NULL),
239            mExtraField(NULL)
240        {}
241        virtual ~LocalFileHeader(void) {
242            delete[] mFileName;
243            delete[] mExtraField;
244        }
245
246        status_t read(FILE* fp);
247        status_t write(FILE* fp);
248
249        // unsigned long mSignature;
250        unsigned short  mVersionToExtract;
251        unsigned short  mGPBitFlag;
252        unsigned short  mCompressionMethod;
253        unsigned short  mLastModFileTime;
254        unsigned short  mLastModFileDate;
255        unsigned long   mCRC32;
256        unsigned long   mCompressedSize;
257        unsigned long   mUncompressedSize;
258        unsigned short  mFileNameLength;
259        unsigned short  mExtraFieldLength;
260        unsigned char*  mFileName;
261        unsigned char*  mExtraField;
262
263        enum {
264            kSignature      = 0x04034b50,
265            kLFHLen         = 30,       // LocalFileHdr len, excl. var fields
266        };
267
268        void dump(void) const;
269    };
270
271    /*
272     * Every entry in the Zip archive has one of these in the "central
273     * directory" at the end of the file.
274     */
275    class CentralDirEntry {
276    public:
277        CentralDirEntry(void) :
278            mVersionMadeBy(0),
279            mVersionToExtract(0),
280            mGPBitFlag(0),
281            mCompressionMethod(0),
282            mLastModFileTime(0),
283            mLastModFileDate(0),
284            mCRC32(0),
285            mCompressedSize(0),
286            mUncompressedSize(0),
287            mFileNameLength(0),
288            mExtraFieldLength(0),
289            mFileCommentLength(0),
290            mDiskNumberStart(0),
291            mInternalAttrs(0),
292            mExternalAttrs(0),
293            mLocalHeaderRelOffset(0),
294            mFileName(NULL),
295            mExtraField(NULL),
296            mFileComment(NULL)
297        {}
298        virtual ~CentralDirEntry(void) {
299            delete[] mFileName;
300            delete[] mExtraField;
301            delete[] mFileComment;
302        }
303
304        status_t read(FILE* fp);
305        status_t write(FILE* fp);
306
307        // unsigned long mSignature;
308        unsigned short  mVersionMadeBy;
309        unsigned short  mVersionToExtract;
310        unsigned short  mGPBitFlag;
311        unsigned short  mCompressionMethod;
312        unsigned short  mLastModFileTime;
313        unsigned short  mLastModFileDate;
314        unsigned long   mCRC32;
315        unsigned long   mCompressedSize;
316        unsigned long   mUncompressedSize;
317        unsigned short  mFileNameLength;
318        unsigned short  mExtraFieldLength;
319        unsigned short  mFileCommentLength;
320        unsigned short  mDiskNumberStart;
321        unsigned short  mInternalAttrs;
322        unsigned long   mExternalAttrs;
323        unsigned long   mLocalHeaderRelOffset;
324        unsigned char*  mFileName;
325        unsigned char*  mExtraField;
326        unsigned char*  mFileComment;
327
328        void dump(void) const;
329
330        enum {
331            kSignature      = 0x02014b50,
332            kCDELen         = 46,       // CentralDirEnt len, excl. var fields
333        };
334    };
335
336    enum {
337        //kDataDescriptorSignature  = 0x08074b50,   // currently unused
338        kDataDescriptorLen  = 16,           // four 32-bit fields
339
340        kDefaultVersion     = 20,           // need deflate, nothing much else
341        kDefaultMadeBy      = 0x0317,       // 03=UNIX, 17=spec v2.3
342        kUsesDataDescr      = 0x0008,       // GPBitFlag bit 3
343    };
344
345    LocalFileHeader     mLFH;
346    CentralDirEntry     mCDE;
347};
348
349}; // namespace android
350
351#endif // __LIBS_ZIPENTRY_H
352