📄 7zin.c
字号:
for (i = 0; i < numFiles; i++)
{
UInt32 len = 0;
UInt32 pos = 0;
CSzFileItem *file = files + i;
while (pos + 2 <= sd->Size)
{
int numAdds;
UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
pos += 2;
len++;
if (value == 0)
break;
if (value < 0x80)
continue;
if (value >= 0xD800 && value < 0xE000)
{
UInt32 c2;
if (value >= 0xDC00)
return SZ_ERROR_ARCHIVE;
if (pos + 2 > sd->Size)
return SZ_ERROR_ARCHIVE;
c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
pos += 2;
if (c2 < 0xDC00 || c2 >= 0xE000)
return SZ_ERROR_ARCHIVE;
value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
}
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
break;
len += numAdds;
}
MY_ALLOC(char, file->Name, (size_t)len, alloc);
len = 0;
while (2 <= sd->Size)
{
int numAdds;
UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
SzSkeepDataSize(sd, 2);
if (value < 0x80)
{
file->Name[len++] = (char)value;
if (value == 0)
break;
continue;
}
if (value >= 0xD800 && value < 0xE000)
{
UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
SzSkeepDataSize(sd, 2);
value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
}
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
break;
file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
do
{
numAdds--;
file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
}
while (numAdds > 0);
len += numAdds;
}
}
return SZ_OK;
}
static SRes SzReadHeader2(
CSzArEx *p, /* allocMain */
CSzData *sd,
CFileSize **unpackSizes, /* allocTemp */
Byte **digestsDefined, /* allocTemp */
UInt32 **digests, /* allocTemp */
Byte **emptyStreamVector, /* allocTemp */
Byte **emptyFileVector, /* allocTemp */
Byte **lwtVector, /* allocTemp */
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt64 type;
UInt32 numUnpackStreams = 0;
UInt32 numFiles = 0;
CSzFileItem *files = 0;
UInt32 numEmptyStreams = 0;
UInt32 i;
RINOK(SzReadID(sd, &type));
if (type == k7zIdArchiveProperties)
{
RINOK(SzReadArchiveProperties(sd));
RINOK(SzReadID(sd, &type));
}
if (type == k7zIdMainStreamsInfo)
{
RINOK(SzReadStreamsInfo(sd,
&p->ArchiveInfo.DataStartPosition,
&p->db,
&numUnpackStreams,
unpackSizes,
digestsDefined,
digests, allocMain, allocTemp));
p->ArchiveInfo.DataStartPosition += p->ArchiveInfo.StartPositionAfterHeader;
RINOK(SzReadID(sd, &type));
}
if (type == k7zIdEnd)
return SZ_OK;
if (type != k7zIdFilesInfo)
return SZ_ERROR_ARCHIVE;
RINOK(SzReadNumber32(sd, &numFiles));
p->db.NumFiles = numFiles;
MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);
p->db.Files = files;
for (i = 0; i < numFiles; i++)
SzFile_Init(files + i);
for (;;)
{
UInt64 type;
UInt64 size;
RINOK(SzReadID(sd, &type));
if (type == k7zIdEnd)
break;
RINOK(SzReadNumber(sd, &size));
if ((UInt64)(int)type != type)
{
RINOK(SzSkeepDataSize(sd, size));
}
else
switch((int)type)
{
case k7zIdName:
{
RINOK(SzReadSwitch(sd));
RINOK(SzReadFileNames(sd, numFiles, files, allocMain))
break;
}
case k7zIdEmptyStream:
{
RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));
numEmptyStreams = 0;
for (i = 0; i < numFiles; i++)
if ((*emptyStreamVector)[i])
numEmptyStreams++;
break;
}
case k7zIdEmptyFile:
{
RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
break;
}
case k7zIdMTime:
{
RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
RINOK(SzReadSwitch(sd));
for (i = 0; i < numFiles; i++)
{
CSzFileItem *f = &files[i];
Byte defined = (*lwtVector)[i];
f->MTimeDefined = defined;
f->MTime.Low = f->MTime.High = 0;
if (defined)
{
RINOK(SzReadUInt32(sd, &f->MTime.Low));
RINOK(SzReadUInt32(sd, &f->MTime.High));
}
}
break;
}
default:
{
RINOK(SzSkeepDataSize(sd, size));
}
}
}
{
UInt32 emptyFileIndex = 0;
UInt32 sizeIndex = 0;
for (i = 0; i < numFiles; i++)
{
CSzFileItem *file = files + i;
file->IsAnti = 0;
if (*emptyStreamVector == 0)
file->HasStream = 1;
else
file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
if (file->HasStream)
{
file->IsDir = 0;
file->Size = (*unpackSizes)[sizeIndex];
file->FileCRC = (*digests)[sizeIndex];
file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex];
sizeIndex++;
}
else
{
if (*emptyFileVector == 0)
file->IsDir = 1;
else
file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
emptyFileIndex++;
file->Size = 0;
file->FileCRCDefined = 0;
}
}
}
return SzArEx_Fill(p, allocMain);
}
static SRes SzReadHeader(
CSzArEx *p,
CSzData *sd,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
CFileSize *unpackSizes = 0;
Byte *digestsDefined = 0;
UInt32 *digests = 0;
Byte *emptyStreamVector = 0;
Byte *emptyFileVector = 0;
Byte *lwtVector = 0;
SRes res = SzReadHeader2(p, sd,
&unpackSizes, &digestsDefined, &digests,
&emptyStreamVector, &emptyFileVector, &lwtVector,
allocMain, allocTemp);
IAlloc_Free(allocTemp, unpackSizes);
IAlloc_Free(allocTemp, digestsDefined);
IAlloc_Free(allocTemp, digests);
IAlloc_Free(allocTemp, emptyStreamVector);
IAlloc_Free(allocTemp, emptyFileVector);
IAlloc_Free(allocTemp, lwtVector);
return res;
}
static SRes SzReadAndDecodePackedStreams2(
ISzInStream *inStream,
CSzData *sd,
CBuf *outBuffer,
CFileSize baseOffset,
CSzAr *p,
CFileSize **unpackSizes,
Byte **digestsDefined,
UInt32 **digests,
ISzAlloc *allocTemp)
{
UInt32 numUnpackStreams = 0;
CFileSize dataStartPos;
CSzFolder *folder;
CFileSize unpackSize;
SRes res;
RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
&numUnpackStreams, unpackSizes, digestsDefined, digests,
allocTemp, allocTemp));
dataStartPos += baseOffset;
if (p->NumFolders != 1)
return SZ_ERROR_ARCHIVE;
folder = p->Folders;
unpackSize = SzFolder_GetUnpackSize(folder);
RINOK(inStream->Seek(inStream, dataStartPos, SZ_SEEK_SET));
if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
return SZ_ERROR_MEM;
res = SzDecode(p->PackSizes, folder,
inStream, dataStartPos,
outBuffer->data, (size_t)unpackSize, allocTemp);
RINOK(res);
if (folder->UnpackCRCDefined)
if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)
return SZ_ERROR_CRC;
return SZ_OK;
}
static SRes SzReadAndDecodePackedStreams(
ISzInStream *inStream,
CSzData *sd,
CBuf *outBuffer,
CFileSize baseOffset,
ISzAlloc *allocTemp)
{
CSzAr p;
CFileSize *unpackSizes = 0;
Byte *digestsDefined = 0;
UInt32 *digests = 0;
SRes res;
SzAr_Init(&p);
res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
&p, &unpackSizes, &digestsDefined, &digests,
allocTemp);
SzAr_Free(&p, allocTemp);
IAlloc_Free(allocTemp, unpackSizes);
IAlloc_Free(allocTemp, digestsDefined);
IAlloc_Free(allocTemp, digests);
return res;
}
static SRes SzArEx_Open2(
CSzArEx *p,
ISzInStream *inStream,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
Byte signature[k7zSignatureSize];
Byte version;
UInt32 crcFromArchive;
UInt64 nextHeaderOffset;
UInt64 nextHeaderSize;
UInt32 nextHeaderCRC;
UInt32 crc = 0;
CFileSize pos = 0;
CBuf buffer;
CSzData sd;
SRes res;
if (SafeReadDirect(inStream, signature, k7zSignatureSize) != SZ_OK)
return SZ_ERROR_NO_ARCHIVE;
if (!TestSignatureCandidate(signature))
return SZ_ERROR_NO_ARCHIVE;
/*
p.Clear();
p.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
*/
RINOK(SafeReadDirectByte(inStream, &version));
if (version != k7zMajorVersion)
return SZ_ERROR_UNSUPPORTED;
RINOK(SafeReadDirectByte(inStream, &version));
RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive, &crc));
crc = CRC_INIT_VAL;
RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset, &crc));
RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize, &crc));
RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC, &crc));
pos = k7zStartHeaderSize;
p->ArchiveInfo.StartPositionAfterHeader = pos;
if (CRC_GET_DIGEST(crc) != crcFromArchive)
return SZ_ERROR_CRC;
if (nextHeaderSize == 0)
return SZ_OK;
RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset), SZ_SEEK_SET));
if (!Buf_Create(&buffer, (size_t)nextHeaderSize, allocTemp))
return SZ_ERROR_MEM;
res = SafeReadDirect(inStream, buffer.data, (size_t)nextHeaderSize);
if (res == SZ_OK)
{
res = SZ_ERROR_ARCHIVE;
if (CrcCalc(buffer.data, (size_t)nextHeaderSize) == nextHeaderCRC)
{
for (;;)
{
UInt64 type;
sd.Data = buffer.data;
sd.Size = buffer.size;
res = SzReadID(&sd, &type);
if (res != SZ_OK)
break;
if (type == k7zIdHeader)
{
res = SzReadHeader(p, &sd, allocMain, allocTemp);
break;
}
if (type != k7zIdEncodedHeader)
{
res = SZ_ERROR_UNSUPPORTED;
break;
}
{
CBuf outBuffer;
Buf_Init(&outBuffer);
res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer,
p->ArchiveInfo.StartPositionAfterHeader,
allocTemp);
if (res != SZ_OK)
{
Buf_Free(&outBuffer, allocTemp);
break;
}
Buf_Free(&buffer, allocTemp);
buffer.data = outBuffer.data;
buffer.size = outBuffer.size;
}
}
}
}
Buf_Free(&buffer, allocTemp);
return res;
}
SRes SzArEx_Open(CSzArEx *p, ISzInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp)
{
SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
if (res != SZ_OK)
SzArEx_Free(p, allocMain);
return res;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -