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 31 namespace android { 32 33 class 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 */ 47 class ZipEntry { 48 public: 49 friend class ZipFile; 50 ZipEntry(void)51 ZipEntry(void) 52 : mDeleted(false), mMarked(false) 53 {} ~ZipEntry(void)54 ~ZipEntry(void) {} 55 56 /* 57 * Returns "true" if the data is compressed. 58 */ isCompressed(void)59 bool isCompressed(void) const { 60 return mCDE.mCompressionMethod != kCompressStored; 61 } getCompressionMethod(void)62 int getCompressionMethod(void) const { return mCDE.mCompressionMethod; } 63 64 /* 65 * Return the uncompressed length. 66 */ getUncompressedLen(void)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 */ getCompressedLen(void)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 */ getFileOffset(void)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 */ getCRC32(void)89 uint32_t getCRC32(void) const { return mCDE.mCRC32; } 90 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 */ getFileName(void)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 */ getMarked(void)105 bool getMarked(void) const { return mMarked; } setMarked(bool val)106 void setMarked(bool val) { mMarked = val; } 107 108 /* 109 * Some basic functions for raw data manipulation. "LE" means 110 * Little Endian. 111 */ getShortLE(const uint8_t * buf)112 static inline uint16_t getShortLE(const uint8_t* buf) { 113 return buf[0] | (buf[1] << 8); 114 } getLongLE(const uint8_t * buf)115 static inline uint32_t getLongLE(const uint8_t* buf) { 116 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 117 } putShortLE(uint8_t * buf,uint16_t val)118 static inline void putShortLE(uint8_t* buf, uint16_t val) { 119 buf[0] = (uint8_t) val; 120 buf[1] = (uint8_t) (val >> 8); 121 } putLongLE(uint8_t * buf,uint32_t val)122 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); 127 } 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 */ getDeleted(void)150 bool getDeleted(void) const { return mDeleted; } 151 152 protected: 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 */ 170 status_t initFromExternal(const ZipEntry* pEntry); 171 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 */ 181 void setDataInfo(long uncompLen, long compLen, uint32_t crc32, 182 int compressionMethod); 183 184 /* 185 * Set the modification date. 186 */ 187 void setModWhen(time_t when); 188 189 /* 190 * Return the offset of the local file header. 191 */ getLFHOffset(void)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 */ setLFHOffset(off_t offset)198 void setLFHOffset(off_t offset) { 199 mCDE.mLocalHeaderRelOffset = (uint32_t) offset; 200 } 201 202 /* mark for deletion; used by ZipFile::remove() */ setDeleted(void)203 void setDeleted(void) { mDeleted = true; } 204 205 private: 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: LocalFileHeader(void)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 {} ~LocalFileHeader(void)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 // 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; 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: CentralDirEntry(void)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 {} ~CentralDirEntry(void)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 302 // 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; 322 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 347