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 <stdint.h> 29 #include <stdio.h> 30 #include <time.h> 31 32 namespace android { 33 34 class 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 */ 48 class ZipEntry { 49 public: 50 friend class ZipFile; 51 ZipEntry(void)52 ZipEntry(void) 53 : mDeleted(false), mMarked(false) 54 {} ~ZipEntry(void)55 ~ZipEntry(void) {} 56 57 /* 58 * Returns "true" if the data is compressed. 59 */ isCompressed(void)60 bool isCompressed(void) const { 61 return mCDE.mCompressionMethod != kCompressStored; 62 } getCompressionMethod(void)63 int getCompressionMethod(void) const { return mCDE.mCompressionMethod; } 64 65 /* 66 * Return the uncompressed length. 67 */ getUncompressedLen(void)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 */ getCompressedLen(void)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 */ getFileOffset(void)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 */ getCRC32(void)90 uint32_t getCRC32(void) const { return mCDE.mCRC32; } 91 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 */ getFileName(void)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 */ getMarked(void)106 bool getMarked(void) const { return mMarked; } setMarked(bool val)107 void setMarked(bool val) { mMarked = val; } 108 109 /* 110 * Some basic functions for raw data manipulation. "LE" means 111 * Little Endian. 112 */ getShortLE(const uint8_t * buf)113 static inline uint16_t getShortLE(const uint8_t* buf) { 114 return buf[0] | (buf[1] << 8); 115 } getLongLE(const uint8_t * buf)116 static inline uint32_t getLongLE(const uint8_t* buf) { 117 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 118 } putShortLE(uint8_t * buf,uint16_t val)119 static inline void putShortLE(uint8_t* buf, uint16_t val) { 120 buf[0] = (uint8_t) val; 121 buf[1] = (uint8_t) (val >> 8); 122 } putLongLE(uint8_t * buf,uint32_t val)123 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); 128 } 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 */ getDeleted(void)151 bool getDeleted(void) const { return mDeleted; } 152 153 protected: 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 */ 171 status_t initFromExternal(const ZipEntry* pEntry); 172 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 */ 182 void setDataInfo(uint32_t uncompLen, uint32_t compLen, uint32_t crc32, 183 uint32_t compressionMethod); 184 185 /* 186 * Set the modification date. 187 */ 188 void setModWhen(time_t when); 189 190 /* 191 * Return the offset of the local file header. 192 */ getLFHOffset(void)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 */ setLFHOffset(off_t offset)199 void setLFHOffset(off_t offset) { 200 mCDE.mLocalHeaderRelOffset = (uint32_t) offset; 201 } 202 203 /* mark for deletion; used by ZipFile::remove() */ setDeleted(void)204 void setDeleted(void) { mDeleted = true; } 205 206 private: 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: LocalFileHeader(void)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 {} ~LocalFileHeader(void)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 245 // 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; 258 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: CentralDirEntry(void)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 {} ~CentralDirEntry(void)294 ~CentralDirEntry(void) { 295 delete[] mFileName; 296 delete[] mExtraField; 297 delete[] mFileComment; 298 } 299 300 status_t read(FILE* fp); 301 status_t write(FILE* fp); 302 303 // 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; 323 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 348