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