blob: 2745a43862782dba569791d69ea81972b8b74880 [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
Adam Lesinskid5c4f872015-04-21 13:56:10 -0700174 * another file. If fileName is non-NULL, override the name with fileName.
Adam Lesinski769de982015-04-10 19:43:55 -0700175 */
Adam Lesinskid5c4f872015-04-21 13:56:10 -0700176 status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry,
177 const char* fileName);
Adam Lesinski769de982015-04-10 19:43:55 -0700178
179 /*
180 * Add some pad bytes to the LFH. We do this by adding or resizing
181 * the "extra" field.
182 */
183 status_t addPadding(int padding);
184
185 /*
186 * Set information about the data for this entry.
187 */
188 void setDataInfo(long uncompLen, long compLen, unsigned long crc32,
189 int compressionMethod);
190
191 /*
192 * Set the modification date.
193 */
194 void setModWhen(time_t when);
195
196 /*
197 * Set the offset of the local file header, relative to the start of
198 * the current file.
199 */
200 void setLFHOffset(off_t offset) {
201 mCDE.mLocalHeaderRelOffset = (long) offset;
202 }
203
204 /* mark for deletion; used by ZipFile::remove() */
205 void setDeleted(void) { mDeleted = true; }
206
207private:
208 /* these are private and not defined */
209 ZipEntry(const ZipEntry& src);
210 ZipEntry& operator=(const ZipEntry& src);
211
212 /* returns "true" if the CDE and the LFH agree */
213 bool compareHeaders(void) const;
214 void copyCDEtoLFH(void);
215
216 bool mDeleted; // set if entry is pending deletion
217 bool mMarked; // app-defined marker
218
219 /*
220 * Every entry in the Zip archive starts off with one of these.
221 */
222 class LocalFileHeader {
223 public:
224 LocalFileHeader(void) :
225 mVersionToExtract(0),
226 mGPBitFlag(0),
227 mCompressionMethod(0),
228 mLastModFileTime(0),
229 mLastModFileDate(0),
230 mCRC32(0),
231 mCompressedSize(0),
232 mUncompressedSize(0),
233 mFileNameLength(0),
234 mExtraFieldLength(0),
235 mFileName(NULL),
236 mExtraField(NULL)
237 {}
238 virtual ~LocalFileHeader(void) {
239 delete[] mFileName;
240 delete[] mExtraField;
241 }
242
243 status_t read(FILE* fp);
244 status_t write(FILE* fp);
245
246 // unsigned long mSignature;
247 unsigned short mVersionToExtract;
248 unsigned short mGPBitFlag;
249 unsigned short mCompressionMethod;
250 unsigned short mLastModFileTime;
251 unsigned short mLastModFileDate;
252 unsigned long mCRC32;
253 unsigned long mCompressedSize;
254 unsigned long mUncompressedSize;
255 unsigned short mFileNameLength;
256 unsigned short mExtraFieldLength;
257 unsigned char* mFileName;
258 unsigned char* mExtraField;
259
260 enum {
261 kSignature = 0x04034b50,
262 kLFHLen = 30, // LocalFileHdr len, excl. var fields
263 };
264
265 void dump(void) const;
266 };
267
268 /*
269 * Every entry in the Zip archive has one of these in the "central
270 * directory" at the end of the file.
271 */
272 class CentralDirEntry {
273 public:
274 CentralDirEntry(void) :
275 mVersionMadeBy(0),
276 mVersionToExtract(0),
277 mGPBitFlag(0),
278 mCompressionMethod(0),
279 mLastModFileTime(0),
280 mLastModFileDate(0),
281 mCRC32(0),
282 mCompressedSize(0),
283 mUncompressedSize(0),
284 mFileNameLength(0),
285 mExtraFieldLength(0),
286 mFileCommentLength(0),
287 mDiskNumberStart(0),
288 mInternalAttrs(0),
289 mExternalAttrs(0),
290 mLocalHeaderRelOffset(0),
291 mFileName(NULL),
292 mExtraField(NULL),
293 mFileComment(NULL)
294 {}
295 virtual ~CentralDirEntry(void) {
296 delete[] mFileName;
297 delete[] mExtraField;
298 delete[] mFileComment;
299 }
300
301 status_t read(FILE* fp);
302 status_t write(FILE* fp);
303
304 CentralDirEntry& operator=(const CentralDirEntry& src);
305
306 // unsigned long mSignature;
307 unsigned short mVersionMadeBy;
308 unsigned short mVersionToExtract;
309 unsigned short mGPBitFlag;
310 unsigned short mCompressionMethod;
311 unsigned short mLastModFileTime;
312 unsigned short mLastModFileDate;
313 unsigned long mCRC32;
314 unsigned long mCompressedSize;
315 unsigned long mUncompressedSize;
316 unsigned short mFileNameLength;
317 unsigned short mExtraFieldLength;
318 unsigned short mFileCommentLength;
319 unsigned short mDiskNumberStart;
320 unsigned short mInternalAttrs;
321 unsigned long mExternalAttrs;
322 unsigned long mLocalHeaderRelOffset;
323 unsigned char* mFileName;
324 unsigned char* mExtraField;
325 unsigned char* mFileComment;
326
327 void dump(void) const;
328
329 enum {
330 kSignature = 0x02014b50,
331 kCDELen = 46, // CentralDirEnt len, excl. var fields
332 };
333 };
334
335 enum {
336 //kDataDescriptorSignature = 0x08074b50, // currently unused
337 kDataDescriptorLen = 16, // four 32-bit fields
338
339 kDefaultVersion = 20, // need deflate, nothing much else
340 kDefaultMadeBy = 0x0317, // 03=UNIX, 17=spec v2.3
341 kUsesDataDescr = 0x0008, // GPBitFlag bit 3
342 };
343
344 LocalFileHeader mLFH;
345 CentralDirEntry mCDE;
346};
347
348}; // namespace aapt
349
350#endif // __LIBS_ZIPENTRY_H