|  | /* | 
|  | * Copyright (C) 2006 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | // | 
|  | // Zip archive entries. | 
|  | // | 
|  | // The ZipEntry class is tightly meshed with the ZipFile class. | 
|  | // | 
|  | #ifndef __LIBS_ZIPENTRY_H | 
|  | #define __LIBS_ZIPENTRY_H | 
|  |  | 
|  | #include <utils/Errors.h> | 
|  |  | 
|  | #include <stdlib.h> | 
|  | #include <stdint.h> | 
|  | #include <stdio.h> | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | class ZipFile; | 
|  |  | 
|  | /* | 
|  | * ZipEntry objects represent a single entry in a Zip archive. | 
|  | * | 
|  | * You can use one of these to get or set information about an entry, but | 
|  | * there are no functions here for accessing the data itself.  (We could | 
|  | * tuck a pointer to the ZipFile in here for convenience, but that raises | 
|  | * the likelihood of using ZipEntry objects after discarding the ZipFile.) | 
|  | * | 
|  | * File information is stored in two places: next to the file data (the Local | 
|  | * File Header, and possibly a Data Descriptor), and at the end of the file | 
|  | * (the Central Directory Entry).  The two must be kept in sync. | 
|  | */ | 
|  | class ZipEntry { | 
|  | public: | 
|  | friend class ZipFile; | 
|  |  | 
|  | ZipEntry(void) | 
|  | : mDeleted(false), mMarked(false) | 
|  | {} | 
|  | ~ZipEntry(void) {} | 
|  |  | 
|  | /* | 
|  | * Returns "true" if the data is compressed. | 
|  | */ | 
|  | bool isCompressed(void) const { | 
|  | return mCDE.mCompressionMethod != kCompressStored; | 
|  | } | 
|  | int getCompressionMethod(void) const { return mCDE.mCompressionMethod; } | 
|  |  | 
|  | /* | 
|  | * Return the uncompressed length. | 
|  | */ | 
|  | off_t getUncompressedLen(void) const { return mCDE.mUncompressedSize; } | 
|  |  | 
|  | /* | 
|  | * Return the compressed length.  For uncompressed data, this returns | 
|  | * the same thing as getUncompresesdLen(). | 
|  | */ | 
|  | off_t getCompressedLen(void) const { return mCDE.mCompressedSize; } | 
|  |  | 
|  | /* | 
|  | * Return the absolute file offset of the start of the compressed or | 
|  | * uncompressed data. | 
|  | */ | 
|  | off_t getFileOffset(void) const { | 
|  | return mCDE.mLocalHeaderRelOffset + | 
|  | LocalFileHeader::kLFHLen + | 
|  | mLFH.mFileNameLength + | 
|  | mLFH.mExtraFieldLength; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Return the data CRC. | 
|  | */ | 
|  | uint32_t getCRC32(void) const { return mCDE.mCRC32; } | 
|  |  | 
|  | /* | 
|  | * Return file modification time in UNIX seconds-since-epoch. | 
|  | */ | 
|  | time_t getModWhen(void) const; | 
|  |  | 
|  | /* | 
|  | * Return the archived file name. | 
|  | */ | 
|  | const char* getFileName(void) const { return (const char*) mCDE.mFileName; } | 
|  |  | 
|  | /* | 
|  | * Application-defined "mark".  Can be useful when synchronizing the | 
|  | * contents of an archive with contents on disk. | 
|  | */ | 
|  | bool getMarked(void) const { return mMarked; } | 
|  | void setMarked(bool val) { mMarked = val; } | 
|  |  | 
|  | /* | 
|  | * Some basic functions for raw data manipulation.  "LE" means | 
|  | * Little Endian. | 
|  | */ | 
|  | static inline uint16_t getShortLE(const uint8_t* buf) { | 
|  | return buf[0] | (buf[1] << 8); | 
|  | } | 
|  | static inline uint32_t getLongLE(const uint8_t* buf) { | 
|  | return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); | 
|  | } | 
|  | static inline void putShortLE(uint8_t* buf, uint16_t val) { | 
|  | buf[0] = (uint8_t) val; | 
|  | buf[1] = (uint8_t) (val >> 8); | 
|  | } | 
|  | static inline void putLongLE(uint8_t* buf, uint32_t val) { | 
|  | buf[0] = (uint8_t) val; | 
|  | buf[1] = (uint8_t) (val >> 8); | 
|  | buf[2] = (uint8_t) (val >> 16); | 
|  | buf[3] = (uint8_t) (val >> 24); | 
|  | } | 
|  |  | 
|  | /* defined for Zip archives */ | 
|  | enum { | 
|  | kCompressStored     = 0,        // no compression | 
|  | // shrunk           = 1, | 
|  | // reduced 1        = 2, | 
|  | // reduced 2        = 3, | 
|  | // reduced 3        = 4, | 
|  | // reduced 4        = 5, | 
|  | // imploded         = 6, | 
|  | // tokenized        = 7, | 
|  | kCompressDeflated   = 8,        // standard deflate | 
|  | // Deflate64        = 9, | 
|  | // lib imploded     = 10, | 
|  | // reserved         = 11, | 
|  | // bzip2            = 12, | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * Deletion flag.  If set, the entry will be removed on the next | 
|  | * call to "flush". | 
|  | */ | 
|  | bool getDeleted(void) const { return mDeleted; } | 
|  |  | 
|  | protected: | 
|  | /* | 
|  | * Initialize the structure from the file, which is pointing at | 
|  | * our Central Directory entry. | 
|  | */ | 
|  | status_t initFromCDE(FILE* fp); | 
|  |  | 
|  | /* | 
|  | * Initialize the structure for a new file.  We need the filename | 
|  | * and comment so that we can properly size the LFH area.  The | 
|  | * filename is mandatory, the comment is optional. | 
|  | */ | 
|  | void initNew(const char* fileName, const char* comment); | 
|  |  | 
|  | /* | 
|  | * Initialize the structure with the contents of a ZipEntry from | 
|  | * another file. | 
|  | */ | 
|  | status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry); | 
|  |  | 
|  | /* | 
|  | * Add some pad bytes to the LFH.  We do this by adding or resizing | 
|  | * the "extra" field. | 
|  | */ | 
|  | status_t addPadding(int padding); | 
|  |  | 
|  | /* | 
|  | * Set information about the data for this entry. | 
|  | */ | 
|  | void setDataInfo(long uncompLen, long compLen, uint32_t crc32, | 
|  | int compressionMethod); | 
|  |  | 
|  | /* | 
|  | * Set the modification date. | 
|  | */ | 
|  | void setModWhen(time_t when); | 
|  |  | 
|  | /* | 
|  | * Return the offset of the local file header. | 
|  | */ | 
|  | off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; } | 
|  |  | 
|  | /* | 
|  | * Set the offset of the local file header, relative to the start of | 
|  | * the current file. | 
|  | */ | 
|  | void setLFHOffset(off_t offset) { | 
|  | mCDE.mLocalHeaderRelOffset = (uint32_t) offset; | 
|  | } | 
|  |  | 
|  | /* mark for deletion; used by ZipFile::remove() */ | 
|  | void setDeleted(void) { mDeleted = true; } | 
|  |  | 
|  | private: | 
|  | /* these are private and not defined */ | 
|  | ZipEntry(const ZipEntry& src); | 
|  | ZipEntry& operator=(const ZipEntry& src); | 
|  |  | 
|  | /* returns "true" if the CDE and the LFH agree */ | 
|  | bool compareHeaders(void) const; | 
|  | void copyCDEtoLFH(void); | 
|  |  | 
|  | bool        mDeleted;       // set if entry is pending deletion | 
|  | bool        mMarked;        // app-defined marker | 
|  |  | 
|  | /* | 
|  | * Every entry in the Zip archive starts off with one of these. | 
|  | */ | 
|  | class LocalFileHeader { | 
|  | public: | 
|  | LocalFileHeader(void) : | 
|  | mVersionToExtract(0), | 
|  | mGPBitFlag(0), | 
|  | mCompressionMethod(0), | 
|  | mLastModFileTime(0), | 
|  | mLastModFileDate(0), | 
|  | mCRC32(0), | 
|  | mCompressedSize(0), | 
|  | mUncompressedSize(0), | 
|  | mFileNameLength(0), | 
|  | mExtraFieldLength(0), | 
|  | mFileName(NULL), | 
|  | mExtraField(NULL) | 
|  | {} | 
|  | virtual ~LocalFileHeader(void) { | 
|  | delete[] mFileName; | 
|  | delete[] mExtraField; | 
|  | } | 
|  |  | 
|  | status_t read(FILE* fp); | 
|  | status_t write(FILE* fp); | 
|  |  | 
|  | // uint32_t mSignature; | 
|  | uint16_t mVersionToExtract; | 
|  | uint16_t mGPBitFlag; | 
|  | uint16_t mCompressionMethod; | 
|  | uint16_t mLastModFileTime; | 
|  | uint16_t mLastModFileDate; | 
|  | uint32_t mCRC32; | 
|  | uint32_t mCompressedSize; | 
|  | uint32_t mUncompressedSize; | 
|  | uint16_t mFileNameLength; | 
|  | uint16_t mExtraFieldLength; | 
|  | uint8_t* mFileName; | 
|  | uint8_t* mExtraField; | 
|  |  | 
|  | enum { | 
|  | kSignature      = 0x04034b50, | 
|  | kLFHLen         = 30,       // LocalFileHdr len, excl. var fields | 
|  | }; | 
|  |  | 
|  | void dump(void) const; | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * Every entry in the Zip archive has one of these in the "central | 
|  | * directory" at the end of the file. | 
|  | */ | 
|  | class CentralDirEntry { | 
|  | public: | 
|  | CentralDirEntry(void) : | 
|  | mVersionMadeBy(0), | 
|  | mVersionToExtract(0), | 
|  | mGPBitFlag(0), | 
|  | mCompressionMethod(0), | 
|  | mLastModFileTime(0), | 
|  | mLastModFileDate(0), | 
|  | mCRC32(0), | 
|  | mCompressedSize(0), | 
|  | mUncompressedSize(0), | 
|  | mFileNameLength(0), | 
|  | mExtraFieldLength(0), | 
|  | mFileCommentLength(0), | 
|  | mDiskNumberStart(0), | 
|  | mInternalAttrs(0), | 
|  | mExternalAttrs(0), | 
|  | mLocalHeaderRelOffset(0), | 
|  | mFileName(NULL), | 
|  | mExtraField(NULL), | 
|  | mFileComment(NULL) | 
|  | {} | 
|  | virtual ~CentralDirEntry(void) { | 
|  | delete[] mFileName; | 
|  | delete[] mExtraField; | 
|  | delete[] mFileComment; | 
|  | } | 
|  |  | 
|  | status_t read(FILE* fp); | 
|  | status_t write(FILE* fp); | 
|  |  | 
|  | // uint32_t mSignature; | 
|  | uint16_t mVersionMadeBy; | 
|  | uint16_t mVersionToExtract; | 
|  | uint16_t mGPBitFlag; | 
|  | uint16_t mCompressionMethod; | 
|  | uint16_t mLastModFileTime; | 
|  | uint16_t mLastModFileDate; | 
|  | uint32_t mCRC32; | 
|  | uint32_t mCompressedSize; | 
|  | uint32_t mUncompressedSize; | 
|  | uint16_t mFileNameLength; | 
|  | uint16_t mExtraFieldLength; | 
|  | uint16_t mFileCommentLength; | 
|  | uint16_t mDiskNumberStart; | 
|  | uint16_t mInternalAttrs; | 
|  | uint32_t mExternalAttrs; | 
|  | uint32_t mLocalHeaderRelOffset; | 
|  | uint8_t* mFileName; | 
|  | uint8_t* mExtraField; | 
|  | uint8_t* mFileComment; | 
|  |  | 
|  | void dump(void) const; | 
|  |  | 
|  | enum { | 
|  | kSignature      = 0x02014b50, | 
|  | kCDELen         = 46,       // CentralDirEnt len, excl. var fields | 
|  | }; | 
|  | }; | 
|  |  | 
|  | enum { | 
|  | //kDataDescriptorSignature  = 0x08074b50,   // currently unused | 
|  | kDataDescriptorLen  = 16,           // four 32-bit fields | 
|  |  | 
|  | kDefaultVersion     = 20,           // need deflate, nothing much else | 
|  | kDefaultMadeBy      = 0x0317,       // 03=UNIX, 17=spec v2.3 | 
|  | kUsesDataDescr      = 0x0008,       // GPBitFlag bit 3 | 
|  | }; | 
|  |  | 
|  | LocalFileHeader     mLFH; | 
|  | CentralDirEntry     mCDE; | 
|  | }; | 
|  |  | 
|  | }; // namespace android | 
|  |  | 
|  | #endif // __LIBS_ZIPENTRY_H |