ZipEntry.h revision 55e3d60da5626752ffe1d15150d35ccb8fa644e7
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     * Return the offset of the local file header.
190     */
191    off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
192
193    /*
194     * Set the offset of the local file header, relative to the start of
195     * the current file.
196     */
197    void setLFHOffset(off_t offset) {
198        mCDE.mLocalHeaderRelOffset = (long) offset;
199    }
200
201    /* mark for deletion; used by ZipFile::remove() */
202    void setDeleted(void) { mDeleted = true; }
203
204private:
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:
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        {}
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:
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        {}
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