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