| /* | 
 |  * 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 <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 offset of the local file header. | 
 |      */ | 
 |     off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; } | 
 |  | 
 |     /* | 
 |      * 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. | 
 |      */ | 
 |     unsigned long 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 unsigned short getShortLE(const unsigned char* buf) { | 
 |         return buf[0] | (buf[1] << 8); | 
 |     } | 
 |     static inline unsigned long getLongLE(const unsigned char* buf) { | 
 |         return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); | 
 |     } | 
 |     static inline void putShortLE(unsigned char* buf, short val) { | 
 |         buf[0] = (unsigned char) val; | 
 |         buf[1] = (unsigned char) (val >> 8); | 
 |     } | 
 |     static inline void putLongLE(unsigned char* buf, long val) { | 
 |         buf[0] = (unsigned char) val; | 
 |         buf[1] = (unsigned char) (val >> 8); | 
 |         buf[2] = (unsigned char) (val >> 16); | 
 |         buf[3] = (unsigned char) (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, unsigned long crc32, | 
 |         int compressionMethod); | 
 |  | 
 |     /* | 
 |      * Set the modification date. | 
 |      */ | 
 |     void setModWhen(time_t when); | 
 |  | 
 |     /* | 
 |      * Set the offset of the local file header, relative to the start of | 
 |      * the current file. | 
 |      */ | 
 |     void setLFHOffset(off_t offset) { | 
 |         mCDE.mLocalHeaderRelOffset = (long) 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); | 
 |  | 
 |         // unsigned long mSignature; | 
 |         unsigned short  mVersionToExtract; | 
 |         unsigned short  mGPBitFlag; | 
 |         unsigned short  mCompressionMethod; | 
 |         unsigned short  mLastModFileTime; | 
 |         unsigned short  mLastModFileDate; | 
 |         unsigned long   mCRC32; | 
 |         unsigned long   mCompressedSize; | 
 |         unsigned long   mUncompressedSize; | 
 |         unsigned short  mFileNameLength; | 
 |         unsigned short  mExtraFieldLength; | 
 |         unsigned char*  mFileName; | 
 |         unsigned char*  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); | 
 |  | 
 |         // unsigned long mSignature; | 
 |         unsigned short  mVersionMadeBy; | 
 |         unsigned short  mVersionToExtract; | 
 |         unsigned short  mGPBitFlag; | 
 |         unsigned short  mCompressionMethod; | 
 |         unsigned short  mLastModFileTime; | 
 |         unsigned short  mLastModFileDate; | 
 |         unsigned long   mCRC32; | 
 |         unsigned long   mCompressedSize; | 
 |         unsigned long   mUncompressedSize; | 
 |         unsigned short  mFileNameLength; | 
 |         unsigned short  mExtraFieldLength; | 
 |         unsigned short  mFileCommentLength; | 
 |         unsigned short  mDiskNumberStart; | 
 |         unsigned short  mInternalAttrs; | 
 |         unsigned long   mExternalAttrs; | 
 |         unsigned long   mLocalHeaderRelOffset; | 
 |         unsigned char*  mFileName; | 
 |         unsigned char*  mExtraField; | 
 |         unsigned char*  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 |