Ejemplo n.º 1
0
// 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;
}