mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-12 12:11:34 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
@@ -16,19 +16,36 @@ void COutArchive::Create(IOutStream *outStream)
|
||||
m_BasePosition = 0;
|
||||
}
|
||||
|
||||
void COutArchive::MoveBasePosition(UINT32 distanceToMove)
|
||||
void COutArchive::MoveBasePosition(UInt64 distanceToMove)
|
||||
{
|
||||
m_BasePosition += distanceToMove; // test overflow
|
||||
}
|
||||
|
||||
void COutArchive::PrepareWriteCompressedData(UINT16 fileNameLength)
|
||||
void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64)
|
||||
{
|
||||
m_LocalFileHeaderSize = sizeof(NFileHeader::CLocalBlockFull) + fileNameLength;
|
||||
m_IsZip64 = isZip64;
|
||||
m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;
|
||||
m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize;
|
||||
}
|
||||
|
||||
void COutArchive::WriteBytes(const void *buffer, UINT32 size)
|
||||
void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize)
|
||||
{
|
||||
UINT32 processedSize;
|
||||
// We test it to 0xF8000000 to support case when compressed size
|
||||
// can be larger than uncompressed size.
|
||||
PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000);
|
||||
}
|
||||
|
||||
void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize)
|
||||
{
|
||||
bool isUnPack64 = unPackSize >= 0xFFFFFFFF;
|
||||
bool isPack64 = packSize >= 0xFFFFFFFF;
|
||||
bool isZip64 = isPack64 || isUnPack64;
|
||||
PrepareWriteCompressedDataZip64(fileNameLength, isZip64);
|
||||
}
|
||||
|
||||
void COutArchive::WriteBytes(const void *buffer, UInt32 size)
|
||||
{
|
||||
UInt32 processedSize;
|
||||
if(m_Stream->Write(buffer, size, &processedSize) != S_OK)
|
||||
throw 0;
|
||||
if(processedSize != size)
|
||||
@@ -36,80 +53,177 @@ void COutArchive::WriteBytes(const void *buffer, UINT32 size)
|
||||
m_BasePosition += size;
|
||||
}
|
||||
|
||||
void COutArchive::WriteLocalHeader(const CItem &item)
|
||||
void COutArchive::WriteByte(Byte b)
|
||||
{
|
||||
NFileHeader::CLocalBlockFull fileHeader;
|
||||
fileHeader.Signature = NSignature::kLocalFileHeader;
|
||||
NFileHeader::CLocalBlock &header = fileHeader.Header;
|
||||
WriteBytes(&b, 1);
|
||||
}
|
||||
|
||||
header.ExtractVersion.HostOS = item.ExtractVersion.HostOS;
|
||||
header.ExtractVersion.Version = item.ExtractVersion.Version;
|
||||
header.Flags = item.Flags;
|
||||
header.CompressionMethod = item.CompressionMethod;
|
||||
header.Time = item.Time;
|
||||
header.FileCRC = item.FileCRC;
|
||||
header.PackSize = item.PackSize;
|
||||
header.UnPackSize = item.UnPackSize;
|
||||
void COutArchive::WriteUInt16(UInt16 value)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
WriteByte((Byte)value);
|
||||
value >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
header.NameSize = item.Name.Length();
|
||||
header.ExtraSize = item.LocalExtraSize; // test it;
|
||||
void COutArchive::WriteUInt32(UInt32 value)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
WriteByte((Byte)value);
|
||||
value >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void COutArchive::WriteUInt64(UInt64 value)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
WriteByte((Byte)value);
|
||||
value >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT COutArchive::WriteLocalHeader(const CItem &item)
|
||||
{
|
||||
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
|
||||
WriteBytes(&fileHeader, sizeof(fileHeader));
|
||||
WriteBytes((const char *)item.Name, header.NameSize);
|
||||
MoveBasePosition(header.ExtraSize + header.PackSize);
|
||||
|
||||
bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF;
|
||||
|
||||
WriteUInt32(NSignature::kLocalFileHeader);
|
||||
WriteByte(item.ExtractVersion.Version);
|
||||
WriteByte(item.ExtractVersion.HostOS);
|
||||
WriteUInt16(item.Flags);
|
||||
WriteUInt16(item.CompressionMethod);
|
||||
WriteUInt32(item.Time);
|
||||
WriteUInt32(item.FileCRC);
|
||||
WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
|
||||
WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
|
||||
WriteUInt16(item.Name.Length());
|
||||
UInt16 localExtraSize = isZip64 ? (4 + 16): 0;
|
||||
if (localExtraSize > m_ExtraSize)
|
||||
return E_FAIL;
|
||||
WriteUInt16(m_ExtraSize); // test it;
|
||||
WriteBytes((const char *)item.Name, item.Name.Length());
|
||||
if (m_ExtraSize > 0)
|
||||
{
|
||||
UInt16 remain = m_ExtraSize - 4;
|
||||
WriteUInt16(0x1); // Zip64 Tag;
|
||||
WriteUInt16(remain);
|
||||
if (isZip64)
|
||||
{
|
||||
WriteUInt64(item.UnPackSize);
|
||||
WriteUInt64(item.PackSize);
|
||||
remain -= 16;
|
||||
}
|
||||
for (int i = 0; i < remain; i++)
|
||||
WriteByte(0);
|
||||
}
|
||||
MoveBasePosition(item.PackSize);
|
||||
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutArchive::WriteCentralHeader(const CItem &item)
|
||||
{
|
||||
NFileHeader::CBlockFull fileHeader;
|
||||
fileHeader.Signature = NSignature::kCentralFileHeader;
|
||||
NFileHeader::CBlock &header = fileHeader.Header;
|
||||
|
||||
header.MadeByVersion.HostOS = item.MadeByVersion.HostOS;
|
||||
header.MadeByVersion.Version = item.MadeByVersion.Version;
|
||||
header.ExtractVersion.HostOS = item.ExtractVersion.HostOS;
|
||||
header.ExtractVersion.Version = item.ExtractVersion.Version;
|
||||
header.Flags = item.Flags;
|
||||
header.CompressionMethod = item.CompressionMethod;
|
||||
header.Time = item.Time;
|
||||
header.FileCRC = item.FileCRC;
|
||||
header.PackSize = item.PackSize;
|
||||
header.UnPackSize = item.UnPackSize;
|
||||
|
||||
header.NameSize = item.Name.Length();
|
||||
|
||||
header.ExtraSize = item.CentralExtraSize; // test it;
|
||||
header.CommentSize = item.CommentSize;
|
||||
header.DiskNumberStart = 0;
|
||||
header.InternalAttributes = item.InternalAttributes;
|
||||
header.ExternalAttributes = item.ExternalAttributes;
|
||||
header.LocalHeaderOffset = item.LocalHeaderPosition;
|
||||
|
||||
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
|
||||
WriteBytes(&fileHeader, sizeof(fileHeader));
|
||||
WriteBytes((const char *)item.Name, header.NameSize);
|
||||
|
||||
bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF;
|
||||
bool isPack64 = item.PackSize >= 0xFFFFFFFF;
|
||||
bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF;
|
||||
bool isZip64 = isPack64 || isUnPack64 || isPosition64;
|
||||
|
||||
WriteUInt32(NSignature::kCentralFileHeader);
|
||||
WriteByte(item.MadeByVersion.Version);
|
||||
WriteByte(item.MadeByVersion.HostOS);
|
||||
WriteByte(item.ExtractVersion.Version);
|
||||
WriteByte(item.ExtractVersion.HostOS);
|
||||
WriteUInt16(item.Flags);
|
||||
WriteUInt16(item.CompressionMethod);
|
||||
WriteUInt32(item.Time);
|
||||
WriteUInt32(item.FileCRC);
|
||||
WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
|
||||
WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
|
||||
WriteUInt16(item.Name.Length());
|
||||
UInt16 zip64ExtraSize = (isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0);
|
||||
UInt16 centralExtraSize = isZip64 ? (4 + zip64ExtraSize) : 0;
|
||||
centralExtraSize += (UInt16)item.CentralExtra.GetSize();
|
||||
WriteUInt16(centralExtraSize); // test it;
|
||||
WriteUInt16(item.Comment.GetCapacity());
|
||||
WriteUInt16(0); // DiskNumberStart;
|
||||
WriteUInt16(item.InternalAttributes);
|
||||
WriteUInt32(item.ExternalAttributes);
|
||||
WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition);
|
||||
WriteBytes((const char *)item.Name, item.Name.Length());
|
||||
if (isZip64)
|
||||
{
|
||||
WriteUInt16(0x1); // Zip64 Tag;
|
||||
WriteUInt16(zip64ExtraSize);
|
||||
if(isUnPack64)
|
||||
WriteUInt64(item.UnPackSize);
|
||||
if(isPack64)
|
||||
WriteUInt64(item.PackSize);
|
||||
if(isPosition64)
|
||||
WriteUInt64(item.LocalHeaderPosition);
|
||||
}
|
||||
if (item.CentralExtra.SubBlocks.Size() != 0)
|
||||
{
|
||||
for (int i = 0; i < item.CentralExtra.SubBlocks.Size(); i++)
|
||||
{
|
||||
CExtraSubBlock subBlock = item.CentralExtra.SubBlocks[i];
|
||||
WriteUInt16(subBlock.ID);
|
||||
WriteUInt16((UInt16)subBlock.Data.GetCapacity());
|
||||
WriteBytes(subBlock.Data, subBlock.Data.GetCapacity());
|
||||
}
|
||||
}
|
||||
if (item.Comment.GetCapacity() > 0)
|
||||
WriteBytes(item.Comment, item.Comment.GetCapacity());
|
||||
}
|
||||
|
||||
void COutArchive::WriteEndOfCentralDir(const COutArchiveInfo &archiveInfo)
|
||||
void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer &comment)
|
||||
{
|
||||
CEndOfCentralDirectoryRecordFull fileHeader;
|
||||
fileHeader.Signature = NSignature::kEndOfCentralDir;
|
||||
CEndOfCentralDirectoryRecord &header = fileHeader.Header;
|
||||
|
||||
header.ThisDiskNumber = 0;
|
||||
header.StartCentralDirectoryDiskNumber = 0;
|
||||
|
||||
header.NumEntriesInCentaralDirectoryOnThisDisk = archiveInfo.NumEntriesInCentaralDirectory;
|
||||
header.NumEntriesInCentaralDirectory = archiveInfo.NumEntriesInCentaralDirectory;
|
||||
|
||||
header.CentralDirectorySize = archiveInfo.CentralDirectorySize;
|
||||
header.CentralDirectoryStartOffset = archiveInfo.CentralDirectoryStartOffset;
|
||||
header.CommentSize = archiveInfo.CommentSize;
|
||||
|
||||
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
|
||||
WriteBytes(&fileHeader, sizeof(fileHeader));
|
||||
|
||||
UInt64 cdOffset = GetCurrentPosition();
|
||||
for(int i = 0; i < items.Size(); i++)
|
||||
WriteCentralHeader(items[i]);
|
||||
UInt64 cd64EndOffset = GetCurrentPosition();
|
||||
UInt64 cdSize = cd64EndOffset - cdOffset;
|
||||
bool cdOffset64 = cdOffset >= 0xFFFFFFFF;
|
||||
bool cdSize64 = cdSize >= 0xFFFFFFFF;
|
||||
bool items64 = items.Size() >= 0xFFFF;
|
||||
bool isZip64 = (cdOffset64 || cdSize64 || items64);
|
||||
|
||||
if (isZip64)
|
||||
{
|
||||
WriteUInt32(NSignature::kZip64EndOfCentralDir);
|
||||
WriteUInt64(kZip64EndOfCentralDirRecordSize); // ThisDiskNumber = 0;
|
||||
WriteUInt16(45); // version
|
||||
WriteUInt16(45); // version
|
||||
WriteUInt32(0); // ThisDiskNumber = 0;
|
||||
WriteUInt32(0); // StartCentralDirectoryDiskNumber;;
|
||||
WriteUInt64((UInt64)items.Size());
|
||||
WriteUInt64((UInt64)items.Size());
|
||||
WriteUInt64((UInt64)cdSize);
|
||||
WriteUInt64((UInt64)cdOffset);
|
||||
|
||||
WriteUInt32(NSignature::kZip64EndOfCentralDirLocator);
|
||||
WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory
|
||||
WriteUInt64(cd64EndOffset);
|
||||
WriteUInt32(1); // total number of disks
|
||||
}
|
||||
WriteUInt32(NSignature::kEndOfCentralDir);
|
||||
WriteUInt16(0); // ThisDiskNumber = 0;
|
||||
WriteUInt16(0); // StartCentralDirectoryDiskNumber;
|
||||
WriteUInt16(items64 ? 0xFFFF: (UInt16)items.Size());
|
||||
WriteUInt16(items64 ? 0xFFFF: (UInt16)items.Size());
|
||||
WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize);
|
||||
WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset);
|
||||
UInt16 commentSize = comment.GetCapacity();
|
||||
WriteUInt16(commentSize);
|
||||
if (commentSize > 0)
|
||||
WriteBytes((const Byte *)comment, commentSize);
|
||||
}
|
||||
|
||||
void COutArchive::CreateStreamForCompressing(IOutStream **outStream)
|
||||
|
||||
Reference in New Issue
Block a user