blob: 669e7395be5bea2f3f3948a2d85013d8923973f4 [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>
Mathias Agopiandf7707c2017-02-28 17:43:39 -080029#include <time.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
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 /*
Kenny Rootfb2a9462010-08-25 07:36:31 -070076 * Return the offset of the local file header.
77 */
78 off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
79
80 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 * Return the absolute file offset of the start of the compressed or
82 * uncompressed data.
83 */
84 off_t getFileOffset(void) const {
85 return mCDE.mLocalHeaderRelOffset +
86 LocalFileHeader::kLFHLen +
87 mLFH.mFileNameLength +
88 mLFH.mExtraFieldLength;
89 }
90
91 /*
92 * Return the data CRC.
93 */
94 unsigned long getCRC32(void) const { return mCDE.mCRC32; }
95
96 /*
97 * Return file modification time in UNIX seconds-since-epoch.
98 */
99 time_t getModWhen(void) const;
100
101 /*
102 * Return the archived file name.
103 */
104 const char* getFileName(void) const { return (const char*) mCDE.mFileName; }
105
106 /*
107 * Application-defined "mark". Can be useful when synchronizing the
108 * contents of an archive with contents on disk.
109 */
110 bool getMarked(void) const { return mMarked; }
111 void setMarked(bool val) { mMarked = val; }
112
113 /*
114 * Some basic functions for raw data manipulation. "LE" means
115 * Little Endian.
116 */
117 static inline unsigned short getShortLE(const unsigned char* buf) {
118 return buf[0] | (buf[1] << 8);
119 }
120 static inline unsigned long getLongLE(const unsigned char* buf) {
121 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
122 }
123 static inline void putShortLE(unsigned char* buf, short val) {
124 buf[0] = (unsigned char) val;
125 buf[1] = (unsigned char) (val >> 8);
126 }
127 static inline void putLongLE(unsigned char* buf, long val) {
128 buf[0] = (unsigned char) val;
129 buf[1] = (unsigned char) (val >> 8);
130 buf[2] = (unsigned char) (val >> 16);
131 buf[3] = (unsigned char) (val >> 24);
132 }
133
134 /* defined for Zip archives */
135 enum {
136 kCompressStored = 0, // no compression
137 // shrunk = 1,
138 // reduced 1 = 2,
139 // reduced 2 = 3,
140 // reduced 3 = 4,
141 // reduced 4 = 5,
142 // imploded = 6,
143 // tokenized = 7,
144 kCompressDeflated = 8, // standard deflate
145 // Deflate64 = 9,
146 // lib imploded = 10,
147 // reserved = 11,
148 // bzip2 = 12,
149 };
150
151 /*
152 * Deletion flag. If set, the entry will be removed on the next
153 * call to "flush".
154 */
155 bool getDeleted(void) const { return mDeleted; }
156
157protected:
158 /*
159 * Initialize the structure from the file, which is pointing at
160 * our Central Directory entry.
161 */
162 status_t initFromCDE(FILE* fp);
163
164 /*
165 * Initialize the structure for a new file. We need the filename
166 * and comment so that we can properly size the LFH area. The
167 * filename is mandatory, the comment is optional.
168 */
169 void initNew(const char* fileName, const char* comment);
170
171 /*
172 * Initialize the structure with the contents of a ZipEntry from
173 * another file.
174 */
175 status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry);
176
177 /*
178 * Add some pad bytes to the LFH. We do this by adding or resizing
179 * the "extra" field.
180 */
181 status_t addPadding(int padding);
182
183 /*
184 * Set information about the data for this entry.
185 */
186 void setDataInfo(long uncompLen, long compLen, unsigned long crc32,
187 int compressionMethod);
188
189 /*
190 * Set the modification date.
191 */
192 void setModWhen(time_t when);
193
194 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 * Set the offset of the local file header, relative to the start of
196 * the current file.
197 */
198 void setLFHOffset(off_t offset) {
199 mCDE.mLocalHeaderRelOffset = (long) offset;
200 }
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
244 // unsigned long mSignature;
245 unsigned short mVersionToExtract;
246 unsigned short mGPBitFlag;
247 unsigned short mCompressionMethod;
248 unsigned short mLastModFileTime;
249 unsigned short mLastModFileDate;
250 unsigned long mCRC32;
251 unsigned long mCompressedSize;
252 unsigned long mUncompressedSize;
253 unsigned short mFileNameLength;
254 unsigned short mExtraFieldLength;
255 unsigned char* mFileName;
256 unsigned char* mExtraField;
257
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 {}
293 virtual ~CentralDirEntry(void) {
294 delete[] mFileName;
295 delete[] mExtraField;
296 delete[] mFileComment;
297 }
298
299 status_t read(FILE* fp);
300 status_t write(FILE* fp);
301
Andreas Gampe2412f842014-09-30 20:55:57 -0700302 CentralDirEntry& operator=(const CentralDirEntry& src);
303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 // unsigned long mSignature;
305 unsigned short mVersionMadeBy;
306 unsigned short mVersionToExtract;
307 unsigned short mGPBitFlag;
308 unsigned short mCompressionMethod;
309 unsigned short mLastModFileTime;
310 unsigned short mLastModFileDate;
311 unsigned long mCRC32;
312 unsigned long mCompressedSize;
313 unsigned long mUncompressedSize;
314 unsigned short mFileNameLength;
315 unsigned short mExtraFieldLength;
316 unsigned short mFileCommentLength;
317 unsigned short mDiskNumberStart;
318 unsigned short mInternalAttrs;
319 unsigned long mExternalAttrs;
320 unsigned long mLocalHeaderRelOffset;
321 unsigned char* mFileName;
322 unsigned char* mExtraField;
323 unsigned char* mFileComment;
324
325 void dump(void) const;
326
327 enum {
328 kSignature = 0x02014b50,
329 kCDELen = 46, // CentralDirEnt len, excl. var fields
330 };
331 };
332
333 enum {
334 //kDataDescriptorSignature = 0x08074b50, // currently unused
335 kDataDescriptorLen = 16, // four 32-bit fields
336
337 kDefaultVersion = 20, // need deflate, nothing much else
338 kDefaultMadeBy = 0x0317, // 03=UNIX, 17=spec v2.3
339 kUsesDataDescr = 0x0008, // GPBitFlag bit 3
340 };
341
342 LocalFileHeader mLFH;
343 CentralDirEntry mCDE;
344};
345
346}; // namespace android
347
348#endif // __LIBS_ZIPENTRY_H