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