/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include "stdafx.h" #undef max #include #include "ZipFileFormat.h" #include "zipdirstructures.h" #include "ZipDirList.h" #include "ZipDirTree.h" ZipDir::FileRecordList::FileRecordList(FileEntryTree* pTree) { clear(); reserve(pTree->NumFilesTotal()); AddAllFiles(pTree); } //recursively adds the files from this directory and subdirectories // the strRoot contains the trailing slash void ZipDir::FileRecordList::AddAllFiles(FileEntryTree* pTree, string strRoot) { for (FileEntryTree::SubdirMap::iterator it = pTree->GetDirBegin(); it != pTree->GetDirEnd(); ++it) { AddAllFiles (it->second, strRoot + it->second->GetOriginalName() + "/"); } for (FileEntryTree::FileMap::iterator it = pTree->GetFileBegin(); it != pTree->GetFileEnd(); ++it) { FileRecord rec; rec.pFileEntry = pTree->GetFileEntry(it); const char* filename = rec.pFileEntry->szOriginalFileName ? rec.pFileEntry->szOriginalFileName : it->first; rec.strPath = strRoot + filename; push_back(rec); } } // sorts the files by the physical offset in the zip file void ZipDir::FileRecordList::SortByFileOffset() { std::sort (begin(), end(), FileRecordFileOffsetOrder()); } // returns the size of CDR in the zip file ZipDir::FileRecordList::ZipStats ZipDir::FileRecordList::GetStats() const { ZipStats Stats; Stats.nSizeCDR = sizeof(ZipFile::CDREnd); Stats.nSizeCompactData = 0; // for each file, we'll need to store only its CDR header and the name for (const_iterator it = begin(); it != end(); ++it) { Stats.nSizeCDR += sizeof(ZipFile::CDRFileHeader) + it->strPath.length(); Stats.nSizeCompactData += sizeof(ZipFile::LocalFileHeader) + it->strPath.length() + it->pFileEntry->desc.lSizeCompressed; } return Stats; } // puts the CDR into the given block of mem size_t ZipDir::FileRecordList::MakeZipCDR(ZipFile::ulong lCDROffset, void* pBuffer, bool encryptedFlag) const { const ZipFile::ushort nBaseVersion = std::max(encryptedFlag ? ZipFile::VERSION_ENCRYPTION_PKWARE : ZipFile::VERSION_DEFAULT, ZipFile::VERSION_COMPRESSION_DEFLATE); char* pCur = (char*)pBuffer; for (const_iterator it = begin(); it != end(); ++it) { ZipFile::CDRFileHeader& h = *(ZipFile::CDRFileHeader*)pCur; pCur = (char*)(&h + 1); h.lSignature = h.SIGNATURE; h.nVersionMadeBy = nBaseVersion + (ZipFile::CREATOR_MSDOS << 8); h.nVersionNeeded = nBaseVersion; h.nFlags = 0; h.nMethod = it->pFileEntry->nMethod; h.nLastModTime = it->pFileEntry->nLastModTime; h.nLastModDate = it->pFileEntry->nLastModDate; h.desc = it->pFileEntry->desc; h.nFileNameLength = (ZipFile::ushort)it->strPath.length(); h.nExtraFieldLength = 0; h.nFileCommentLength = 0; h.nDiskNumberStart = 0; h.nAttrInternal = 0; h.lAttrExternal = 0; h.lLocalHeaderOffset = it->pFileEntry->nFileHeaderOffset; memcpy (pCur, it->strPath.c_str(), it->strPath.length()); pCur += it->strPath.length(); } ZipFile::CDREnd& e = *(ZipFile::CDREnd*)pCur; e.lSignature = e.SIGNATURE; e.nDisk = encryptedFlag ? (1 << 15) : 0; e.nCDRStartDisk = 0; e.numEntriesOnDisk = (ZipFile::ushort)this->size(); e.numEntriesTotal = (ZipFile::ushort)this->size(); e.lCDRSize = (ZipFile::ulong)(pCur - (char*)pBuffer); e.lCDROffset = lCDROffset; e.nCommentLength = 0; pCur = (char*)(&e + 1); return pCur - (char*)pBuffer; } ZipDir::FileEntryList::FileEntryList (FileEntryTree* pTree, unsigned lCDROffset) : m_lCDROffset (lCDROffset) { Add (pTree); } void ZipDir::FileEntryList::Add(FileEntryTree* pTree) { for (FileEntryTree::SubdirMap::iterator itDir = pTree->GetDirBegin(); itDir != pTree->GetDirEnd(); ++itDir) { Add(pTree->GetDirEntry(itDir)); } for (FileEntryTree::FileMap::iterator itFile = pTree->GetFileBegin(); itFile != pTree->GetFileEnd(); ++itFile) { insert(pTree->GetFileEntry(itFile)); } } // updates each file entry's info about the next file entry void ZipDir::FileEntryList::RefreshEOFOffsets() { iterator it, itNext = begin(); if (itNext != end()) { while ((it = itNext, ++itNext) != end()) { // start scan (*it)->nEOFOffset = (*itNext)->nFileHeaderOffset; } // it is the last one.. (*it)->nEOFOffset = m_lCDROffset; } } void ZipDir::FileRecordList::Backup(std::vector& arrFiles) const { arrFiles.resize (size()); std::vector::iterator itTgt = arrFiles.begin(); for (const_iterator it = begin(); it != end(); ++it, ++itTgt) { *itTgt = *it->pFileEntry; } } void ZipDir::FileRecordList::Restore(const std::vector& arrFiles) { if (arrFiles.size() == size()) { std::vector::const_iterator itTgt = arrFiles.begin(); for (iterator it = begin(); it != end(); ++it, ++itTgt) { *it->pFileEntry = *itTgt; } } }