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 #include <time.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 offset of the local file header. 77 */ getLFHOffset(void)78 off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; } 79 80 /* 81 * Return the absolute file offset of the start of the compressed or 82 * uncompressed data. 83 */ getFileOffset(void)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 */ getCRC32(void)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 */ getFileName(void)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 */ getMarked(void)110 bool getMarked(void) const { return mMarked; } setMarked(bool val)111 void setMarked(bool val) { mMarked = val; } 112 113 /* 114 * Some basic functions for raw data manipulation. "LE" means 115 * Little Endian. 116 */ getShortLE(const unsigned char * buf)117 static inline unsigned short getShortLE(const unsigned char* buf) { 118 return buf[0] | (buf[1] << 8); 119 } getLongLE(const unsigned char * buf)120 static inline unsigned long getLongLE(const unsigned char* buf) { 121 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 122 } putShortLE(unsigned char * buf,short val)123 static inline void putShortLE(unsigned char* buf, short val) { 124 buf[0] = (unsigned char) val; 125 buf[1] = (unsigned char) (val >> 8); 126 } putLongLE(unsigned char * buf,long val)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 */ getDeleted(void)155 bool getDeleted(void) const { return mDeleted; } 156 157 protected: 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 /* 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 = (long) 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 // 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: 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 CentralDirEntry& operator=(const CentralDirEntry& src); 303 304 // 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 349