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