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