Compress-Deflate7
view release on metacpan or search on metacpan
7zip/CPP/7zip/Archive/Rar/RarIn.cpp view on Meta::CPAN
bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
{
size_t processed = size;
if (ReadBytesSpec(data, &processed) != S_OK)
return false;
return processed == size;
}
HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{
m_CryptoMode = false;
RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));
m_Position = m_StreamStartPosition;
UInt64 arcStartPos;
RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
searchHeaderSizeLimit, arcStartPos));
m_Position = arcStartPos + NHeader::kMarkerSize;
RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];
RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize));
AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);
UInt32 blockSize = Get16(buf + 5);
_header.EncryptVersion = 0;
_header.Flags = Get16(buf + 3);
UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;
if (_header.IsThereEncryptVer())
{
if (blockSize <= headerSize)
return S_FALSE;
RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));
AddToSeekValue(1);
_header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];
headerSize += 1;
}
if (blockSize < headerSize ||
buf[2] != NHeader::NBlockType::kArchiveHeader ||
(UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))
return S_FALSE;
size_t commentSize = blockSize - headerSize;
_comment.SetCapacity(commentSize);
RINOK(ReadStream_FALSE(stream, _comment, commentSize));
AddToSeekValue(commentSize);
m_Stream = stream;
_header.StartPosition = arcStartPos;
return S_OK;
}
void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
{
archiveInfo = _header;
}
static void DecodeUnicodeFileName(const char *name, const Byte *encName,
int encSize, wchar_t *unicodeName, int maxDecSize)
{
int encPos = 0;
int decPos = 0;
int flagBits = 0;
Byte flags = 0;
Byte highByte = encName[encPos++];
while (encPos < encSize && decPos < maxDecSize)
{
if (flagBits == 0)
{
flags = encName[encPos++];
flagBits = 8;
}
switch(flags >> 6)
{
case 0:
unicodeName[decPos++] = encName[encPos++];
break;
case 1:
unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));
break;
case 2:
unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));
encPos += 2;
break;
case 3:
{
int length = encName[encPos++];
if (length & 0x80)
{
Byte correction = encName[encPos++];
for (length = (length & 0x7f) + 2;
length > 0 && decPos < maxDecSize; length--, decPos++)
unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
}
else
for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)
unicodeName[decPos] = name[decPos];
}
break;
}
flags <<= 2;
flagBits -= 2;
}
unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;
}
void CInArchive::ReadName(CItemEx &item, int nameSize)
{
item.UnicodeName.Empty();
if (nameSize > 0)
{
m_NameBuffer.EnsureCapacity(nameSize + 1);
char *buffer = (char *)m_NameBuffer;
for (int i = 0; i < nameSize; i++)
buffer[i] = ReadByte();
int mainLen;
for (mainLen = 0; mainLen < nameSize; mainLen++)
if (buffer[mainLen] == '\0')
break;
buffer[mainLen] = '\0';
item.Name = buffer;
if(item.HasUnicodeName())
{
if(mainLen < nameSize)
{
int unicodeNameSizeMax = MyMin(nameSize, (0x400));
_unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1);
DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1,
nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax);
item.UnicodeName = _unicodeNameBuffer;
}
else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
item.UnicodeName.Empty();
}
}
else
item.Name.Empty();
}
Byte CInArchive::ReadByte()
{
if (m_CurPos >= m_PosLimit)
throw CInArchiveException(CInArchiveException::kIncorrectArchive);
return m_CurData[m_CurPos++];
}
UInt16 CInArchive::ReadUInt16()
{
UInt16 value = 0;
for (int i = 0; i < 2; i++)
{
Byte b = ReadByte();
value |= (UInt16(b) << (8 * i));
}
return value;
}
UInt32 CInArchive::ReadUInt32()
{
UInt32 value = 0;
for (int i = 0; i < 4; i++)
{
Byte b = ReadByte();
value |= (UInt32(b) << (8 * i));
}
return value;
}
void CInArchive::ReadTime(Byte mask, CRarTime &rarTime)
{
rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);
int numDigits = (mask & 3);
rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;
for (int i = 0; i < numDigits; i++)
rarTime.SubTime[3 - numDigits + i] = ReadByte();
}
void CInArchive::ReadHeaderReal(CItemEx &item)
{
item.Flags = m_BlockHeader.Flags;
item.PackSize = ReadUInt32();
item.Size = ReadUInt32();
item.HostOS = ReadByte();
item.FileCRC = ReadUInt32();
item.MTime.DosTime = ReadUInt32();
item.UnPackVersion = ReadByte();
item.Method = ReadByte();
int nameSize = ReadUInt16();
item.Attrib = ReadUInt32();
7zip/CPP/7zip/Archive/Rar/RarIn.cpp view on Meta::CPAN
if (item.CTimeDefined)
{
item.CTime.DosTime = ReadUInt32();
ReadTime(createMask, item.CTime);
}
item.ATimeDefined = ((accessMask & 8) != 0);
if (item.ATimeDefined)
{
item.ATime.DosTime = ReadUInt32();
ReadTime(accessMask, item.ATime);
}
}
UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos;
item.Position = m_Position;
item.MainPartSize = fileHeaderWithNameSize;
item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);
if (m_CryptoMode)
item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);
else
item.AlignSize = 0;
AddToSeekValue(m_BlockHeader.HeadSize);
}
void CInArchive::AddToSeekValue(UInt64 addValue)
{
m_Position += addValue;
}
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)
{
decryptionError = false;
for (;;)
{
SeekInArchive(m_Position);
if (!m_CryptoMode && (_header.Flags &
NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
{
m_CryptoMode = false;
if (getTextPassword == 0)
return S_FALSE;
if (!m_RarAES)
{
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
m_RarAES = m_RarAESSpec;
}
m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld());
// Salt
const UInt32 kSaltSize = 8;
Byte salt[kSaltSize];
if(!ReadBytesAndTestSize(salt, kSaltSize))
return S_FALSE;
m_Position += kSaltSize;
RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
// Password
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password))
UString unicodePassword(password);
CByteBuffer buffer;
const UInt32 sizeInBytes = unicodePassword.Length() * 2;
buffer.SetCapacity(sizeInBytes);
for (int i = 0; i < unicodePassword.Length(); i++)
{
wchar_t c = unicodePassword[i];
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
const UInt32 kDecryptedBufferSize = (1 << 12);
if (m_DecryptedData.GetCapacity() == 0)
{
const UInt32 kAlign = 16;
m_DecryptedData.SetCapacity(kDecryptedBufferSize + kAlign);
m_DecryptedDataAligned = (Byte *)((ptrdiff_t)((Byte *)m_DecryptedData + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1));
}
RINOK(m_RarAES->Init());
size_t decryptedDataSizeT = kDecryptedBufferSize;
RINOK(ReadStream(m_Stream, m_DecryptedDataAligned, &decryptedDataSizeT));
m_DecryptedDataSize = (UInt32)decryptedDataSizeT;
m_DecryptedDataSize = m_RarAES->Filter(m_DecryptedDataAligned, m_DecryptedDataSize);
m_CryptoMode = true;
m_CryptoPos = 0;
}
m_FileHeaderData.EnsureCapacity(7);
size_t processed = 7;
RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed));
if (processed != 7)
{
if (processed != 0)
errorMessage = k_UnexpectedEnd;
return S_FALSE;
}
m_CurData = (Byte *)m_FileHeaderData;
m_CurPos = 0;
m_PosLimit = 7;
m_BlockHeader.CRC = ReadUInt16();
m_BlockHeader.Type = ReadByte();
m_BlockHeader.Flags = ReadUInt16();
m_BlockHeader.HeadSize = ReadUInt16();
if (m_BlockHeader.HeadSize < 7)
ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);
if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)
return S_FALSE;
if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader)
{
m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
m_CurData = (Byte *)m_FileHeaderData;
m_PosLimit = m_BlockHeader.HeadSize;
if (!ReadBytesAndTestSize(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7))
{
errorMessage = k_UnexpectedEnd;
return S_FALSE;
}
ReadHeaderReal(item);
if ((CrcCalc(m_CurData + 2,
( run in 0.489 second using v1.01-cache-2.11-cpan-39bf76dae61 )