📄 7zin.c
字号:
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,
UInt64 **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->dataPos,
&p->db,
&numUnpackStreams,
unpackSizes,
digestsDefined,
digests, allocMain, allocTemp));
p->dataPos += p->startPosAfterHeader;
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)
{
UInt64 *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(
ILookInStream *inStream,
CSzData *sd,
CBuf *outBuffer,
UInt64 baseOffset,
CSzAr *p,
UInt64 **unpackSizes,
Byte **digestsDefined,
UInt32 **digests,
ISzAlloc *allocTemp)
{
UInt32 numUnpackStreams = 0;
UInt64 dataStartPos;
CSzFolder *folder;
UInt64 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(LookInStream_SeekTo(inStream, dataStartPos));
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(
ILookInStream *inStream,
CSzData *sd,
CBuf *outBuffer,
UInt64 baseOffset,
ISzAlloc *allocTemp)
{
CSzAr p;
UInt64 *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,
ILookInStream *inStream,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
Byte header[k7zStartHeaderSize];
UInt64 nextHeaderOffset, nextHeaderSize;
size_t nextHeaderSizeT;
UInt32 nextHeaderCRC;
CBuf buffer;
SRes res;
RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
if (!TestSignatureCandidate(header))
return SZ_ERROR_NO_ARCHIVE;
if (header[6] != k7zMajorVersion)
return SZ_ERROR_UNSUPPORTED;
nextHeaderOffset = GetUi64(header + 12);
nextHeaderSize = GetUi64(header + 20);
nextHeaderCRC = GetUi32(header + 28);
p->startPosAfterHeader = k7zStartHeaderSize;
if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
return SZ_ERROR_CRC;
nextHeaderSizeT = (size_t)nextHeaderSize;
if (nextHeaderSizeT != nextHeaderSize)
return SZ_ERROR_MEM;
if (nextHeaderSizeT == 0)
return SZ_OK;
if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
return SZ_ERROR_NO_ARCHIVE;
{
Int64 pos = 0;
RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
if ((UInt64)pos < nextHeaderOffset ||
(UInt64)pos < k7zStartHeaderSize + nextHeaderOffset ||
(UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
return SZ_ERROR_INPUT_EOF;
}
RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset));
if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
return SZ_ERROR_MEM;
res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);
if (res == SZ_OK)
{
res = SZ_ERROR_ARCHIVE;
if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)
{
CSzData sd;
UInt64 type;
sd.Data = buffer.data;
sd.Size = buffer.size;
res = SzReadID(&sd, &type);
if (res == SZ_OK)
{
if (type == k7zIdEncodedHeader)
{
CBuf outBuffer;
Buf_Init(&outBuffer);
res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);
if (res != SZ_OK)
Buf_Free(&outBuffer, allocTemp);
else
{
Buf_Free(&buffer, allocTemp);
buffer.data = outBuffer.data;
buffer.size = outBuffer.size;
sd.Data = buffer.data;
sd.Size = buffer.size;
res = SzReadID(&sd, &type);
}
}
}
if (res == SZ_OK)
{
if (type == k7zIdHeader)
res = SzReadHeader(p, &sd, allocMain, allocTemp);
else
res = SZ_ERROR_UNSUPPORTED;
}
}
}
Buf_Free(&buffer, allocTemp);
return res;
}
SRes SzArEx_Open(CSzArEx *p, ILookInStream *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 + -