blob: 4c7e18c2c709c71e3757de78bb0c0ce4912c1cfa [file] [log] [blame]
Mathias Agopian3344b2e2009-06-05 14:55:48 -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>
Dan Willemsen41bc4242015-11-04 14:08:20 -080028#include <stdint.h>
Mathias Agopian3344b2e2009-06-05 14:55:48 -070029#include <stdio.h>
Mathias Agopian319524b2017-02-28 17:40:33 -080030#include <time.h>
Mathias Agopian3344b2e2009-06-05 14:55:48 -070031
32namespace android {
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 absolute file offset of the start of the compressed or
78 * uncompressed data.
79 */
80 off_t getFileOffset(void) const {
81 return mCDE.mLocalHeaderRelOffset +
82 LocalFileHeader::kLFHLen +
83 mLFH.mFileNameLength +
84 mLFH.mExtraFieldLength;
85 }
86
87 /*
88 * Return the data CRC.
89 */
Dan Willemsen41bc4242015-11-04 14:08:20 -080090 uint32_t getCRC32(void) const { return mCDE.mCRC32; }
Mathias Agopian3344b2e2009-06-05 14:55:48 -070091
92 /*
93 * Return file modification time in UNIX seconds-since-epoch.
94 */
95 time_t getModWhen(void) const;
96
97 /*
98 * Return the archived file name.
99 */
100 const char* getFileName(void) const { return (const char*) mCDE.mFileName; }
101
102 /*
103 * Application-defined "mark". Can be useful when synchronizing the
104 * contents of an archive with contents on disk.
105 */
106 bool getMarked(void) const { return mMarked; }
107 void setMarked(bool val) { mMarked = val; }
108
109 /*
110 * Some basic functions for raw data manipulation. "LE" means
111 * Little Endian.
112 */
Dan Willemsen41bc4242015-11-04 14:08:20 -0800113 static inline uint16_t getShortLE(const uint8_t* buf) {
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700114 return buf[0] | (buf[1] << 8);
115 }
Dan Willemsen41bc4242015-11-04 14:08:20 -0800116 static inline uint32_t getLongLE(const uint8_t* buf) {
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700117 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
118 }
Dan Willemsen41bc4242015-11-04 14:08:20 -0800119 static inline void putShortLE(uint8_t* buf, uint16_t val) {
120 buf[0] = (uint8_t) val;
121 buf[1] = (uint8_t) (val >> 8);
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700122 }
Dan Willemsen41bc4242015-11-04 14:08:20 -0800123 static inline void putLongLE(uint8_t* buf, uint32_t val) {
124 buf[0] = (uint8_t) val;
125 buf[1] = (uint8_t) (val >> 8);
126 buf[2] = (uint8_t) (val >> 16);
127 buf[3] = (uint8_t) (val >> 24);
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700128 }
129
130 /* defined for Zip archives */
131 enum {
132 kCompressStored = 0, // no compression
133 // shrunk = 1,
134 // reduced 1 = 2,
135 // reduced 2 = 3,
136 // reduced 3 = 4,
137 // reduced 4 = 5,
138 // imploded = 6,
139 // tokenized = 7,
140 kCompressDeflated = 8, // standard deflate
141 // Deflate64 = 9,
142 // lib imploded = 10,
143 // reserved = 11,
144 // bzip2 = 12,
145 };
146
147 /*
148 * Deletion flag. If set, the entry will be removed on the next
149 * call to "flush".
150 */
151 bool getDeleted(void) const { return mDeleted; }
152
153protected:
154 /*
155 * Initialize the structure from the file, which is pointing at
156 * our Central Directory entry.
157 */
158 status_t initFromCDE(FILE* fp);
159
160 /*
161 * Initialize the structure for a new file. We need the filename
162 * and comment so that we can properly size the LFH area. The
163 * filename is mandatory, the comment is optional.
164 */
165 void initNew(const char* fileName, const char* comment);
166
167 /*
168 * Initialize the structure with the contents of a ZipEntry from
169 * another file.
170 */
Aurimas Liutikasaf1d7412016-02-11 18:11:21 -0800171 status_t initFromExternal(const ZipEntry* pEntry);
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700172
173 /*
174 * Add some pad bytes to the LFH. We do this by adding or resizing
175 * the "extra" field.
176 */
177 status_t addPadding(int padding);
178
179 /*
180 * Set information about the data for this entry.
181 */
Chih-Hung Hsieh0c0d9282018-08-10 15:14:26 -0700182 void setDataInfo(uint32_t uncompLen, uint32_t compLen, uint32_t crc32,
183 uint32_t compressionMethod);
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700184
185 /*
186 * Set the modification date.
187 */
188 void setModWhen(time_t when);
189
190 /*
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700191 * Return the offset of the local file header.
192 */
193 off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
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) {
Dan Willemsen41bc4242015-11-04 14:08:20 -0800200 mCDE.mLocalHeaderRelOffset = (uint32_t) offset;
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700201 }
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
Dan Willemsen41bc4242015-11-04 14:08:20 -0800245 // uint32_t mSignature;
246 uint16_t mVersionToExtract;
247 uint16_t mGPBitFlag;
248 uint16_t mCompressionMethod;
249 uint16_t mLastModFileTime;
250 uint16_t mLastModFileDate;
251 uint32_t mCRC32;
252 uint32_t mCompressedSize;
253 uint32_t mUncompressedSize;
254 uint16_t mFileNameLength;
255 uint16_t mExtraFieldLength;
256 uint8_t* mFileName;
257 uint8_t* mExtraField;
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700258
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 {}
Ying Wang0c38bc52016-03-17 14:44:42 -0700294 ~CentralDirEntry(void) {
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700295 delete[] mFileName;
296 delete[] mExtraField;
297 delete[] mFileComment;
298 }
299
300 status_t read(FILE* fp);
301 status_t write(FILE* fp);
302
Dan Willemsen41bc4242015-11-04 14:08:20 -0800303 // uint32_t mSignature;
304 uint16_t mVersionMadeBy;
305 uint16_t mVersionToExtract;
306 uint16_t mGPBitFlag;
307 uint16_t mCompressionMethod;
308 uint16_t mLastModFileTime;
309 uint16_t mLastModFileDate;
310 uint32_t mCRC32;
311 uint32_t mCompressedSize;
312 uint32_t mUncompressedSize;
313 uint16_t mFileNameLength;
314 uint16_t mExtraFieldLength;
315 uint16_t mFileCommentLength;
316 uint16_t mDiskNumberStart;
317 uint16_t mInternalAttrs;
318 uint32_t mExternalAttrs;
319 uint32_t mLocalHeaderRelOffset;
320 uint8_t* mFileName;
321 uint8_t* mExtraField;
322 uint8_t* mFileComment;
Mathias Agopian3344b2e2009-06-05 14:55:48 -0700323
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