// add new header using the argument as a template CZipFileHeader* CZipCentralDir::AddNewFile(const CZipFileHeader & header, ZIP_INDEX_TYPE uReplaceIndex, int iLevel, bool bRichHeaderTemplateCopy) { // copy some of the template data m_pOpenedFile = NULL; ZIP_INDEX_TYPE uIndex; CZipFileHeader* pHeader = new CZipFileHeader(this); try { pHeader->m_uMethod = header.m_uMethod; pHeader->m_uModDate = header.m_uModDate; pHeader->m_uModTime = header.m_uModTime; pHeader->m_tModificationTime = header.m_tModificationTime; pHeader->m_tCreationTime = header.m_tCreationTime; pHeader->m_tLastAccessTime = header.m_tLastAccessTime; pHeader->m_uExternalAttr = header.m_uExternalAttr; pHeader->m_uLocalComprSize = header.m_uLocalComprSize; pHeader->m_uLocalUncomprSize = header.m_uLocalUncomprSize; pHeader->m_uLocalHeaderSize = header.m_uLocalHeaderSize; pHeader->m_fileName = header.m_fileName; pHeader->m_comment = header.m_comment; pHeader->m_aLocalExtraData = header.m_aLocalExtraData; // local will be removed in a moment in PrepareData pHeader->m_aCentralExtraData = header.m_aCentralExtraData; pHeader->m_aCentralExtraData.RemoveInternalHeaders(); pHeader->m_iSystemCompatibility = header.m_iSystemCompatibility; pHeader->m_uEncryptionMethod = header.m_uEncryptionMethod; pHeader->UpdateStringsFlags(false); #ifdef _ZIP_UNICODE_CUSTOM // current settings pHeader->m_stringSettings = GetStringStoreSettings(); #endif // set only when adding a new file, not in PrepareData (which may be called under different circumstances) // we need the proper encryption method to be set already RemoveFromDisk(); bool bReplace = IsValidIndex(uReplaceIndex); pHeader->PrepareData(iLevel, m_pStorage->IsSegmented()); if (bRichHeaderTemplateCopy) { // call here, because PrepareData will zero them pHeader->m_uCrc32 = header.m_uCrc32; pHeader->m_uComprSize = header.m_uComprSize; pHeader->m_uUncomprSize = header.m_uUncomprSize; } // now that everything is all right, we can add the new file if (bReplace) { // PrepareStringBuffers was called in CZipArchive::OpenNewFile // the local extra field is updated if needed, so we can check the lengths if (!pHeader->CheckLengths(true)) ThrowError(CZipException::tooLongData); CZipFileHeader* pfh = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uReplaceIndex]; m_pStorage->Seek(pfh->m_uOffset); RemoveFile(pfh, uReplaceIndex, false); m_pHeaders->InsertAt((ZIP_ARRAY_SIZE_TYPE)uReplaceIndex, pHeader); m_pOpenedFile = pHeader; uIndex = uReplaceIndex; } else { uIndex = (ZIP_INDEX_TYPE)m_pHeaders->Add(pHeader); m_pOpenedFile = pHeader; m_pStorage->m_pFile->SeekToEnd(); } } catch(...) { // otherwise it is added to the collection and will be auto-deleted if (pHeader != NULL && m_pOpenedFile == NULL) delete pHeader; throw; } if (m_pInfo->m_bFindFastEnabled) InsertFindFastElement(pHeader, uIndex); // GetCount > 0, because we have just added a header m_pInfo->m_iLastIndexAdded = uIndex; return pHeader; }