123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "io/stream.h"
- #include "io/zip/centralDir.h"
- #include "io/zip/compressor.h"
- #include "memory/safeDelete.h"
- namespace Zip
- {
- //////////////////////////////////////////////////////////////////////////
- // CentralDir Class
- //////////////////////////////////////////////////////////////////////////
- CentralDir::CentralDir()
- {
- mHeaderSig = mCentralDirSignature;
- mDiskNumStart = 0;
- mInternalFileAttr = 0;
- mExternalFileAttr = 0;
- mLocalHeadOffset = 0;
-
- mVersionMadeBy = 0;
- mFileComment = NULL;
- mInternalFlags = 0;
- }
- CentralDir::CentralDir(FileHeader &fh) : FileHeader(fh)
- {
- mHeaderSig = mCentralDirSignature;
- mDiskNumStart = 0;
- mInternalFileAttr = 0;
- mExternalFileAttr = 0;
- mLocalHeadOffset = 0;
- mVersionMadeBy = 0;
- mFileComment = NULL;
- }
- CentralDir::~CentralDir()
- {
- SAFE_DELETE_ARRAY(mFileComment);
- }
- //////////////////////////////////////////////////////////////////////////
- bool CentralDir::read(Stream *stream)
- {
- stream->read(&mHeaderSig);
- if(mHeaderSig != mCentralDirSignature)
- return false;
- stream->read(&mVersionMadeBy);
- stream->read(&mExtractVer);
- stream->read(&mFlags);
- stream->read(&mCompressMethod);
- stream->read(&mModTime);
- stream->read(&mModDate);
- stream->read(&mCRC32);
- stream->read(&mCompressedSize);
- stream->read(&mUncompressedSize);
- U16 fnLen, efLen, fcLen;
- stream->read(&fnLen);
- stream->read(&efLen);
- stream->read(&fcLen);
- stream->read(&mDiskNumStart);
- stream->read(&mInternalFileAttr);
- stream->read(&mExternalFileAttr);
- stream->read(&mLocalHeadOffset);
- char *fn = new char[fnLen + 1];
- stream->read(fnLen, fn);
- fn[fnLen] = 0;
- SAFE_DELETE_ARRAY(mFilename);
- mFilename = fn;
- // [tom, 10/28/2006] We currently only need the extra fields when we want to
- // open the file, so we won't bother reading them here. This avoids keeping
- // them in memory twice.
- //readExtraFields(stream, efLen);
- stream->setPosition(stream->getPosition() + efLen);
- fn = new char[fcLen + 1];
- stream->read(fcLen, fn);
- fn[fcLen] = 0;
- SAFE_DELETE_ARRAY(mFileComment);
- mFileComment = fn;
- // Sanity checks to make life easier elsewhere
- if(mCompressMethod != Stored && mUncompressedSize == 0 && mCompressedSize == 0)
- mCompressMethod = Stored;
- return true;
- }
- bool CentralDir::write(Stream *stream)
- {
- mHeaderSig = mCentralDirSignature;
- stream->write(mHeaderSig);
- stream->write(mVersionMadeBy);
- stream->write(mExtractVer);
- stream->write(mFlags);
- stream->write(mCompressMethod);
- stream->write(mModTime);
- stream->write(mModDate);
- stream->write(mCRC32);
- stream->write(mCompressedSize);
- stream->write(mUncompressedSize);
- U16 fnLen = mFilename ? (U16)dStrlen(mFilename) : 0,
- efLen = 0,
- fcLen = mFileComment ? (U16)dStrlen(mFileComment) : 0;
- stream->write(fnLen);
- stream->write(efLen);
- stream->write(fcLen);
- stream->write(mDiskNumStart);
- stream->write(mInternalFileAttr);
- stream->write(mExternalFileAttr);
- stream->write(mLocalHeadOffset);
- if(fnLen)
- stream->write(fnLen, mFilename);
- // FIXME [tom, 10/29/2006] Write extra fields here
- if(fcLen)
- stream->write(fcLen, mFileComment);
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- void CentralDir::setFileComment(const char *comment)
- {
- SAFE_DELETE_ARRAY(mFileComment);
- mFileComment = new char [dStrlen(comment)+1];
- dStrcpy((char *)mFileComment, comment);
- }
- //////////////////////////////////////////////////////////////////////////
- // EndOfCentralDir Class
- //////////////////////////////////////////////////////////////////////////
- EndOfCentralDir::EndOfCentralDir()
- {
- mHeaderSig = mEOCDSignature;
- mDiskNum = 0;
- mStartCDDiskNum = 0;
- mNumEntriesInThisCD = 0;
- mTotalEntriesInCD = 0;
- mCDSize = 0;
- mCDOffset = 0;
- mCommentSize = 0;
- mZipComment = NULL;
- }
- EndOfCentralDir::~EndOfCentralDir()
- {
- SAFE_DELETE_ARRAY(mZipComment);
- }
- //////////////////////////////////////////////////////////////////////////
- bool EndOfCentralDir::read(Stream *stream)
- {
- stream->read(&mHeaderSig);
- if(mHeaderSig != mEOCDSignature)
- return false;
- stream->read(&mDiskNum);
- stream->read(&mStartCDDiskNum);
- stream->read(&mNumEntriesInThisCD);
- stream->read(&mTotalEntriesInCD);
- stream->read(&mCDSize);
- stream->read(&mCDOffset);
- stream->read(&mCommentSize);
-
- char *comment = new char[mCommentSize + 1];
- stream->read(mCommentSize, comment);
- comment[mCommentSize] = 0;
- SAFE_DELETE_ARRAY(mZipComment);
- mZipComment = comment;
- return true;
- }
- bool EndOfCentralDir::write(Stream *stream)
- {
- stream->write(mHeaderSig);
- stream->write(mDiskNum);
- stream->write(mStartCDDiskNum);
- stream->write(mNumEntriesInThisCD);
- stream->write(mTotalEntriesInCD);
- stream->write(mCDSize);
- stream->write(mCDOffset);
- stream->write(mCommentSize);
- if(mZipComment && mCommentSize)
- stream->write(mCommentSize, mZipComment);
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- // [tom, 10/19/2006] I know, i know ... this'll get rewritten.
- // [tom, 1/23/2007] Maybe.
- bool EndOfCentralDir::findInStream(Stream *stream)
- {
- U32 initialPos = stream->getPosition();
- U32 size = stream->getStreamSize();
- U32 pos;
- if(size == 0)
- return false;
- if(! stream->setPosition(size - mRecordSize))
- goto hell;
- U32 sig;
- stream->read(&sig);
- if(sig == mEOCDSignature)
- {
- stream->setPosition(size - mRecordSize);
- return true;
- }
- // OK, so we couldn't find the EOCD where we expected it. The zip file
- // either has comments or isn't a zip file. We need to search the last
- // 64Kb of the file for the EOCD.
- pos = size > mEOCDSearchSize ? size - mEOCDSearchSize : 0;
- if(! stream->setPosition(pos))
- goto hell;
- while(pos < (size - 4))
- {
- stream->read(&sig);
- if(sig == mEOCDSignature)
- {
- stream->setPosition(pos);
- return true;
- }
- pos++;
- if(! stream->setPosition(pos))
- goto hell;
- }
- hell:
- stream->setPosition(initialPos);
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void EndOfCentralDir::setZipComment(U16 commentSize, const char *zipComment)
- {
- SAFE_DELETE_ARRAY(mZipComment);
- mZipComment = new char [commentSize];
- dMemcpy((void *)mZipComment, zipComment, commentSize);
- mCommentSize = commentSize;
- }
- void EndOfCentralDir::setZipComment(const char *zipComment)
- {
- setZipComment(dStrlen(zipComment), zipComment);
- }
- } // end namespace Zip
|