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