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 ZipEntry(void)50 ZipEntry(void) 51 : mDeleted(false), mMarked(false) 52 {} ~ZipEntry(void)53 ~ZipEntry(void) {} 54 55 /* 56 * Returns "true" if the data is compressed. 57 */ isCompressed(void)58 bool isCompressed(void) const { 59 return mCDE.mCompressionMethod != kCompressStored; 60 } getCompressionMethod(void)61 int getCompressionMethod(void) const { return mCDE.mCompressionMethod; } 62 63 /* 64 * Return the uncompressed length. 65 */ getUncompressedLen(void)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 */ getCompressedLen(void)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 */ getFileOffset(void)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 */ getCRC32(void)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 */ getFileName(void)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 */ getMarked(void)104 bool getMarked(void) const { return mMarked; } setMarked(bool val)105 void setMarked(bool val) { mMarked = val; } 106 107 /* 108 * Some basic functions for raw data manipulation. "LE" means 109 * Little Endian. 110 */ getShortLE(const unsigned char * buf)111 static inline unsigned short getShortLE(const unsigned char* buf) { 112 return buf[0] | (buf[1] << 8); 113 } getLongLE(const unsigned char * buf)114 static inline unsigned long getLongLE(const unsigned char* buf) { 115 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 116 } putShortLE(unsigned char * buf,short val)117 static inline void putShortLE(unsigned char* buf, short val) { 118 buf[0] = (unsigned char) val; 119 buf[1] = (unsigned char) (val >> 8); 120 } putLongLE(unsigned char * buf,long val)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 */ getDeleted(void)149 bool getDeleted(void) const { return mDeleted; } 150 151 protected: 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 /* 189 * Return the offset of the local file header. 190 */ getLFHOffset(void)191 off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; } 192 193 /* 194 * Set the offset of the local file header, relative to the start of 195 * the current file. 196 */ setLFHOffset(off_t offset)197 void setLFHOffset(off_t offset) { 198 mCDE.mLocalHeaderRelOffset = (long) offset; 199 } 200 201 /* mark for deletion; used by ZipFile::remove() */ setDeleted(void)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: LocalFileHeader(void)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 {} ~LocalFileHeader(void)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: CentralDirEntry(void)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 {} ~CentralDirEntry(void)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 346