blob: 287a540673a32fff7ed6727652bb247a288ce41e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Mathias Agopian55e3d602009-06-05 14:56:35 -070025#include <utils/Errors.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026
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 /*
Kenny Rootfb2a9462010-08-25 07:36:31 -070075 * Return the offset of the local file header.
76 */
77 off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
78
79 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 * Return the absolute file offset of the start of the compressed or
81 * uncompressed data.
82 */
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 */
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 */
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 */
109 bool getMarked(void) const { return mMarked; }
110 void setMarked(bool val) { mMarked = val; }
111
112 /*
113 * Some basic functions for raw data manipulation. "LE" means
114 * Little Endian.
115 */
116 static inline unsigned short getShortLE(const unsigned char* buf) {
117 return buf[0] | (buf[1] << 8);
118 }
119 static inline unsigned long getLongLE(const unsigned char* buf) {
120 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
121 }
122 static inline void putShortLE(unsigned char* buf, short val) {
123 buf[0] = (unsigned char) val;
124 buf[1] = (unsigned char) (val >> 8);
125 }
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 */
154 bool getDeleted(void) const { return mDeleted; }
155
156protected:
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 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 * 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
Andreas Gampe2412f842014-09-30 20:55:57 -0700301 CentralDirEntry& operator=(const CentralDirEntry& src);
302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 // unsigned long mSignature;
304 unsigned short mVersionMadeBy;
305 unsigned short mVersionToExtract;
306 unsigned short mGPBitFlag;
307 unsigned short mCompressionMethod;
308 unsigned short mLastModFileTime;
309 unsigned short mLastModFileDate;
310 unsigned long mCRC32;
311 unsigned long mCompressedSize;
312 unsigned long mUncompressedSize;
313 unsigned short mFileNameLength;
314 unsigned short mExtraFieldLength;
315 unsigned short mFileCommentLength;
316 unsigned short mDiskNumberStart;
317 unsigned short mInternalAttrs;
318 unsigned long mExternalAttrs;
319 unsigned long mLocalHeaderRelOffset;
320 unsigned char* mFileName;
321 unsigned char* mExtraField;
322 unsigned char* mFileComment;
323
324 void dump(void) const;
325
326 enum {
327 kSignature = 0x02014b50,
328 kCDELen = 46, // CentralDirEnt len, excl. var fields
329 };
330 };
331
332 enum {
333 //kDataDescriptorSignature = 0x08074b50, // currently unused
334 kDataDescriptorLen = 16, // four 32-bit fields
335
336 kDefaultVersion = 20, // need deflate, nothing much else
337 kDefaultMadeBy = 0x0317, // 03=UNIX, 17=spec v2.3
338 kUsesDataDescr = 0x0008, // GPBitFlag bit 3
339 };
340
341 LocalFileHeader mLFH;
342 CentralDirEntry mCDE;
343};
344
345}; // namespace android
346
347#endif // __LIBS_ZIPENTRY_H