9.06 beta

This commit is contained in:
Igor Pavlov
2009-08-17 00:00:00 +00:00
committed by Kornel Lesiński
parent 829409452d
commit c99f3ebdd6
445 changed files with 15246 additions and 8133 deletions

201
C/7z.h Executable file
View File

@@ -0,0 +1,201 @@
/* 7z.h -- 7z interface
2009-08-17 : Igor Pavlov : Public domain */
#ifndef __7Z_H
#define __7Z_H
#include "7zBuf.h"
EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnpackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnpackSize,
k7zIdNumUnpackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCTime,
k7zIdATime,
k7zIdMTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos,
k7zIdDummy
};
typedef struct
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
UInt64 MethodID;
CBuf Props;
} CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CSzBindPair;
typedef struct
{
CSzCoderInfo *Coders;
CSzBindPair *BindPairs;
UInt32 *PackStreams;
UInt64 *UnpackSizes;
UInt32 NumCoders;
UInt32 NumBindPairs;
UInt32 NumPackStreams;
int UnpackCRCDefined;
UInt32 UnpackCRC;
UInt32 NumUnpackStreams;
} CSzFolder;
void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
CNtfsFileTime MTime;
UInt64 Size;
UInt32 Crc;
Byte HasStream;
Byte IsDir;
Byte IsAnti;
Byte CrcDefined;
Byte MTimeDefined;
} CSzFileItem;
void SzFile_Init(CSzFileItem *p);
typedef struct
{
UInt64 *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
CSzFolder *Folders;
CSzFileItem *Files;
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt32 NumFiles;
} CSzAr;
void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */
CBuf FileNames; /* UTF-16-LE */
} CSzArEx;
void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/*
if dest == NULL, the return value specifies the required size of the buffer,
in 16-bit characters, including the null-terminating character.
if dest != NULL, the return value specifies the number of 16-bit characters that
are written to the dest, including the null-terminating character. */
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
SRes SzArEx_Extract(
const CSzArEx *db,
ILookInStream *inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
/*
SzArEx_Open Errors:
SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM
SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
EXTERN_C_END
#endif

View File

@@ -1,14 +1,14 @@
/* 7zDecode.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2009-05-03 : Igor Pavlov : Public domain */ 2009-08-16 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
#include "../../Bcj2.h" #include "7z.h"
#include "../../Bra.h"
#include "../../LzmaDec.h"
#include "../../Lzma2Dec.h"
#include "7zDecode.h" #include "Bcj2.h"
#include "Bra.h"
#include "LzmaDec.h"
#include "Lzma2Dec.h"
#define k_Copy 0 #define k_Copy 0
#define k_LZMA2 0x21 #define k_LZMA2 0x21
@@ -137,7 +137,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
SRes CheckSupportedFolder(const CSzFolder *f) static SRes CheckSupportedFolder(const CSzFolder *f)
{ {
if (f->NumCoders < 1 || f->NumCoders > 4) if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
@@ -179,7 +179,7 @@ SRes CheckSupportedFolder(const CSzFolder *f)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
UInt64 GetSum(const UInt64 *values, UInt32 index) static UInt64 GetSum(const UInt64 *values, UInt32 index)
{ {
UInt64 sum = 0; UInt64 sum = 0;
UInt32 i; UInt32 i;
@@ -188,7 +188,7 @@ UInt64 GetSum(const UInt64 *values, UInt32 index)
return sum; return sum;
} }
SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
Byte *tempBuf[]) Byte *tempBuf[])
@@ -296,13 +296,13 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
return SZ_OK; return SZ_OK;
} }
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
{ {
Byte *tempBuf[3] = { 0, 0, 0}; Byte *tempBuf[3] = { 0, 0, 0};
int i; int i;
SRes res = SzDecode2(packSizes, folder, inStream, startPos, SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf); outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]); IAlloc_Free(allocMain, tempBuf[i]);

View File

@@ -1,5 +1,5 @@
/* 7zFile.c -- File IO /* 7zFile.c -- File IO
2008-11-22 : Igor Pavlov : Public domain */ 2009-08-16 : Igor Pavlov : Public domain */
#include "7zFile.h" #include "7zFile.h"
@@ -52,6 +52,20 @@ static WRes File_Open(CSzFile *p, const char *name, int writeMode)
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
#ifdef USE_WINDOWS_FILE
static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
{
p->handle = CreateFileW(name,
writeMode ? GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ, NULL,
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
}
WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
#endif
WRes File_Close(CSzFile *p) WRes File_Close(CSzFile *p)
{ {
#ifdef USE_WINDOWS_FILE #ifdef USE_WINDOWS_FILE

View File

@@ -1,5 +1,5 @@
/* 7zFile.h -- File IO /* 7zFile.h -- File IO
2009-02-07 : Igor Pavlov : Public domain */ 2009-08-16 : Igor Pavlov : Public domain */
#ifndef __7Z_FILE_H #ifndef __7Z_FILE_H
#define __7Z_FILE_H #define __7Z_FILE_H
@@ -16,10 +16,7 @@
#include "Types.h" #include "Types.h"
#ifdef __cplusplus EXTERN_C_BEGIN
extern "C" {
#endif
/* ---------- File ---------- */ /* ---------- File ---------- */
@@ -35,6 +32,10 @@ typedef struct
void File_Construct(CSzFile *p); void File_Construct(CSzFile *p);
WRes InFile_Open(CSzFile *p, const char *name); WRes InFile_Open(CSzFile *p, const char *name);
WRes OutFile_Open(CSzFile *p, const char *name); WRes OutFile_Open(CSzFile *p, const char *name);
#ifdef USE_WINDOWS_FILE
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
#endif
WRes File_Close(CSzFile *p); WRes File_Close(CSzFile *p);
/* reads max(*size, remain file's size) bytes */ /* reads max(*size, remain file's size) bytes */
@@ -75,8 +76,6 @@ typedef struct
void FileOutStream_CreateVTable(CFileOutStream *p); void FileOutStream_CreateVTable(CFileOutStream *p);
#ifdef __cplusplus EXTERN_C_END
}
#endif
#endif #endif

View File

@@ -1,17 +1,134 @@
/* 7zIn.c -- 7z Input functions /* 7zIn.c -- 7z Input functions
2008-12-31 : Igor Pavlov : Public domain */ 2009-08-17 : Igor Pavlov : Public domain */
#include "../../7zCrc.h" #include <string.h>
#include "../../CpuArch.h"
#include "7zDecode.h" #include "7z.h"
#include "7zIn.h" #include "7zCrc.h"
#include "CpuArch.h"
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }
#define NUM_FOLDER_CODERS_MAX 32 #define NUM_FOLDER_CODERS_MAX 32
#define NUM_CODER_STREAMS_MAX 32 #define NUM_CODER_STREAMS_MAX 32
void SzCoderInfo_Init(CSzCoderInfo *p)
{
Buf_Init(&p->Props);
}
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
{
Buf_Free(&p->Props, alloc);
SzCoderInfo_Init(p);
}
void SzFolder_Init(CSzFolder *p)
{
p->Coders = 0;
p->BindPairs = 0;
p->PackStreams = 0;
p->UnpackSizes = 0;
p->NumCoders = 0;
p->NumBindPairs = 0;
p->NumPackStreams = 0;
p->UnpackCRCDefined = 0;
p->UnpackCRC = 0;
p->NumUnpackStreams = 0;
}
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Coders)
for (i = 0; i < p->NumCoders; i++)
SzCoderInfo_Free(&p->Coders[i], alloc);
IAlloc_Free(alloc, p->Coders);
IAlloc_Free(alloc, p->BindPairs);
IAlloc_Free(alloc, p->PackStreams);
IAlloc_Free(alloc, p->UnpackSizes);
SzFolder_Init(p);
}
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
{
UInt32 result = 0;
UInt32 i;
for (i = 0; i < p->NumCoders; i++)
result += p->Coders[i].NumOutStreams;
return result;
}
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
{
int i = (int)SzFolder_GetNumOutStreams(p);
if (i == 0)
return 0;
for (i--; i >= 0; i--)
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
return p->UnpackSizes[i];
/* throw 1; */
return 0;
}
void SzFile_Init(CSzFileItem *p)
{
p->HasStream = 1;
p->IsDir = 0;
p->IsAnti = 0;
p->CrcDefined = 0;
p->MTimeDefined = 0;
}
void SzAr_Init(CSzAr *p)
{
p->PackSizes = 0;
p->PackCRCsDefined = 0;
p->PackCRCs = 0;
p->Folders = 0;
p->Files = 0;
p->NumPackStreams = 0;
p->NumFolders = 0;
p->NumFiles = 0;
}
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Folders)
for (i = 0; i < p->NumFolders; i++)
SzFolder_Free(&p->Folders[i], alloc);
IAlloc_Free(alloc, p->PackSizes);
IAlloc_Free(alloc, p->PackCRCsDefined);
IAlloc_Free(alloc, p->PackCRCs);
IAlloc_Free(alloc, p->Folders);
IAlloc_Free(alloc, p->Files);
SzAr_Init(p);
}
void SzArEx_Init(CSzArEx *p) void SzArEx_Init(CSzArEx *p)
{ {
SzAr_Init(&p->db); SzAr_Init(&p->db);
@@ -19,6 +136,8 @@ void SzArEx_Init(CSzArEx *p)
p->PackStreamStartPositions = 0; p->PackStreamStartPositions = 0;
p->FolderStartFileIndex = 0; p->FolderStartFileIndex = 0;
p->FileIndexToFolderIndexMap = 0; p->FileIndexToFolderIndexMap = 0;
p->FileNameOffsets = 0;
Buf_Init(&p->FileNames);
} }
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
@@ -27,6 +146,10 @@ void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->PackStreamStartPositions);
IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FolderStartFileIndex);
IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);
IAlloc_Free(alloc, p->FileNameOffsets);
Buf_Free(&p->FileNames, alloc);
SzAr_Free(&p->db, alloc); SzAr_Free(&p->db, alloc);
SzArEx_Init(p); SzArEx_Init(p);
} }
@@ -488,11 +611,11 @@ static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
folder->NumBindPairs = numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs = numOutStreams - 1;
MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);
for (i = 0; i < numBindPairs; i++) for (i = 0; i < numBindPairs; i++)
{ {
CBindPair *bp = folder->BindPairs + i; CSzBindPair *bp = folder->BindPairs + i;
RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->InIndex));
RINOK(SzReadNumber32(sd, &bp->OutIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex));
} }
@@ -780,81 +903,38 @@ static SRes SzReadStreamsInfo(
} }
} }
Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
{
size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
if (dest != 0)
{
size_t i;
const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2);
for (i = 0; i < len; i++)
dest[i] = GetUi16(src + i * 2);
}
return len;
}
static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes)
{ {
UInt32 i; UInt32 i;
size_t pos = 0;
for (i = 0; i < numFiles; i++) for (i = 0; i < numFiles; i++)
{ {
UInt32 len = 0; sizes[i] = pos;
UInt32 pos = 0; for (;;)
CSzFileItem *file = files + i;
while (pos + 2 <= sd->Size)
{ {
int numAdds; if (pos >= size)
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; return SZ_ERROR_ARCHIVE;
if (pos + 2 > sd->Size) if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0)
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; break;
len += numAdds; pos++;
} }
pos++;
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) sizes[i] = pos;
{ return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
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( static SRes SzReadHeader2(
@@ -920,7 +1000,8 @@ static SRes SzReadHeader2(
if (type == k7zIdEnd) if (type == k7zIdEnd)
break; break;
RINOK(SzReadNumber(sd, &size)); RINOK(SzReadNumber(sd, &size));
if (size > sd->Size)
return SZ_ERROR_ARCHIVE;
if ((UInt64)(int)type != type) if ((UInt64)(int)type != type)
{ {
RINOK(SzSkeepDataSize(sd, size)); RINOK(SzSkeepDataSize(sd, size));
@@ -930,8 +1011,16 @@ static SRes SzReadHeader2(
{ {
case k7zIdName: case k7zIdName:
{ {
size_t namesSize;
RINOK(SzReadSwitch(sd)); RINOK(SzReadSwitch(sd));
RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) namesSize = (size_t)size - 1;
if ((namesSize & 1) != 0)
return SZ_ERROR_ARCHIVE;
if (!Buf_Create(&p->FileNames, namesSize, allocMain))
return SZ_ERROR_MEM;
MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
memcpy(p->FileNames.data, sd->Data, namesSize);
RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))
break; break;
} }
case k7zIdEmptyStream: case k7zIdEmptyStream:
@@ -988,8 +1077,8 @@ static SRes SzReadHeader2(
{ {
file->IsDir = 0; file->IsDir = 0;
file->Size = (*unpackSizes)[sizeIndex]; file->Size = (*unpackSizes)[sizeIndex];
file->FileCRC = (*digests)[sizeIndex]; file->Crc = (*digests)[sizeIndex];
file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex];
sizeIndex++; sizeIndex++;
} }
else else
@@ -1000,7 +1089,8 @@ static SRes SzReadHeader2(
file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
emptyFileIndex++; emptyFileIndex++;
file->Size = 0; file->Size = 0;
file->FileCRCDefined = 0; file->Crc = 0;
file->CrcDefined = 0;
} }
} }
} }
@@ -1066,7 +1156,7 @@ static SRes SzReadAndDecodePackedStreams2(
if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = SzDecode(p->PackSizes, folder, res = SzFolder_Decode(folder, p->PackSizes,
inStream, dataStartPos, inStream, dataStartPos,
outBuffer->data, (size_t)unpackSize, allocTemp); outBuffer->data, (size_t)unpackSize, allocTemp);
RINOK(res); RINOK(res);
@@ -1202,3 +1292,85 @@ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAl
SzArEx_Free(p, allocMain); SzArEx_Free(p, allocMain);
return res; return res;
} }
SRes SzArEx_Extract(
const CSzArEx *p,
ILookInStream *inStream,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
SRes res = SZ_OK;
*offset = 0;
*outSizeProcessed = 0;
if (folderIndex == (UInt32)-1)
{
IAlloc_Free(allocMain, *outBuffer);
*blockIndex = folderIndex;
*outBuffer = 0;
*outBufferSize = 0;
return SZ_OK;
}
if (*outBuffer == 0 || *blockIndex != folderIndex)
{
CSzFolder *folder = p->db.Folders + folderIndex;
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec;
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM;
*blockIndex = folderIndex;
IAlloc_Free(allocMain, *outBuffer);
*outBuffer = 0;
RINOK(LookInStream_SeekTo(inStream, startOffset));
if (res == SZ_OK)
{
*outBufferSize = unpackSize;
if (unpackSize != 0)
{
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
if (*outBuffer == 0)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
{
res = SzFolder_Decode(folder,
p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
inStream, startOffset,
*outBuffer, unpackSize, allocTemp);
if (res == SZ_OK)
{
if (folder->UnpackCRCDefined)
{
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
res = SZ_ERROR_CRC;
}
}
}
}
}
if (res == SZ_OK)
{
UInt32 i;
CSzFileItem *fileItem = p->db.Files + fileIndex;
*offset = 0;
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)p->db.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;
if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL;
if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)
res = SZ_ERROR_CRC;
}
return res;
}

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 04 #define MY_VER_MINOR 06
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.04 beta" #define MY_VERSION "9.06 beta"
#define MY_DATE "2009-05-30" #define MY_DATE "2009-08-17"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@@ -1,7 +1,5 @@
/* Aes.c -- AES encryption / decryption /* Aes.c -- AES encryption / decryption
2008-08-05 2009-06-10 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#include "Aes.h" #include "Aes.h"
#include "CpuArch.h" #include "CpuArch.h"
@@ -49,7 +47,7 @@ void AesGenTables(void)
{ {
UInt32 a1 = Sbox[i]; UInt32 a1 = Sbox[i];
UInt32 a2 = xtime(a1); UInt32 a2 = xtime(a1);
UInt32 a3 = xtime(a1) ^ a1; UInt32 a3 = a2 ^ a1;
T[ i] = Ui32(a2, a1, a1, a3); T[ i] = Ui32(a2, a1, a1, a3);
T[0x100 + i] = Ui32(a3, a2, a1, a1); T[0x100 + i] = Ui32(a3, a2, a1, a1);
T[0x200 + i] = Ui32(a1, a3, a2, a1); T[0x200 + i] = Ui32(a1, a3, a2, a1);
@@ -115,7 +113,7 @@ void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize)
w = p->rkey; w = p->rkey;
for (i = 0; i < keySize; i++, key += 4) for (i = 0; i < keySize; i++, key += 4)
w[i] = Ui32(key[0], key[1], key[2], key[3]); w[i] = GetUi32(key);
for (; i < wSize; i++) for (; i < wSize; i++)
{ {

View File

@@ -1,21 +0,0 @@
/* 7zDecode.h -- Decoding from 7z folder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
#include "7zItem.h"
#ifdef __cplusplus
extern "C" {
#endif
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,93 +0,0 @@
/* 7zExtract.c -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */
#include "../../7zCrc.h"
#include "7zDecode.h"
#include "7zExtract.h"
SRes SzAr_Extract(
const CSzArEx *p,
ILookInStream *inStream,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
SRes res = SZ_OK;
*offset = 0;
*outSizeProcessed = 0;
if (folderIndex == (UInt32)-1)
{
IAlloc_Free(allocMain, *outBuffer);
*blockIndex = folderIndex;
*outBuffer = 0;
*outBufferSize = 0;
return SZ_OK;
}
if (*outBuffer == 0 || *blockIndex != folderIndex)
{
CSzFolder *folder = p->db.Folders + folderIndex;
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec;
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM;
*blockIndex = folderIndex;
IAlloc_Free(allocMain, *outBuffer);
*outBuffer = 0;
RINOK(LookInStream_SeekTo(inStream, startOffset));
if (res == SZ_OK)
{
*outBufferSize = unpackSize;
if (unpackSize != 0)
{
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
if (*outBuffer == 0)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
{
res = SzDecode(p->db.PackSizes +
p->FolderStartPackStreamIndex[folderIndex], folder,
inStream, startOffset,
*outBuffer, unpackSize, allocTemp);
if (res == SZ_OK)
{
if (folder->UnpackCRCDefined)
{
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
res = SZ_ERROR_CRC;
}
}
}
}
}
if (res == SZ_OK)
{
UInt32 i;
CSzFileItem *fileItem = p->db.Files + fileIndex;
*offset = 0;
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)p->db.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;
if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL;
{
if (fileItem->FileCRCDefined)
{
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
res = SZ_ERROR_CRC;
}
}
}
return res;
}

View File

@@ -1,49 +0,0 @@
/* 7zExtract.h -- Extracting from 7z archive
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_EXTRACT_H
#define __7Z_EXTRACT_H
#include "7zIn.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
SRes SzAr_Extract(
const CSzArEx *db,
ILookInStream *inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,6 +0,0 @@
/* 7zHeader.c -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */
#include "7zHeader.h"
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

View File

@@ -1,65 +0,0 @@
/* 7zHeader.h -- 7z Headers
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_HEADER_H
#define __7Z_HEADER_H
#include "../../Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
#define k7zStartHeaderSize 0x20
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnpackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnpackSize,
k7zIdNumUnpackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCTime,
k7zIdATime,
k7zIdMTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos,
k7zIdDummy
};
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,49 +0,0 @@
/* 7zIn.h -- 7z Input
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_IN_H
#define __7Z_IN_H
#include "7zHeader.h"
#include "7zItem.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
} CSzArEx;
void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/*
Errors:
SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM
SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,127 +0,0 @@
/* 7zItem.c -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */
#include "7zItem.h"
void SzCoderInfo_Init(CSzCoderInfo *p)
{
Buf_Init(&p->Props);
}
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
{
Buf_Free(&p->Props, alloc);
SzCoderInfo_Init(p);
}
void SzFolder_Init(CSzFolder *p)
{
p->Coders = 0;
p->BindPairs = 0;
p->PackStreams = 0;
p->UnpackSizes = 0;
p->NumCoders = 0;
p->NumBindPairs = 0;
p->NumPackStreams = 0;
p->UnpackCRCDefined = 0;
p->UnpackCRC = 0;
p->NumUnpackStreams = 0;
}
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Coders)
for (i = 0; i < p->NumCoders; i++)
SzCoderInfo_Free(&p->Coders[i], alloc);
IAlloc_Free(alloc, p->Coders);
IAlloc_Free(alloc, p->BindPairs);
IAlloc_Free(alloc, p->PackStreams);
IAlloc_Free(alloc, p->UnpackSizes);
SzFolder_Init(p);
}
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
{
UInt32 result = 0;
UInt32 i;
for (i = 0; i < p->NumCoders; i++)
result += p->Coders[i].NumOutStreams;
return result;
}
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
{
int i = (int)SzFolder_GetNumOutStreams(p);
if (i == 0)
return 0;
for (i--; i >= 0; i--)
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
return p->UnpackSizes[i];
/* throw 1; */
return 0;
}
void SzFile_Init(CSzFileItem *p)
{
p->HasStream = 1;
p->IsDir = 0;
p->IsAnti = 0;
p->FileCRCDefined = 0;
p->MTimeDefined = 0;
p->Name = 0;
}
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
{
IAlloc_Free(alloc, p->Name);
SzFile_Init(p);
}
void SzAr_Init(CSzAr *p)
{
p->PackSizes = 0;
p->PackCRCsDefined = 0;
p->PackCRCs = 0;
p->Folders = 0;
p->Files = 0;
p->NumPackStreams = 0;
p->NumFolders = 0;
p->NumFiles = 0;
}
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Folders)
for (i = 0; i < p->NumFolders; i++)
SzFolder_Free(&p->Folders[i], alloc);
if (p->Files)
for (i = 0; i < p->NumFiles; i++)
SzFile_Free(&p->Files[i], alloc);
IAlloc_Free(alloc, p->PackSizes);
IAlloc_Free(alloc, p->PackCRCsDefined);
IAlloc_Free(alloc, p->PackCRCs);
IAlloc_Free(alloc, p->Folders);
IAlloc_Free(alloc, p->Files);
SzAr_Init(p);
}

View File

@@ -1,92 +0,0 @@
/* 7zItem.h -- 7z Items
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_ITEM_H
#define __7Z_ITEM_H
#include "../../7zBuf.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
UInt64 MethodID;
CBuf Props;
} CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CBindPair;
typedef struct
{
CSzCoderInfo *Coders;
CBindPair *BindPairs;
UInt32 *PackStreams;
UInt64 *UnpackSizes;
UInt32 NumCoders;
UInt32 NumBindPairs;
UInt32 NumPackStreams;
int UnpackCRCDefined;
UInt32 UnpackCRC;
UInt32 NumUnpackStreams;
} CSzFolder;
void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
CNtfsFileTime MTime;
UInt64 Size;
char *Name;
UInt32 FileCRC;
Byte HasStream;
Byte IsDir;
Byte IsAnti;
Byte FileCRCDefined;
Byte MTimeDefined;
} CSzFileItem;
void SzFile_Init(CSzFileItem *p);
typedef struct
{
UInt64 *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
CSzFolder *Folders;
CSzFileItem *Files;
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt32 NumFiles;
} CSzAr;
void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,5 +1,5 @@
/* CpuArch.h /* CpuArch.h
2009-03-22 : Igor Pavlov : Public domain */ 2009-08-11 : Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
@@ -16,7 +16,19 @@ if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
about these properties of platform. about these properties of platform.
*/ */
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
#define MY_CPU_AMD64
#endif
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
#define MY_CPU_64BIT
#endif
#if defined(_M_IX86) || defined(__i386__) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64
#endif
#if defined(MY_CPU_X86_OR_AMD64)
#define LITTLE_ENDIAN_UNALIGN #define LITTLE_ENDIAN_UNALIGN
#endif #endif

View File

@@ -1,14 +1,15 @@
/* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86.h -- LZMA + x86 (BCJ) Filter
2009-02-07 : Igor Pavlov : Public domain */ 2009-08-14 : Igor Pavlov : Public domain */
#ifndef __LZMA86_ENC_H #ifndef __LZMA86_H
#define __LZMA86_ENC_H #define __LZMA86_H
#include "../Types.h" #include "Types.h"
#ifdef __cplusplus EXTERN_C_BEGIN
extern "C" {
#endif #define LZMA86_SIZE_OFFSET (1 + 5)
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
/* /*
It's an example for LZMA + x86 Filter use. It's an example for LZMA + x86 Filter use.
@@ -16,8 +17,8 @@ You can use .lzma86 extension, if you write that stream to file.
.lzma86 header adds one additional byte to standard .lzma header. .lzma86 header adds one additional byte to standard .lzma header.
.lzma86 header (14 bytes): .lzma86 header (14 bytes):
Offset Size Description Offset Size Description
0 1 = 0 - no filter, 0 1 = 0 - no filter, pure LZMA
= 1 - x86 filter = 1 - x86 filter + LZMA
1 1 lc, lp and pb in encoded form 1 1 lc, lp and pb in encoded form
2 4 dictSize (little endian) 2 4 dictSize (little endian)
6 8 uncompressed size (little endian) 6 8 uncompressed size (little endian)
@@ -27,7 +28,6 @@ Lzma86_Encode
------------- -------------
level - compression level: 0 <= level <= 9, the default value for "level" is 5. level - compression level: 0 <= level <= 9, the default value for "level" is 5.
dictSize - The dictionary size in bytes. The maximum value is dictSize - The dictionary size in bytes. The maximum value is
128 MB = (1 << 27) bytes for 32-bit version 128 MB = (1 << 27) bytes for 32-bit version
1 GB = (1 << 30) bytes for 64-bit version 1 GB = (1 << 30) bytes for 64-bit version
@@ -71,8 +71,41 @@ enum ESzFilterMode
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode); int level, UInt32 dictSize, int filterMode);
#ifdef __cplusplus
} /*
#endif Lzma86_GetUnpackSize:
In:
src - input data
srcLen - input data size
Out:
unpackSize - size of uncompressed stream
Return code:
SZ_OK - OK
SZ_ERROR_INPUT_EOF - Error in headers
*/
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);
/*
Lzma86_Decode:
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
Out:
destLen - processed output size
srcLen - processed input size
Return code:
SZ_OK - OK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - unsupported file
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer
*/
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
EXTERN_C_END
#endif #endif

View File

@@ -1,20 +1,14 @@
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
2008-04-07 2009-08-14 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#include "Lzma86Dec.h" #include "Lzma86.h"
#include "../Alloc.h" #include "Alloc.h"
#include "../Bra.h" #include "Bra.h"
#include "../LzmaDec.h" #include "LzmaDec.h"
#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE)
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); } static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
{ {
@@ -29,6 +23,7 @@ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)
{ {
ISzAlloc g_Alloc = { SzAlloc, SzFree };
SRes res; SRes res;
int useFilter; int useFilter;
SizeT inSizePure; SizeT inSizePure;

View File

@@ -1,28 +1,23 @@
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2008-08-05 2009-08-14 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#include <string.h> #include <string.h>
#include "Lzma86Enc.h" #include "Lzma86.h"
#include "../Alloc.h" #include "Alloc.h"
#include "../Bra.h" #include "Bra.h"
#include "../LzmaEnc.h" #include "LzmaEnc.h"
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR #define SZE_OUT_OVERFLOW SZE_DATA_ERROR
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); } static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE)
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode) int level, UInt32 dictSize, int filterMode)
{ {
ISzAlloc g_Alloc = { SzAlloc, SzFree };
size_t outSize2 = *destLen; size_t outSize2 = *destLen;
Byte *filteredStream; Byte *filteredStream;
Bool useFilter; Bool useFilter;

View File

@@ -1,51 +0,0 @@
/* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA86_DEC_H
#define __LZMA86_DEC_H
#include "../Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
Lzma86_GetUnpackSize:
In:
src - input data
srcLen - input data size
Out:
unpackSize - size of uncompressed stream
Return code:
SZ_OK - OK
SZ_ERROR_INPUT_EOF - Error in headers
*/
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);
/*
Lzma86_Decode:
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
Out:
destLen - processed output size
srcLen - processed input size
Return code:
SZ_OK - OK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - unsupported file
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer
*/
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,44 +0,0 @@
PROG = lzma
CXX = g++
LIB =
RM = rm -f
CFLAGS = -c -O2 -Wall
OBJS = \
LzmaUtil.o \
Alloc.o \
LzFind.o \
LzmaDec.o \
LzmaEnc.o \
7zFile.o \
7zStream.o \
all: $(PROG)
$(PROG): $(OBJS)
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
LzmaUtil.o: LzmaUtil.c
$(CXX) $(CFLAGS) LzmaUtil.c
Alloc.o: ../Alloc.c
$(CXX) $(CFLAGS) ../Alloc.c
LzFind.o: ../LzFind.c
$(CXX) $(CFLAGS) ../LzFind.c
LzmaDec.o: ../LzmaDec.c
$(CXX) $(CFLAGS) ../LzmaDec.c
LzmaEnc.o: ../LzmaEnc.c
$(CXX) $(CFLAGS) ../LzmaEnc.c
7zFile.o: ../7zFile.c
$(CXX) $(CFLAGS) ../7zFile.c
7zStream.o: ../7zStream.c
$(CXX) $(CFLAGS) ../7zStream.c
clean:
-$(RM) $(PROG) $(OBJS)

View File

@@ -1,7 +1,9 @@
/* Threads.c -- multithreading library /* Threads.c -- multithreading library
2009-03-27 : Igor Pavlov : Public domain */ 2009-07-20 : Igor Pavlov : Public domain */
#ifndef _WIN32_WCE
#include <process.h> #include <process.h>
#endif
#include "Threads.h" #include "Threads.h"
@@ -29,8 +31,11 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
{ {
unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
*p = *p =
/* CreateThread(0, 0, startAddress, param, 0, &threadId); */ #ifdef UNDER_CE
CreateThread(0, 0, func, param, 0, &threadId);
#else
(HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
#endif
/* maybe we must use errno here, but probably GetLastError() is also OK. */ /* maybe we must use errno here, but probably GetLastError() is also OK. */
return HandleToWRes(*p); return HandleToWRes(*p);
} }

View File

@@ -1,5 +1,5 @@
/* Types.h -- Basic types /* Types.h -- Basic types
2009-02-07 : Igor Pavlov : Public domain */ 2009-08-14 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
@@ -10,9 +10,17 @@
#include <windows.h> #include <windows.h>
#endif #endif
#ifndef EXTERN_C_BEGIN
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { #define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif #endif
#endif
EXTERN_C_BEGIN
#define SZ_OK 0 #define SZ_OK 0
@@ -209,8 +217,6 @@ typedef struct
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a) #define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef __cplusplus EXTERN_C_END
}
#endif
#endif #endif

View File

@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FAs /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /YX /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
@@ -67,7 +67,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
@@ -132,6 +132,10 @@ SOURCE=..\..\Bra86.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\CpuArch.h
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.c SOURCE=..\..\Lzma2Dec.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -153,6 +157,10 @@ SOURCE=..\..\Types.h
# End Group # End Group
# Begin Source File # Begin Source File
SOURCE=..\..\7z.h
# End Source File
# Begin Source File
SOURCE=.\7zAlloc.c SOURCE=.\7zAlloc.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -161,43 +169,11 @@ SOURCE=.\7zAlloc.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\7zDecode.c SOURCE=..\..\7zDec.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\7zDecode.h SOURCE=..\..\7zIn.c
# End Source File
# Begin Source File
SOURCE=.\7zExtract.c
# End Source File
# Begin Source File
SOURCE=.\7zExtract.h
# End Source File
# Begin Source File
SOURCE=.\7zHeader.c
# End Source File
# Begin Source File
SOURCE=.\7zHeader.h
# End Source File
# Begin Source File
SOURCE=.\7zIn.c
# End Source File
# Begin Source File
SOURCE=.\7zIn.h
# End Source File
# Begin Source File
SOURCE=.\7zItem.c
# End Source File
# Begin Source File
SOURCE=.\7zItem.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

View File

@@ -1,17 +1,16 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2009-04-04 : Igor Pavlov : Public domain */ 2009-08-17 : Igor Pavlov : Public domain */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../../7z.h"
#include "../../7zCrc.h" #include "../../7zCrc.h"
#include "../../7zFile.h" #include "../../7zFile.h"
#include "../../7zVersion.h" #include "../../7zVersion.h"
#include "7zAlloc.h" #include "7zAlloc.h"
#include "7zExtract.h"
#include "7zIn.h"
#ifndef USE_WINDOWS_FILE #ifndef USE_WINDOWS_FILE
/* for mkdir */ /* for mkdir */
@@ -29,20 +28,162 @@
#define CHAR_PATH_SEPARATOR '/' #define CHAR_PATH_SEPARATOR '/'
#endif #endif
static WRes MyCreateDir(const char *name) static ISzAlloc g_Alloc = { SzAlloc, SzFree };
static int Buf_EnsureSize(CBuf *dest, size_t size)
{
if (dest->size >= size)
return 1;
Buf_Free(dest, &g_Alloc);
return Buf_Create(dest, size, &g_Alloc);
}
#ifndef _WIN32
static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen)
{
size_t destPos = 0, srcPos = 0;
for (;;)
{
unsigned numAdds;
UInt32 value;
if (srcPos == srcLen)
{
*destLen = destPos;
return True;
}
value = src[srcPos++];
if (value < 0x80)
{
if (dest)
dest[destPos] = (char)value;
destPos++;
continue;
}
if (value >= 0xD800 && value < 0xE000)
{
UInt32 c2;
if (value >= 0xDC00 || srcPos == srcLen)
break;
c2 = src[srcPos++];
if (c2 < 0xDC00 || c2 >= 0xE000)
break;
value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
}
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
break;
if (dest)
dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
destPos++;
do
{
numAdds--;
if (dest)
dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
destPos++;
}
while (numAdds != 0);
}
*destLen = destPos;
return False;
}
static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)
{
size_t destLen = 0;
Bool res;
Utf16_To_Utf8(NULL, &destLen, src, srcLen);
destLen += 1;
if (!Buf_EnsureSize(dest, destLen))
return SZ_ERROR_MEM;
res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);
dest->data[destLen] = 0;
return res ? SZ_OK : SZ_ERROR_FAIL;
}
#endif
static WRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode)
{
int len = 0;
for (len = 0; s[len] != '\0'; len++);
#ifdef _WIN32
{
int size = len * 3 + 100;
if (!Buf_EnsureSize(buf, size))
return SZ_ERROR_MEM;
{
char defaultChar = '_';
BOOL defUsed;
int numChars = WideCharToMultiByte(fileMode ? (AreFileApisANSI() ? CP_ACP : CP_OEMCP) : CP_OEMCP,
0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);
if (numChars == 0 || numChars >= size)
return SZ_ERROR_FAIL;
buf->data[numChars] = 0;
return SZ_OK;
}
}
#else
fileMode = fileMode;
return Utf16_To_Utf8Buf(buf, s, len);
#endif
}
static WRes MyCreateDir(const UInt16 *name)
{ {
#ifdef USE_WINDOWS_FILE #ifdef USE_WINDOWS_FILE
return CreateDirectoryA(name, NULL) ? 0 : GetLastError();
return CreateDirectoryW(name, NULL) ? 0 : GetLastError();
#else #else
CBuf buf;
WRes res;
Buf_Init(&buf);
RINOK(Utf16_To_Char(&buf, name, 1));
res =
#ifdef _WIN32 #ifdef _WIN32
return _mkdir(name) _mkdir((const char *)buf.data)
#else #else
return mkdir(name, 0777) mkdir((const char *)buf.data, 0777)
#endif #endif
== 0 ? 0 : errno; == 0 ? 0 : errno;
Buf_Free(&buf, &g_Alloc);
return res;
#endif #endif
} }
static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
{
#ifdef USE_WINDOWS_FILE
return OutFile_OpenW(p, name);
#else
CBuf buf;
WRes res;
Buf_Init(&buf);
RINOK(Utf16_To_Char(&buf, name, 1));
res = OutFile_Open(p, (const char *)buf.data);
Buf_Free(&buf, &g_Alloc);
return res;
#endif
}
static void PrintString(const UInt16 *s)
{
CBuf buf;
Buf_Init(&buf);
if (Utf16_To_Char(&buf, s, 0) == 0)
{
printf("%s", buf.data);
Buf_Free(&buf, &g_Alloc);
}
}
static void ConvertNumberToString(UInt64 value, char *s) static void ConvertNumberToString(UInt64 value, char *s)
{ {
@@ -128,7 +269,7 @@ int MY_CDECL main(int numargs, char *args[])
SRes res; SRes res;
ISzAlloc allocImp; ISzAlloc allocImp;
ISzAlloc allocTempImp; ISzAlloc allocTempImp;
char *temp = NULL; UInt16 *temp = NULL;
size_t tempSize = 0; size_t tempSize = 0;
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");
@@ -149,25 +290,24 @@ int MY_CDECL main(int numargs, char *args[])
return 1; return 1;
} }
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
allocTempImp.Alloc = SzAllocTemp;
allocTempImp.Free = SzFreeTemp;
if (InFile_Open(&archiveStream.file, args[2])) if (InFile_Open(&archiveStream.file, args[2]))
{ {
PrintError("can not open input file"); PrintError("can not open input file");
return 1; return 1;
} }
FileInStream_CreateVTable(&archiveStream); FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False); LookToRead_CreateVTable(&lookStream, False);
lookStream.realStream = &archiveStream.s; lookStream.realStream = &archiveStream.s;
LookToRead_Init(&lookStream); LookToRead_Init(&lookStream);
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
allocTempImp.Alloc = SzAllocTemp;
allocTempImp.Free = SzFreeTemp;
CrcGenerateTable(); CrcGenerateTable();
SzArEx_Init(&db); SzArEx_Init(&db);
@@ -180,27 +320,13 @@ int MY_CDECL main(int numargs, char *args[])
else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1;
else if (strcmp(command, "e") == 0) extractCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1;
else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; } else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; }
if (listCommand)
{
UInt32 i;
for (i = 0; i < db.db.NumFiles; i++)
{
const CSzFileItem *f = db.db.Files + i;
char s[32], t[32];
ConvertNumberToString(f->Size, s);
if (f->MTimeDefined)
ConvertFileTimeToString(&f->MTime, t);
else else
strcpy(t, " "); {
PrintError("incorrect command");
res = SZ_ERROR_FAIL;
}
printf("%s %10s %s", t, s, f->Name); if (res == SZ_OK)
if (f->IsDir)
printf("/");
printf("\n");
}
}
else if (testCommand || extractCommand)
{ {
UInt32 i; UInt32 i;
@@ -214,20 +340,52 @@ int MY_CDECL main(int numargs, char *args[])
for (i = 0; i < db.db.NumFiles; i++) for (i = 0; i < db.db.NumFiles; i++)
{ {
size_t offset; size_t offset = 0;
size_t outSizeProcessed; size_t outSizeProcessed = 0;
const CSzFileItem *f = db.db.Files + i; const CSzFileItem *f = db.db.Files + i;
if (f->IsDir && !fullPaths) size_t len;
if (listCommand == 0 && f->IsDir && !fullPaths)
continue; continue;
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (len > tempSize)
{
SzFree(NULL, temp);
tempSize = len;
temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));
if (temp == 0)
{
res = SZ_ERROR_MEM;
break;
}
}
SzArEx_GetFileNameUtf16(&db, i, temp);
if (listCommand)
{
char s[32], t[32];
ConvertNumberToString(f->Size, s);
if (f->MTimeDefined)
ConvertFileTimeToString(&f->MTime, t);
else
strcpy(t, " ");
printf("%s %10s ", t, s);
PrintString(temp);
if (f->IsDir)
printf("/");
printf("\n");
continue;
}
printf(testCommand ? printf(testCommand ?
"Testing ": "Testing ":
"Extracting"); "Extracting ");
printf(" %s", f->Name); PrintString(temp);
if (f->IsDir) if (f->IsDir)
printf("/"); printf("/");
else else
{ {
res = SzAr_Extract(&db, &lookStream.s, i, res = SzArEx_Extract(&db, &lookStream.s, i,
&blockIndex, &outBuffer, &outBufferSize, &blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed, &offset, &outSizeProcessed,
&allocImp, &allocTempImp); &allocImp, &allocTempImp);
@@ -238,32 +396,20 @@ int MY_CDECL main(int numargs, char *args[])
{ {
CSzFile outFile; CSzFile outFile;
size_t processedSize; size_t processedSize;
size_t j, nameLen = strlen(f->Name); size_t j;
const char *destPath; UInt16 *name = (UInt16 *)temp;
if (nameLen + 1 > tempSize) const UInt16 *destPath = (const UInt16 *)name;
{ for (j = 0; name[j] != 0; j++)
SzFree(NULL, temp); if (name[j] == '/')
tempSize = nameLen + 1;
temp = (char *)SzAlloc(NULL, tempSize);
if (temp == 0)
{
res = SZ_ERROR_MEM;
break;
}
}
destPath = temp;
strcpy(temp, f->Name);
for (j = 0; j < nameLen; j++)
if (temp[j] == '/')
{ {
if (fullPaths) if (fullPaths)
{ {
temp[j] = 0; name[j] = 0;
MyCreateDir(temp); MyCreateDir(name);
temp[j] = CHAR_PATH_SEPARATOR; name[j] = CHAR_PATH_SEPARATOR;
} }
else else
destPath = temp + j + 1; destPath = name + j + 1;
} }
if (f->IsDir) if (f->IsDir)
@@ -272,15 +418,14 @@ int MY_CDECL main(int numargs, char *args[])
printf("\n"); printf("\n");
continue; continue;
} }
else if (OutFile_Open(&outFile, destPath)) else if (OutFile_OpenUtf16(&outFile, destPath))
{ {
PrintError("can not open output file"); PrintError("can not open output file");
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
break; break;
} }
processedSize = outSizeProcessed; processedSize = outSizeProcessed;
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
processedSize != outSizeProcessed)
{ {
PrintError("can not write output file"); PrintError("can not write output file");
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
@@ -297,11 +442,6 @@ int MY_CDECL main(int numargs, char *args[])
} }
IAlloc_Free(&allocImp, outBuffer); IAlloc_Free(&allocImp, outBuffer);
} }
else
{
PrintError("incorrect command");
res = SZ_ERROR_FAIL;
}
} }
SzArEx_Free(&db, &allocImp); SzArEx_Free(&db, &allocImp);
SzFree(NULL, temp); SzFree(NULL, temp);

View File

@@ -6,20 +6,17 @@ C_OBJS = \
$O\7zBuf.obj \ $O\7zBuf.obj \
$O\7zBuf2.obj \ $O\7zBuf2.obj \
$O\7zCrc.obj \ $O\7zCrc.obj \
$O\LzmaDec.obj \
$O\Lzma2Dec.obj \
$O\Bra86.obj \
$O\Bcj2.obj \
$O\7zFile.obj \ $O\7zFile.obj \
$O\7zDec.obj \
$O\7zIn.obj \
$O\7zStream.obj \ $O\7zStream.obj \
$O\Bcj2.obj \
$O\Bra86.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
7Z_OBJS = \ 7Z_OBJS = \
$O\7zAlloc.obj \ $O\7zAlloc.obj \
$O\7zDecode.obj \
$O\7zExtract.obj \
$O\7zHeader.obj \
$O\7zIn.obj \
$O\7zItem.obj \
$O\7zMain.obj \ $O\7zMain.obj \
OBJS = \ OBJS = \

View File

@@ -4,7 +4,7 @@ LIB =
RM = rm -f RM = rm -f
CFLAGS = -c -O2 -Wall CFLAGS = -c -O2 -Wall
OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDec.o 7zIn.o 7zMain.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o
all: $(PROG) all: $(PROG)
@@ -23,20 +23,11 @@ $(PROG): $(OBJS)
7zCrc.o: ../../7zCrc.c 7zCrc.o: ../../7zCrc.c
$(CXX) $(CFLAGS) ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c
7zDecode.o: 7zDecode.c 7zDec.o: ../../7zDec.c
$(CXX) $(CFLAGS) 7zDecode.c $(CXX) $(CFLAGS) ../../7zDec.c
7zExtract.o: 7zExtract.c 7zIn.o: ../../7zIn.c
$(CXX) $(CFLAGS) 7zExtract.c $(CXX) $(CFLAGS) ../../7zIn.c
7zHeader.o: 7zHeader.c
$(CXX) $(CFLAGS) 7zHeader.c
7zIn.o: 7zIn.c
$(CXX) $(CFLAGS) 7zIn.c
7zItem.o: 7zItem.c
$(CXX) $(CFLAGS) 7zItem.c
7zMain.o: 7zMain.c 7zMain.o: 7zMain.c
$(CXX) $(CFLAGS) 7zMain.c $(CXX) $(CFLAGS) 7zMain.c

View File

@@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression /* LzmaUtil.c -- Test application for LZMA compression
2008-11-23 : Igor Pavlov : Public domain */ 2009-08-14 : Igor Pavlov : Public domain */
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
@@ -7,11 +7,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../Alloc.h" #include "../../Alloc.h"
#include "../7zFile.h" #include "../../7zFile.h"
#include "../7zVersion.h" #include "../../7zVersion.h"
#include "../LzmaDec.h" #include "../../LzmaDec.h"
#include "../LzmaEnc.h" #include "../../LzmaEnc.h"
const char *kCantReadMessage = "Can not read input file"; const char *kCantReadMessage = "Can not read input file";
const char *kCantWriteMessage = "Can not write output file"; const char *kCantWriteMessage = "Can not write output file";

View File

@@ -51,7 +51,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\lzmac.exe" # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7lzma.exe"
!ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" !ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug"
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\lzmac.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7lzma.exe" /pdbtype:sept
!ENDIF !ENDIF
@@ -86,67 +86,67 @@ LINK32=link.exe
# Name "LzmaUtil - Win32 Debug" # Name "LzmaUtil - Win32 Debug"
# Begin Source File # Begin Source File
SOURCE=..\7zFile.c SOURCE=..\..\7zFile.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\7zFile.h SOURCE=..\..\7zFile.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\7zStream.c SOURCE=..\..\7zStream.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\7zVersion.h SOURCE=..\..\7zVersion.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Alloc.c SOURCE=..\..\Alloc.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Alloc.h SOURCE=..\..\Alloc.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\CpuArch.h SOURCE=..\..\CpuArch.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFind.c SOURCE=..\..\LzFind.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFind.h SOURCE=..\..\LzFind.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFindMt.c SOURCE=..\..\LzFindMt.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFindMt.h SOURCE=..\..\LzFindMt.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzHash.h SOURCE=..\..\LzHash.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaDec.c SOURCE=..\..\LzmaDec.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaDec.h SOURCE=..\..\LzmaDec.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaEnc.c SOURCE=..\..\LzmaEnc.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaEnc.h SOURCE=..\..\LzmaEnc.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -154,15 +154,15 @@ SOURCE=.\LzmaUtil.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Threads.c SOURCE=..\..\Threads.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Threads.h SOURCE=..\..\Threads.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Types.h SOURCE=..\..\Types.h
# End Source File # End Source File
# End Target # End Target
# End Project # End Project

View File

@@ -21,9 +21,9 @@ OBJS = \
$(LIB_OBJS) \ $(LIB_OBJS) \
$(C_OBJS) \ $(C_OBJS) \
!include "../../CPP/Build.mak" !include "../../../CPP/Build.mak"
$(LIB_OBJS): $(*B).c $(LIB_OBJS): $(*B).c
$(COMPL_O2) $(COMPL_O2)
$(C_OBJS): ../$(*B).c $(C_OBJS): ../../$(*B).c
$(COMPL_O2) $(COMPL_O2)

44
C/Util/Lzma/makefile.gcc Executable file
View File

@@ -0,0 +1,44 @@
PROG = lzma
CXX = g++
LIB =
RM = rm -f
CFLAGS = -c -O2 -Wall
OBJS = \
LzmaUtil.o \
Alloc.o \
LzFind.o \
LzmaDec.o \
LzmaEnc.o \
7zFile.o \
7zStream.o \
all: $(PROG)
$(PROG): $(OBJS)
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
LzmaUtil.o: LzmaUtil.c
$(CXX) $(CFLAGS) LzmaUtil.c
Alloc.o: ../../Alloc.c
$(CXX) $(CFLAGS) ../../Alloc.c
LzFind.o: ../../LzFind.c
$(CXX) $(CFLAGS) ../../LzFind.c
LzmaDec.o: ../../LzmaDec.c
$(CXX) $(CFLAGS) ../../LzmaDec.c
LzmaEnc.o: ../../LzmaEnc.c
$(CXX) $(CFLAGS) ../../LzmaEnc.c
7zFile.o: ../../7zFile.c
$(CXX) $(CFLAGS) ../../7zFile.c
7zStream.o: ../../7zStream.c
$(CXX) $(CFLAGS) ../../7zStream.c
clean:
-$(RM) $(PROG) $(OBJS)

View File

@@ -104,59 +104,59 @@ SOURCE=.\LzmaLibExports.c
# End Group # End Group
# Begin Source File # Begin Source File
SOURCE=..\Alloc.c SOURCE=..\..\Alloc.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Alloc.h SOURCE=..\..\Alloc.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\IStream.h SOURCE=..\..\IStream.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFind.c SOURCE=..\..\LzFind.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFind.h SOURCE=..\..\LzFind.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFindMt.c SOURCE=..\..\LzFindMt.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzFindMt.h SOURCE=..\..\LzFindMt.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzHash.h SOURCE=..\..\LzHash.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaDec.c SOURCE=..\..\LzmaDec.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaDec.h SOURCE=..\..\LzmaDec.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaEnc.c SOURCE=..\..\LzmaEnc.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaEnc.h SOURCE=..\..\LzmaEnc.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaLib.c SOURCE=..\..\LzmaLib.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\LzmaLib.h SOURCE=..\..\LzmaLib.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -164,15 +164,15 @@ SOURCE=.\resource.rc
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Threads.c SOURCE=..\..\Threads.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Threads.h SOURCE=..\..\Threads.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Types.h SOURCE=..\..\Types.h
# End Source File # End Source File
# End Target # End Target
# End Project # End Project

View File

@@ -7,8 +7,6 @@ DEF_FILE = LzmaLib.def
CFLAGS = $(CFLAGS) \ CFLAGS = $(CFLAGS) \
-DCOMPRESS_MF_MT \ -DCOMPRESS_MF_MT \
LIBS = $(LIBS) oleaut32.lib
LIB_OBJS = \ LIB_OBJS = \
$O\LzmaLibExports.obj \ $O\LzmaLibExports.obj \
@@ -26,12 +24,12 @@ OBJS = \
$(C_OBJS) \ $(C_OBJS) \
$O\resource.res $O\resource.res
!include "../../CPP/Build.mak" !include "../../../CPP/Build.mak"
$(SLIBPATH): $O $(OBJS) $(SLIBPATH): $O $(OBJS)
lib -out:$(SLIBPATH) $(OBJS) $(LIBS) lib -out:$(SLIBPATH) $(OBJS) $(LIBS)
$(LIB_OBJS): $(*B).c $(LIB_OBJS): $(*B).c
$(COMPL_O2) $(COMPL_O2)
$(C_OBJS): ../$(*B).c $(C_OBJS): ../../$(*B).c
$(COMPL_O2) $(COMPL_O2)

View File

@@ -1,4 +1,4 @@
#include "../../CPP/7zip/MyVersionInfo.rc" #include "../../../CPP/7zip/MyVersionInfo.rc"
MY_VERSION_INFO_DLL("LZMA library", "LZMA") MY_VERSION_INFO_DLL("LZMA library", "LZMA")

View File

@@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode /* XzDec.c -- Xz Decode
2009-05-29 : Igor Pavlov : Public domain */ 2009-06-08 : Igor Pavlov : Public domain */
/* #define XZ_DUMP */ /* #define XZ_DUMP */
@@ -291,9 +291,10 @@ static void Lzma2State_Init(void *pp)
} }
static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ELzmaFinishMode finishMode, int *wasFinished) int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
{ {
ELzmaStatus status; ELzmaStatus status;
/* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status); SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status);
srcWasFinished = srcWasFinished; srcWasFinished = srcWasFinished;
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
@@ -373,7 +374,7 @@ SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcWasFinished, const Byte *src, SizeT *srcLen, int srcWasFinished,
ELzmaFinishMode finishMode, ECoderStatus *status) ECoderFinishMode finishMode, ECoderStatus *status)
{ {
SizeT destLenOrig = *destLen; SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen; SizeT srcLenOrig = *srcLen;

View File

@@ -1,5 +1,5 @@
/* XzEnc.c -- Xz Encode /* XzEnc.c -- Xz Encode
2009-05-26 : Igor Pavlov : Public domain */ 2009-06-04 : Igor Pavlov : Public domain */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -442,7 +442,7 @@ static SRes Xz_Compress(CXzStream *xz,
{ {
UInt64 packPos = seqSizeOutStream.processed; UInt64 packPos = seqSizeOutStream.processed;
HRESULT res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
useSubblock ? &lzmaf->sb.p: useSubblock ? &lzmaf->sb.p:
#endif #endif

View File

@@ -1,10 +1,11 @@
/* XzIn.c - Xz input /* XzIn.c - Xz input
2009-04-15 : Igor Pavlov : Public domain */ 2009-06-19 : Igor Pavlov : Public domain */
#include "Xz.h" #include <string.h>
#include "7zCrc.h" #include "7zCrc.h"
#include "CpuArch.h" #include "CpuArch.h"
#include "Xz.h"
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream) SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)
{ {

View File

@@ -164,8 +164,7 @@ HRESULT CEncoder::Encode(
} }
for (i = 1; i < _bindInfo.OutStreams.Size(); i++) for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{ {
CSequentialOutTempBufferImp *tempBufferSpec = CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;
new CSequentialOutTempBufferImp;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer); tempBuffers.Add(tempBuffer);
@@ -260,9 +259,7 @@ HRESULT CEncoder::Encode(
for (i = 1; i < _bindInfo.OutStreams.Size(); i++) for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{ {
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
inOutTempBuffer.FlushWrite(); RINOK(inOutTempBuffer.WriteToStream(outStream));
inOutTempBuffer.InitReading();
inOutTempBuffer.WriteToStream(outStream);
packSizes.Add(inOutTempBuffer.GetDataSize()); packSizes.Add(inOutTempBuffer.GetDataSize());
} }

View File

@@ -44,7 +44,7 @@ struct CExtractFolderInfo
}; };
}; };
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
@@ -52,7 +52,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UInt64 importantTotalUnpacked = 0; UInt64 importantTotalUnpacked = 0;
bool allFilesMode = (numItems == UInt32(-1)); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = numItems =
#ifdef _7Z_VOL #ifdef _7Z_VOL
@@ -244,25 +244,25 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (result == S_FALSE) if (result == S_FALSE)
{ {
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
continue; continue;
} }
if (result == E_NOTIMPL) if (result == E_NOTIMPL)
{ {
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod));
continue; continue;
} }
if (result != S_OK) if (result != S_OK)
return result; return result;
if (folderOutStream->WasWritingFinished() != S_OK) if (folderOutStream->WasWritingFinished() != S_OK)
{ {
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
continue; continue;
} }
} }
catch(...) catch(...)
{ {
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
continue; continue;
} }
} }

View File

@@ -37,9 +37,9 @@ HRESULT CFolderOutStream::Init(
HRESULT CFolderOutStream::OpenFile() HRESULT CFolderOutStream::OpenFile()
{ {
Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ? Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract): NExtract::NAskMode::kExtract) :
NArchive::NExtract::NAskMode::kSkip; NExtract::NAskMode::kSkip;
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
UInt32 index = _startIndex + _currentIndex; UInt32 index = _startIndex + _currentIndex;
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
@@ -48,9 +48,9 @@ HRESULT CFolderOutStream::OpenFile()
_fileIsOpen = true; _fileIsOpen = true;
const CFileItem &fi = _db->Files[index]; const CFileItem &fi = _db->Files[index];
_rem = fi.Size; _rem = fi.Size;
if (askMode == NArchive::NExtract::NAskMode::kExtract && !realOutStream && if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&
!_db->IsItemAnti(index) && !fi.IsDir) !_db->IsItemAnti(index) && !fi.IsDir)
askMode = NArchive::NExtract::NAskMode::kSkip; askMode = NExtract::NAskMode::kSkip;
return _extractCallback->PrepareOperation(askMode); return _extractCallback->PrepareOperation(askMode);
} }
@@ -67,8 +67,8 @@ HRESULT CFolderOutStream::CloseFileAndSetResult()
const CFileItem &fi = _db->Files[_startIndex + _currentIndex]; const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
return CloseFileAndSetResult( return CloseFileAndSetResult(
(fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ? (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
NArchive::NExtract::NOperationResult::kOK : NExtract::NOperationResult::kOK :
NArchive::NExtract::NOperationResult::kCRCError); NExtract::NOperationResult::kCRCError);
} }
HRESULT CFolderOutStream::ProcessEmptyFiles() HRESULT CFolderOutStream::ProcessEmptyFiles()

View File

@@ -300,11 +300,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5) else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)
{ {
Byte order = *(const Byte *)coder.Props; Byte order = *(const Byte *)coder.Props;
methodsString += L'o'; propsString = L'o';
methodsString += ConvertUInt32ToString(order); propsString += ConvertUInt32ToString(order);
methodsString += L":mem"; propsString += L":mem";
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
propsString = GetStringForSizeValue(dicSize); propsString += GetStringForSizeValue(dicSize);
} }
else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1) else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)
{ {

View File

@@ -27,7 +27,13 @@ static const wchar_t *kDefaultMethodName = kLZMAMethodName;
static const UInt32 kLzmaAlgorithmX5 = 1; static const UInt32 kLzmaAlgorithmX5 = 1;
static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kDictionaryForHeaders =
#ifdef UNDER_CE
1 << 18
#else
1 << 20
#endif
;
static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kNumFastBytesForHeaders = 273;
static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;

View File

@@ -1,4 +1,4 @@
// 7z/Header.cpp // 7zHeader.cpp
#include "StdAfx.h" #include "StdAfx.h"
#include "7zHeader.h" #include "7zHeader.h"
@@ -6,22 +6,9 @@
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
#ifdef _7Z_VOL #ifdef _7Z_VOL
Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
#endif #endif
class SignatureInitializer
{
public:
SignatureInitializer()
{
kSignature[0]--;
#ifdef _7Z_VOL
kFinishSignature[0]--;
#endif
};
} g_SignatureInitializer;
}} }}

View File

@@ -541,16 +541,16 @@ void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
HRESULT COutArchive::EncodeStream( HRESULT COutArchive::EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const Byte *data, size_t dataSize, CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
{ {
CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> stream = streamSpec; CMyComPtr<ISequentialInStream> stream = streamSpec;
streamSpec->Init(data, dataSize); streamSpec->Init(data, data.GetCapacity());
CFolder folderItem; CFolder folderItem;
folderItem.UnpackCRCDefined = true; folderItem.UnpackCRCDefined = true;
folderItem.UnpackCRC = CrcCalc(data, dataSize); folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity());
UInt64 dataSize64 = dataSize; UInt64 dataSize64 = data.GetCapacity();
RINOK(encoder.Encode( RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))
@@ -558,16 +558,6 @@ HRESULT COutArchive::EncodeStream(
return S_OK; return S_OK;
} }
HRESULT COutArchive::EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
{
return EncodeStream(
EXTERNAL_CODECS_LOC_VARS
encoder, data, data.GetCapacity(), packSizes, folders);
}
void COutArchive::WriteHeader( void COutArchive::WriteHeader(
const CArchiveDatabase &db, const CArchiveDatabase &db,
const CHeaderOptions &headerOptions, const CHeaderOptions &headerOptions,
@@ -804,8 +794,8 @@ HRESULT COutArchive::WriteDatabase(
CObjectVector<CFolder> folders; CObjectVector<CFolder> folders;
RINOK(EncodeStream( RINOK(EncodeStream(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
encoder, (const Byte *)buf, encoder, buf,
_countSize, packSizes, folders)); packSizes, folders));
_writeToStream = true; _writeToStream = true;

View File

@@ -98,10 +98,6 @@ class COutArchive
void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize);
void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);
HRESULT EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const Byte *data, size_t dataSize,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
HRESULT EncodeStream( HRESULT EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const CByteBuffer &data, CEncoder &encoder, const CByteBuffer &data,

View File

@@ -13,6 +13,6 @@ static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; }
#endif #endif
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; { L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut };
REGISTER_ARC_DEC_SIG(7z) REGISTER_ARC_DEC_SIG(7z)

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../Common/LimitedStreams.h" #include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h" #include "../../Common/ProgressUtils.h"
@@ -32,6 +34,10 @@ static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;
#ifdef MY_CPU_X86_OR_AMD64
#define USE_86_FILTER
#endif
static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
UInt64 position, UInt64 size, ICompressProgressInfo *progress) UInt64 position, UInt64 size, ICompressProgressInfo *progress)
{ {
@@ -122,7 +128,7 @@ static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
} }
*/ */
const struct CFolderRepack struct CFolderRepack
{ {
int FolderIndex; int FolderIndex;
int Group; int Group;
@@ -334,7 +340,9 @@ static bool IsExeExt(const UString &ext)
return false; return false;
} }
static void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) #ifdef USE_86_FILTER
static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult)
{ {
methodResult.Id = methodID; methodResult.Id = methodID;
methodResult.NumInStreams = numInStreams; methodResult.NumInStreams = numInStreams;
@@ -409,6 +417,8 @@ static void MakeExeMethod(const CCompressionMethodMode &method,
} }
} }
#endif
static void FromUpdateItemToFileItem(const CUpdateItem &ui, static void FromUpdateItemToFileItem(const CUpdateItem &ui,
CFileItem &file, CFileItem2 &file2) CFileItem &file, CFileItem2 &file2)
{ {
@@ -665,7 +675,9 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
static const int kNumGroupsMax = 4; static const int kNumGroupsMax = 4;
#ifdef USE_86_FILTER
static bool Is86Group(int group) { return (group & 1) != 0; } static bool Is86Group(int group) { return (group & 1) != 0; }
#endif
static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
static int GetGroupIndex(bool encrypted, int bcjFiltered) static int GetGroupIndex(bool encrypted, int bcjFiltered)
{ return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
@@ -865,9 +877,11 @@ HRESULT Update(
const CSolidGroup &group = groups[groupIndex]; const CSolidGroup &group = groups[groupIndex];
CCompressionMethodMode method; CCompressionMethodMode method;
#ifdef USE_86_FILTER
if (Is86Group(groupIndex)) if (Is86Group(groupIndex))
MakeExeMethod(*options.Method, options.MaxFilter, method); MakeExeMethod(*options.Method, options.MaxFilter, method);
else else
#endif
method = *options.Method; method = *options.Method;
if (IsEncryptedGroup(groupIndex)) if (IsEncryptedGroup(groupIndex))

View File

@@ -4,8 +4,6 @@ CFLAGS = $(CFLAGS) -I ../../../ \
-DCOMPRESS_MT \ -DCOMPRESS_MT \
-DEXTERNAL_CODECS \ -DEXTERNAL_CODECS \
LIBS = $(LIBS) oleaut32.lib user32.lib
AR_OBJS = \ AR_OBJS = \
$O\ArchiveExports.obj \ $O\ArchiveExports.obj \
$O\DllExports.obj \ $O\DllExports.obj \

View File

@@ -10,11 +10,17 @@
static const unsigned int kNumArcsMax = 48; static const unsigned int kNumArcsMax = 48;
static unsigned int g_NumArcs = 0; static unsigned int g_NumArcs = 0;
static unsigned int g_DefaultArcIndex = 0;
static const CArcInfo *g_Arcs[kNumArcsMax]; static const CArcInfo *g_Arcs[kNumArcsMax];
void RegisterArc(const CArcInfo *arcInfo) void RegisterArc(const CArcInfo *arcInfo)
{ {
if (g_NumArcs < kNumArcsMax) if (g_NumArcs < kNumArcsMax)
{
const wchar_t *p = arcInfo->Name;
if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
g_DefaultArcIndex = g_NumArcs;
g_Arcs[g_NumArcs++] = arcInfo; g_Arcs[g_NumArcs++] = arcInfo;
}
} }
DEFINE_GUID(CLSID_CArchiveHandler, DEFINE_GUID(CLSID_CArchiveHandler,
@@ -117,7 +123,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
{ {
return GetHandlerProperty2(0, propID, value); return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
} }
STDAPI GetNumberOfFormats(UINT32 *numFormats) STDAPI GetNumberOfFormats(UINT32 *numFormats)

View File

@@ -652,13 +652,12 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (testModeSpec != 0);
UInt64 totalUnpacked = 0, totalPacked = 0; UInt64 totalUnpacked = 0, totalPacked = 0;
bool allFilesMode = (numItems == UInt32(-1)); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = _items.Size(); numItems = _items.Size();
if (numItems == 0) if (numItems == 0)
@@ -714,7 +713,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
continue; continue;
} }
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));

View File

@@ -154,28 +154,23 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (!allFilesMode)
{
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
if (numItems != 1 || indices[0] != 0) if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG; return E_INVALIDARG;
}
bool testMode = (_aTestMode != 0);
if (_stream) if (_stream)
extractCallback->SetTotal(_packSize); extractCallback->SetTotal(_packSize);
UInt64 currentTotalPacked = 0; UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked)); RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream) if (!testMode && !realOutStream)
return S_OK; return S_OK;
@@ -421,7 +416,7 @@ static IOutArchive *CreateArcOut() { return new CHandler; }
#endif #endif
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"BZip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut }; { L"bzip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut };
REGISTER_ARC(BZip2) REGISTER_ARC(BZip2)

View File

@@ -2,6 +2,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/Buffer.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/Defs.h" #include "Common/Defs.h"
#include "Common/IntToString.h" #include "Common/IntToString.h"
@@ -12,6 +13,7 @@
#include "Windows/Time.h" #include "Windows/Time.h"
#include "../../Common/ProgressUtils.h" #include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
#include "../../Compress/CopyCoder.h" #include "../../Compress/CopyCoder.h"
#include "../../Compress/DeflateDecoder.h" #include "../../Compress/DeflateDecoder.h"
@@ -30,6 +32,8 @@ namespace NCab {
// #define _CAB_DETAILS // #define _CAB_DETAILS
static const UInt32 kMaxTempBufSize = 1 << 20;
#ifdef _CAB_DETAILS #ifdef _CAB_DETAILS
enum enum
{ {
@@ -279,7 +283,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
{ {
const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo; const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo;
if (ai.IsTherePrev()) if (ai.IsTherePrev())
otherArchive = &ai.PreviousArchive; otherArchive = &ai.PrevArc;
else else
prevChecked = true; prevChecked = true;
} }
@@ -287,7 +291,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
{ {
const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo; const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo;
if (ai.IsThereNext()) if (ai.IsThereNext())
otherArchive = &ai.NextArchive; otherArchive = &ai.NextArc;
} }
if (!otherArchive) if (!otherArchive)
break; break;
@@ -328,7 +332,7 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
class CCabFolderOutStream: class CFolderOutStream:
public ISequentialOutStream, public ISequentialOutStream,
public CMyUnknownImp public CMyUnknownImp
{ {
@@ -339,6 +343,12 @@ public:
private: private:
const CMvDatabaseEx *m_Database; const CMvDatabaseEx *m_Database;
const CRecordVector<bool> *m_ExtractStatuses; const CRecordVector<bool> *m_ExtractStatuses;
CByteBuffer TempBuf;
bool TempBufMode;
bool IsSupported;
UInt32 m_BufStartFolderOffset;
int m_StartIndex; int m_StartIndex;
int m_CurrentIndex; int m_CurrentIndex;
CMyComPtr<IArchiveExtractCallback> m_ExtractCallback; CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
@@ -348,11 +358,12 @@ private:
bool m_IsOk; bool m_IsOk;
bool m_FileIsOpen; bool m_FileIsOpen;
UInt64 m_RemainFileSize; UInt32 m_RemainFileSize;
UInt64 m_FolderSize; UInt64 m_FolderSize;
UInt64 m_PosInFolder; UInt64 m_PosInFolder;
HRESULT OpenFile(); HRESULT OpenFile();
HRESULT CloseFile();
HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK); HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
public: public:
HRESULT WriteEmptyFiles(); HRESULT WriteEmptyFiles();
@@ -371,7 +382,7 @@ public:
UInt64 GetPosInFolder() const { return m_PosInFolder; } UInt64 GetPosInFolder() const { return m_PosInFolder; }
}; };
void CCabFolderOutStream::Init( void CFolderOutStream::Init(
const CMvDatabaseEx *database, const CMvDatabaseEx *database,
const CRecordVector<bool> *extractStatuses, const CRecordVector<bool> *extractStatuses,
int startIndex, int startIndex,
@@ -391,25 +402,66 @@ void CCabFolderOutStream::Init(
m_PosInFolder = 0; m_PosInFolder = 0;
m_FileIsOpen = false; m_FileIsOpen = false;
m_IsOk = true; m_IsOk = true;
TempBufMode = false;
} }
HRESULT CCabFolderOutStream::OpenFile() HRESULT CFolderOutStream::CloseFile()
{
m_RealOutStream.Release();
HRESULT res = m_ExtractCallback->SetOperationResult(m_IsOk ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kDataError);
m_FileIsOpen = false;
return res;
}
HRESULT CFolderOutStream::OpenFile()
{ {
Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ? Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?
NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract) : NExtract::NAskMode::kExtract) :
NExtract::NAskMode::kSkip; NExtract::NAskMode::kSkip;
if (!TempBufMode)
{
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
int curIndex = m_CurrentIndex + 1;
for (; curIndex < m_ExtractStatuses->Size(); curIndex++)
if ((*m_ExtractStatuses)[curIndex])
{
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
const CItem &item2 = m_Database->Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex];
if (item.Offset != item2.Offset ||
item.Size != item2.Size ||
item.Size == 0)
break;
}
if (curIndex > m_CurrentIndex + 1)
{
size_t oldCapacity = TempBuf.GetCapacity();
IsSupported = (item.Size <= kMaxTempBufSize);
if (item.Size > oldCapacity && IsSupported)
{
TempBuf.SetCapacity(0);
TempBuf.SetCapacity(item.Size);
}
TempBufMode = true;
m_BufStartFolderOffset = item.Offset;
}
}
RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));
if (!m_RealOutStream && !m_TestMode) if (!m_RealOutStream && !m_TestMode)
askMode = NArchive::NExtract::NAskMode::kSkip; askMode = NExtract::NAskMode::kSkip;
return m_ExtractCallback->PrepareOperation(askMode); return m_ExtractCallback->PrepareOperation(askMode);
} }
HRESULT CCabFolderOutStream::WriteEmptyFiles() HRESULT CFolderOutStream::WriteEmptyFiles()
{ {
if (m_FileIsOpen) if (m_FileIsOpen)
return S_OK; return S_OK;
for(;m_CurrentIndex < m_ExtractStatuses->Size(); m_CurrentIndex++) for (; m_CurrentIndex < m_ExtractStatuses->Size(); m_CurrentIndex++)
{ {
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
@@ -419,22 +471,23 @@ HRESULT CCabFolderOutStream::WriteEmptyFiles()
HRESULT result = OpenFile(); HRESULT result = OpenFile();
m_RealOutStream.Release(); m_RealOutStream.Release();
RINOK(result); RINOK(result);
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
} }
return S_OK; return S_OK;
} }
// This is Write function // This is Write function
HRESULT CCabFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK) HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
{ {
COM_TRY_BEGIN
UInt32 realProcessed = 0; UInt32 realProcessed = 0;
if (processedSize != NULL) if (processedSize != NULL)
*processedSize = 0; *processedSize = 0;
while(size != 0) while (size != 0)
{ {
if (m_FileIsOpen) if (m_FileIsOpen)
{ {
UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size)); UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size);
HRESULT res = S_OK; HRESULT res = S_OK;
if (numBytesToWrite > 0) if (numBytesToWrite > 0)
{ {
@@ -446,6 +499,8 @@ HRESULT CCabFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal); res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
numBytesToWrite = processedSizeLocal; numBytesToWrite = processedSizeLocal;
} }
if (TempBufMode && IsSupported)
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
} }
realProcessed += numBytesToWrite; realProcessed += numBytesToWrite;
if (processedSize != NULL) if (processedSize != NULL)
@@ -459,12 +514,38 @@ HRESULT CCabFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
if (m_RemainFileSize == 0) if (m_RemainFileSize == 0)
{ {
m_RealOutStream.Release(); m_RealOutStream.Release();
RINOK(m_ExtractCallback->SetOperationResult( RINOK(CloseFile());
m_IsOk ?
NArchive::NExtract::NOperationResult::kOK: if (TempBufMode)
NArchive::NExtract::NOperationResult::kDataError)); {
while (m_CurrentIndex < m_ExtractStatuses->Size())
{
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.Offset != m_BufStartFolderOffset)
break;
HRESULT result = OpenFile();
m_FileIsOpen = true;
m_CurrentIndex++;
m_IsOk = true;
if (result == S_OK && m_RealOutStream && IsSupported)
result = WriteStream(m_RealOutStream, TempBuf, item.Size);
if (IsSupported)
{
RINOK(CloseFile());
RINOK(result);
}
else
{
m_RealOutStream.Release();
RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
m_FileIsOpen = false; m_FileIsOpen = false;
} }
}
TempBufMode = false;
}
}
if (realProcessed > 0) if (realProcessed > 0)
break; // with this break this function works as Write-Part break; // with this break this function works as Write-Part
} }
@@ -483,7 +564,7 @@ HRESULT CCabFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
return E_FAIL; return E_FAIL;
if (fileOffset > m_PosInFolder) if (fileOffset > m_PosInFolder)
{ {
UInt32 numBytesToWrite = (UInt32)MyMin((UInt64)fileOffset - m_PosInFolder, UInt64(size)); UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);
realProcessed += numBytesToWrite; realProcessed += numBytesToWrite;
if (processedSize != NULL) if (processedSize != NULL)
*processedSize = realProcessed; *processedSize = realProcessed;
@@ -501,14 +582,15 @@ HRESULT CCabFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
} }
} }
return WriteEmptyFiles(); return WriteEmptyFiles();
COM_TRY_END
} }
STDMETHODIMP CCabFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ {
return Write2(data, size, processedSize, true); return Write2(data, size, processedSize, true);
} }
HRESULT CCabFolderOutStream::FlushCorrupted() HRESULT CFolderOutStream::FlushCorrupted()
{ {
const UInt32 kBufferSize = (1 << 10); const UInt32 kBufferSize = (1 << 10);
Byte buffer[kBufferSize]; Byte buffer[kBufferSize];
@@ -525,7 +607,7 @@ HRESULT CCabFolderOutStream::FlushCorrupted()
} }
} }
HRESULT CCabFolderOutStream::Unsupported() HRESULT CFolderOutStream::Unsupported()
{ {
while(m_CurrentIndex < m_ExtractStatuses->Size()) while(m_CurrentIndex < m_ExtractStatuses->Size())
{ {
@@ -533,23 +615,23 @@ HRESULT CCabFolderOutStream::Unsupported()
if (result != S_FALSE && result != S_OK) if (result != S_FALSE && result != S_OK)
return result; return result;
m_RealOutStream.Release(); m_RealOutStream.Release();
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
m_CurrentIndex++; m_CurrentIndex++;
} }
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)(-1)); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = m_Database.Items.Size(); numItems = m_Database.Items.Size();
if(numItems == 0) if(numItems == 0)
return S_OK; return S_OK;
bool testMode = (_aTestMode != 0); bool testMode = (testModeSpec != 0);
UInt64 totalUnPacked = 0; UInt64 totalUnPacked = 0;
UInt32 i; UInt32 i;
@@ -610,14 +692,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
i++; i++;
if (item.IsDir()) if (item.IsDir())
{ {
Int32 askMode= testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
int folderIndex = m_Database.GetFolderIndex(&mvItem); int folderIndex = m_Database.GetFolderIndex(&mvItem);
@@ -625,13 +707,13 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
{ {
// If we need previous archive // If we need previous archive
Int32 askMode= testMode ? Int32 askMode= testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
continue; continue;
} }
int startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; int startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
@@ -664,7 +746,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
lps->InSize = totalPacked; lps->InSize = totalPacked;
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CCabFolderOutStream *cabFolderOutStream = new CCabFolderOutStream; CFolderOutStream *cabFolderOutStream = new CFolderOutStream;
CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream); CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream);
const CFolder &folder = db.Folders[item.GetFolderIndex(db.Folders.Size())]; const CFolder &folder = db.Folders[item.GetFolderIndex(db.Folders.Size())];

View File

@@ -1,15 +1,15 @@
// Archive/Cab/Header.h // CabHeader.cpp
#include "StdAfx.h" #include "StdAfx.h"
#include "CabHeader.h" #include "CabHeader.h"
namespace NArchive{ namespace NArchive {
namespace NCab{ namespace NCab {
namespace NHeader{ namespace NHeader {
Byte kMarker[kMarkerSize] = {'M' + 1, 'S', 'C', 'F', 0, 0, 0, 0 }; Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
struct SignatureInitializer { SignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer; // struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer;
}}} }}}

View File

@@ -2,14 +2,14 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "CabIn.h"
#include "../Common/FindSignature.h" #include "../Common/FindSignature.h"
#include "CabIn.h"
namespace NArchive { namespace NArchive {
namespace NCab { namespace NCab {
Byte CInArchive::ReadByte() Byte CInArchive::Read8()
{ {
Byte b; Byte b;
if (!inBuffer.ReadByte(b)) if (!inBuffer.ReadByte(b))
@@ -17,23 +17,23 @@ Byte CInArchive::ReadByte()
return b; return b;
} }
UInt16 CInArchive::ReadUInt16() UInt16 CInArchive::Read16()
{ {
UInt16 value = 0; UInt16 value = 0;
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
Byte b = ReadByte(); Byte b = Read8();
value |= (UInt16(b) << (8 * i)); value |= (UInt16(b) << (8 * i));
} }
return value; return value;
} }
UInt32 CInArchive::ReadUInt32() UInt32 CInArchive::Read32()
{ {
UInt32 value = 0; UInt32 value = 0;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
Byte b = ReadByte(); Byte b = Read8();
value |= (UInt32(b) << (8 * i)); value |= (UInt32(b) << (8 * i));
} }
return value; return value;
@@ -44,7 +44,7 @@ AString CInArchive::SafeReadName()
AString name; AString name;
for (;;) for (;;)
{ {
Byte b = ReadByte(); Byte b = Read8();
if (b == 0) if (b == 0)
return name; return name;
name += (char)b; name += (char)b;
@@ -57,61 +57,60 @@ void CInArchive::ReadOtherArchive(COtherArchive &oa)
oa.DiskName = SafeReadName(); oa.DiskName = SafeReadName();
} }
void CInArchive::Skip(size_t size) void CInArchive::Skip(UInt32 size)
{ {
while (size-- != 0) while (size-- != 0)
ReadByte(); Read8();
} }
HRESULT CInArchive::Open2(IInStream *stream, HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db)
const UInt64 *searchHeaderSizeLimit,
CDatabase &database)
{ {
database.Clear(); IInStream *stream = db.Stream;
RINOK(stream->Seek(0, STREAM_SEEK_SET, &database.StartPosition)); db.Clear();
RINOK(stream->Seek(0, STREAM_SEEK_SET, &db.StartPosition));
RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize, RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
searchHeaderSizeLimit, database.StartPosition)); searchHeaderSizeLimit, db.StartPosition));
RINOK(stream->Seek(database.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL)); RINOK(stream->Seek(db.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL));
if (!inBuffer.Create(1 << 17)) if (!inBuffer.Create(1 << 17))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
inBuffer.SetStream(stream); inBuffer.SetStream(stream);
inBuffer.Init(); inBuffer.Init();
CInArchiveInfo &ai = database.ArchiveInfo; CInArchiveInfo &ai = db.ArchiveInfo;
ai.Size = ReadUInt32(); ai.Size = Read32();
if (ReadUInt32() != 0) if (Read32() != 0)
return S_FALSE; return S_FALSE;
ai.FileHeadersOffset = ReadUInt32(); ai.FileHeadersOffset = Read32();
if (ReadUInt32() != 0) if (Read32() != 0)
return S_FALSE; return S_FALSE;
ai.VersionMinor = ReadByte(); ai.VersionMinor = Read8();
ai.VersionMajor = ReadByte(); ai.VersionMajor = Read8();
ai.NumFolders = ReadUInt16(); ai.NumFolders = Read16();
ai.NumFiles = ReadUInt16(); ai.NumFiles = Read16();
ai.Flags = ReadUInt16(); ai.Flags = Read16();
if (ai.Flags > 7) if (ai.Flags > 7)
return S_FALSE; return S_FALSE;
ai.SetID = ReadUInt16(); ai.SetID = Read16();
ai.CabinetNumber = ReadUInt16(); ai.CabinetNumber = Read16();
if (ai.ReserveBlockPresent()) if (ai.ReserveBlockPresent())
{ {
ai.PerCabinetAreaSize = ReadUInt16(); ai.PerCabinetAreaSize = Read16();
ai.PerFolderAreaSize = ReadByte(); ai.PerFolderAreaSize = Read8();
ai.PerDataBlockAreaSize = ReadByte(); ai.PerDataBlockAreaSize = Read8();
Skip(ai.PerCabinetAreaSize); Skip(ai.PerCabinetAreaSize);
} }
{ {
if (ai.IsTherePrev()) if (ai.IsTherePrev())
ReadOtherArchive(ai.PreviousArchive); ReadOtherArchive(ai.PrevArc);
if (ai.IsThereNext()) if (ai.IsThereNext())
ReadOtherArchive(ai.NextArchive); ReadOtherArchive(ai.NextArc);
} }
int i; int i;
@@ -119,54 +118,40 @@ HRESULT CInArchive::Open2(IInStream *stream,
{ {
CFolder folder; CFolder folder;
folder.DataStart = ReadUInt32(); folder.DataStart = Read32();
folder.NumDataBlocks = ReadUInt16(); folder.NumDataBlocks = Read16();
folder.CompressionTypeMajor = ReadByte(); folder.CompressionTypeMajor = Read8();
folder.CompressionTypeMinor = ReadByte(); folder.CompressionTypeMinor = Read8();
Skip(ai.PerFolderAreaSize); Skip(ai.PerFolderAreaSize);
database.Folders.Add(folder); db.Folders.Add(folder);
} }
RINOK(stream->Seek(database.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL)); RINOK(stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));
inBuffer.SetStream(stream); inBuffer.SetStream(stream);
inBuffer.Init(); inBuffer.Init();
for (i = 0; i < ai.NumFiles; i++) for (i = 0; i < ai.NumFiles; i++)
{ {
CItem item; CItem item;
item.Size = ReadUInt32(); item.Size = Read32();
item.Offset = ReadUInt32(); item.Offset = Read32();
item.FolderIndex = ReadUInt16(); item.FolderIndex = Read16();
UInt16 pureDate = ReadUInt16(); UInt16 pureDate = Read16();
UInt16 pureTime = ReadUInt16(); UInt16 pureTime = Read16();
item.Time = ((UInt32(pureDate) << 16)) | pureTime; item.Time = ((UInt32(pureDate) << 16)) | pureTime;
item.Attributes = ReadUInt16(); item.Attributes = Read16();
item.Name = SafeReadName(); item.Name = SafeReadName();
int folderIndex = item.GetFolderIndex(database.Folders.Size()); int folderIndex = item.GetFolderIndex(db.Folders.Size());
if (folderIndex >= database.Folders.Size()) if (folderIndex >= db.Folders.Size())
return S_FALSE; return S_FALSE;
database.Items.Add(item); db.Items.Add(item);
} }
return S_OK; return S_OK;
} }
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
HRESULT CInArchive::Open(
const UInt64 *searchHeaderSizeLimit,
CDatabaseEx &database)
{
return Open2(database.Stream, searchHeaderSizeLimit, database);
}
static int CompareMvItems2(const CMvItem *p1, const CMvItem *p2)
{
RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));
return MyCompare(p1->ItemIndex, p2->ItemIndex);
}
static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
{ {
const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param; const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;
@@ -185,7 +170,8 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
RINOZ(MyCompare(f1, f2)); RINOZ(MyCompare(f1, f2));
RINOZ(MyCompare(item1.Offset, item2.Offset)); RINOZ(MyCompare(item1.Offset, item2.Offset));
RINOZ(MyCompare(item1.Size, item2.Size)); RINOZ(MyCompare(item1.Size, item2.Size));
return CompareMvItems2(p1, p2); RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));
return MyCompare(p1->ItemIndex, p2->ItemIndex);
} }
bool CMvDatabaseEx::AreItemsEqual(int i1, int i2) bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
@@ -236,8 +222,7 @@ void CMvDatabaseEx::FillSortAndShrink()
for (i = 0; i < Items.Size(); i++) for (i = 0; i < Items.Size(); i++)
{ {
const CMvItem &mvItem = Items[i]; int folderIndex = GetFolderIndex(&Items[i]);
int folderIndex = GetFolderIndex(&mvItem);
if (folderIndex >= FolderStartFileIndex.Size()) if (folderIndex >= FolderStartFileIndex.Size())
FolderStartFileIndex.Add(i); FolderStartFileIndex.Add(i);
} }
@@ -260,7 +245,8 @@ bool CMvDatabaseEx::Check()
return false; return false;
} }
} }
UInt64 maxPos = 0; UInt32 beginPos = 0;
UInt64 endPos = 0;
int prevFolder = -2; int prevFolder = -2;
for (int i = 0; i < Items.Size(); i++) for (int i = 0; i < Items.Size(); i++)
{ {
@@ -273,16 +259,12 @@ bool CMvDatabaseEx::Check()
continue; continue;
int folderIndex = GetFolderIndex(&mvItem); int folderIndex = GetFolderIndex(&mvItem);
if (folderIndex != prevFolder) if (folderIndex != prevFolder)
{
prevFolder = folderIndex; prevFolder = folderIndex;
maxPos = 0; else if (item.Offset < endPos &&
continue; (item.Offset != beginPos || item.GetEndOffset() != endPos))
}
if (item.Offset < maxPos)
return false;
maxPos = item.GetEndOffset();
if (maxPos < item.Offset)
return false; return false;
beginPos = item.Offset;
endPos = item.GetEndOffset();
} }
return true; return true;
} }

View File

@@ -50,8 +50,8 @@ struct CArchiveInfo
Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); } Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); }
COtherArchive PreviousArchive; COtherArchive PrevArc;
COtherArchive NextArchive; COtherArchive NextArc;
CArchiveInfo() CArchiveInfo()
{ {
@@ -73,13 +73,13 @@ struct CInArchiveInfo: public CArchiveInfo
}; };
class CDatabase struct CDatabase
{ {
public:
UInt64 StartPosition; UInt64 StartPosition;
CInArchiveInfo ArchiveInfo; CInArchiveInfo ArchiveInfo;
CObjectVector<CFolder> Folders; CObjectVector<CFolder> Folders;
CObjectVector<CItem> Items; CObjectVector<CItem> Items;
void Clear() void Clear()
{ {
ArchiveInfo.Clear(); ArchiveInfo.Clear();
@@ -104,9 +104,8 @@ public:
UInt32 GetFileSize(int index) const { return Items[index].Size; } UInt32 GetFileSize(int index) const { return Items[index].Size; }
}; };
class CDatabaseEx: public CDatabase struct CDatabaseEx: public CDatabase
{ {
public:
CMyComPtr<IInStream> Stream; CMyComPtr<IInStream> Stream;
}; };
@@ -124,6 +123,7 @@ public:
CRecordVector<CMvItem> Items; CRecordVector<CMvItem> Items;
CRecordVector<int> StartFolderOfVol; CRecordVector<int> StartFolderOfVol;
CRecordVector<int> FolderStartFileIndex; CRecordVector<int> FolderStartFileIndex;
int GetFolderIndex(const CMvItem *mvi) const int GetFolderIndex(const CMvItem *mvi) const
{ {
const CDatabaseEx &db = Volumes[mvi->VolumeIndex]; const CDatabaseEx &db = Volumes[mvi->VolumeIndex];
@@ -145,20 +145,15 @@ class CInArchive
{ {
CInBuffer inBuffer; CInBuffer inBuffer;
Byte ReadByte(); Byte Read8();
UInt16 ReadUInt16(); UInt16 Read16();
UInt32 ReadUInt32(); UInt32 Read32();
AString SafeReadName(); AString SafeReadName();
void Skip(size_t size); void Skip(UInt32 size);
void ReadOtherArchive(COtherArchive &oa); void ReadOtherArchive(COtherArchive &oa);
HRESULT Open2(IInStream *inStream,
const UInt64 *searchHeaderSizeLimit,
CDatabase &database);
public: public:
HRESULT Open( HRESULT Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db);
const UInt64 *searchHeaderSizeLimit,
CDatabaseEx &database);
}; };
}} }}

View File

@@ -275,7 +275,7 @@ HRESULT CChmFolderOutStream::OpenFile()
m_RealOutStream.Release(); m_RealOutStream.Release();
RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));
if (!m_RealOutStream && !m_TestMode) if (!m_RealOutStream && !m_TestMode)
askMode = NArchive::NExtract::NAskMode::kSkip; askMode = NExtract::NAskMode::kSkip;
return m_ExtractCallback->PrepareOperation(askMode); return m_ExtractCallback->PrepareOperation(askMode);
} }
@@ -291,7 +291,7 @@ HRESULT CChmFolderOutStream::WriteEmptyFiles()
HRESULT result = OpenFile(); HRESULT result = OpenFile();
m_RealOutStream.Release(); m_RealOutStream.Release();
RINOK(result); RINOK(result);
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
} }
return S_OK; return S_OK;
} }
@@ -334,8 +334,8 @@ HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
m_RealOutStream.Release(); m_RealOutStream.Release();
RINOK(m_ExtractCallback->SetOperationResult( RINOK(m_ExtractCallback->SetOperationResult(
m_IsOk ? m_IsOk ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
m_FileIsOpen = false; m_FileIsOpen = false;
} }
if (realProcessed > 0) if (realProcessed > 0)
@@ -398,11 +398,11 @@ HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool allFilesMode = (numItems == UInt32(-1)); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = m_Database.NewFormat ? 1: numItems = m_Database.NewFormat ? 1:
@@ -411,7 +411,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
m_Database.Indices.Size()); m_Database.Indices.Size());
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
bool testMode = (_aTestMode != 0); bool testMode = (testModeSpec != 0);
UInt64 currentTotalSize = 0; UInt64 currentTotalSize = 0;
@@ -447,8 +447,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode= testMode ? Int32 askMode= testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
@@ -456,32 +456,32 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
{ {
if (index != 0) if (index != 0)
return E_FAIL; return E_FAIL;
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
if (!testMode) if (!testMode)
{ {
UInt32 size = m_Database.NewFormatString.Length(); UInt32 size = m_Database.NewFormatString.Length();
RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size)); RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size));
} }
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
const CItem &item = m_Database.Items[index]; const CItem &item = m_Database.Items[index];
currentItemSize = item.Size; currentItemSize = item.Size;
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
if (item.Section != 0) if (item.Section != 0)
{ {
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
continue; continue;
} }
if (testMode) if (testMode)
{ {
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
@@ -491,8 +491,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
} }
@@ -543,15 +543,15 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
const CItem &item = m_Database.Items[entryIndex]; const CItem &item = m_Database.Items[entryIndex];
UInt64 sectionIndex = item.Section; UInt64 sectionIndex = item.Section;
Int32 askMode= testMode ? Int32 askMode= testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
if (item.IsDir()) if (item.IsDir())
{ {
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
@@ -562,17 +562,17 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
{ {
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
Int32 opRes = NArchive::NExtract::NOperationResult::kOK; Int32 opRes = NExtract::NOperationResult::kOK;
if (!testMode && item.Size != 0) if (!testMode && item.Size != 0)
{ {
RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL)); RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
streamSpec->Init(item.Size); streamSpec->Init(item.Size);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != item.Size) if (copyCoderSpec->TotalSize != item.Size)
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
} }
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult(opRes)); RINOK(extractCallback->SetOperationResult(opRes));
@@ -586,10 +586,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
{ {
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if(!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
continue; continue;
} }
@@ -603,7 +603,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
chmFolderOutStream->Init(&m_Database, extractCallback, testMode); chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
if(lzxDecoderSpec == NULL) if (lzxDecoderSpec == NULL)
{ {
lzxDecoderSpec = new NCompress::NLzx::CDecoder; lzxDecoderSpec = new NCompress::NLzx::CDecoder;
lzxDecoder = lzxDecoderSpec; lzxDecoder = lzxDecoderSpec;

View File

@@ -95,12 +95,11 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _db.Refs.Size(); numItems = _db.Refs.Size();
if (numItems == 0) if (numItems == 0)
@@ -135,30 +134,30 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
CMyComPtr<ISequentialOutStream> outStream; CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(index, &outStream, askMode)); RINOK(extractCallback->GetStream(index, &outStream, askMode));
if (item.IsDir()) if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
totalPackSize += _db.GetItemPackSize(item.Size); totalPackSize += _db.GetItemPackSize(item.Size);
totalSize += item.Size; totalSize += item.Size;
if (!testMode && (!outStream)) if (!testMode && !outStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
Int32 res = NArchive::NExtract::NOperationResult::kDataError; Int32 res = NExtract::NOperationResult::kDataError;
CMyComPtr<ISequentialInStream> inStream; CMyComPtr<ISequentialInStream> inStream;
HRESULT hres = GetStream(index, &inStream); HRESULT hres = GetStream(index, &inStream);
if (hres == S_FALSE) if (hres == S_FALSE)
res = NArchive::NExtract::NOperationResult::kDataError; res = NExtract::NOperationResult::kDataError;
else if (hres == E_NOTIMPL) else if (hres == E_NOTIMPL)
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; res = NExtract::NOperationResult::kUnSupportedMethod;
else else
{ {
RINOK(hres); RINOK(hres);
@@ -166,7 +165,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
{ {
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize == item.Size) if (copyCoderSpec->TotalSize == item.Size)
res = NArchive::NExtract::NOperationResult::kOK; res = NExtract::NOperationResult::kOK;
} }
} }
outStream.Release(); outStream.Release();

View File

@@ -8,6 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NCom::CHandler; } static IInArchive *CreateArc() { return new NArchive::NCom::CHandler; }
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"Compound", L"msi doc xls ppt", 0, 0xE5, { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }, 8, false, CreateArc, 0 }; { L"Compound", L"msi msp doc xls ppt", 0, 0xE5, { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }, 8, false, CreateArc, 0 };
REGISTER_ARC(Com) REGISTER_ARC(Com)

View File

@@ -39,7 +39,7 @@ bool HasTailSlash(const AString &name, UINT codePage)
if (name.IsEmpty()) if (name.IsEmpty())
return false; return false;
LPCSTR prev = LPCSTR prev =
#ifdef _WIN32 #if defined(_WIN32) && !defined(UNDER_CE)
CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);
#else #else
(LPCSTR)(name) + (name.Length() - 1); (LPCSTR)(name) + (name.Length() - 1);

View File

@@ -540,12 +540,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _items.Size(); numItems = _items.Size();
if (numItems == 0) if (numItems == 0)
@@ -575,8 +574,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> outStream; CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
const CItemEx &item = _items[index]; const CItemEx &item = _items[index];
RINOK(extractCallback->GetStream(index, &outStream, askMode)); RINOK(extractCallback->GetStream(index, &outStream, askMode));
@@ -584,7 +583,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (item.IsDir()) if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
if (!testMode && !outStream) if (!testMode && !outStream)
@@ -592,7 +591,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
if (testMode) if (testMode)
{ {
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
@@ -600,8 +599,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View File

@@ -236,7 +236,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
COM_TRY_BEGIN COM_TRY_BEGIN
{ {
CInArchive archive; CInArchive archive;
if(archive.Open(stream) != S_OK) if (archive.Open(stream) != S_OK)
return S_FALSE; return S_FALSE;
_items.Clear(); _items.Clear();
@@ -314,12 +314,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _items.Size(); numItems = _items.Size();
if (numItems == 0) if (numItems == 0)
@@ -349,19 +348,19 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index]; const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
currentTotalSize += item.Size; currentTotalSize += item.Size;
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
if (testMode) if (testMode)
{ {
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));
@@ -369,8 +368,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

118
CPP/7zip/Archive/DeflateProps.cpp Executable file
View File

@@ -0,0 +1,118 @@
// DeflateProps.cpp
#include "StdAfx.h"
#include "Windows/PropVariant.h"
#include "Common/ParseProperties.h"
#include "DeflateProps.h"
namespace NArchive {
static const UInt32 kAlgo1 = 0;
static const UInt32 kAlgo5 = 1;
static const UInt32 kPasses1 = 1;
static const UInt32 kPasses7 = 3;
static const UInt32 kPasses9 = 10;
static const UInt32 kFb1 = 32;
static const UInt32 kFb7 = 64;
static const UInt32 kFb9 = 128;
void CDeflateProps::Normalize()
{
UInt32 level = Level;
if (level == 0xFFFFFFFF)
level = 5;
if (Algo == 0xFFFFFFFF)
Algo = (level >= 5 ?
kAlgo5 :
kAlgo1);
if (NumPasses == 0xFFFFFFFF)
NumPasses =
(level >= 9 ? kPasses9 :
(level >= 7 ? kPasses7 :
kPasses1));
if (Fb == 0xFFFFFFFF)
Fb =
(level >= 9 ? kFb9 :
(level >= 7 ? kFb7 :
kFb1));
}
HRESULT CDeflateProps::SetCoderProperties(ICompressSetCoderProperties *setCoderProperties)
{
Normalize();
NWindows::NCOM::CPropVariant props[] =
{
Algo,
NumPasses,
Fb,
Mc
};
PROPID propIDs[] =
{
NCoderPropID::kAlgorithm,
NCoderPropID::kNumPasses,
NCoderPropID::kNumFastBytes,
NCoderPropID::kMatchFinderCycles
};
int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
if (!McDefined)
numProps--;
return setCoderProperties->SetCoderProperties(propIDs, props, numProps);
}
HRESULT CDeflateProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
Init();
for (int i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &prop = values[i];
if (name[0] == L'X')
{
UInt32 a = 9;
RINOK(ParsePropValue(name.Mid(1), prop, a));
Level = a;
}
else if (name.Left(1) == L"A")
{
UInt32 a = kAlgo5;
RINOK(ParsePropValue(name.Mid(1), prop, a));
Algo = a;
}
else if (name.Left(4) == L"PASS")
{
UInt32 a = kPasses9;
RINOK(ParsePropValue(name.Mid(4), prop, a));
NumPasses = a;
}
else if (name.Left(2) == L"FB")
{
UInt32 a = kFb9;
RINOK(ParsePropValue(name.Mid(2), prop, a));
Fb = a;
}
else if (name.Left(2) == L"MC")
{
UInt32 a = 0xFFFFFFFF;
RINOK(ParsePropValue(name.Mid(2), prop, a));
Mc = a;
McDefined = true;
}
else
return E_INVALIDARG;
}
return S_OK;
}
}

35
CPP/7zip/Archive/DeflateProps.h Executable file
View File

@@ -0,0 +1,35 @@
// DeflateProps.h
#ifndef __DEFLATE_PROPS_H
#define __DEFLATE_PROPS_H
#include "../ICoder.h"
namespace NArchive {
class CDeflateProps
{
UInt32 Level;
UInt32 NumPasses;
UInt32 Fb;
UInt32 Algo;
UInt32 Mc;
bool McDefined;
void Init()
{
Level = NumPasses = Fb = Algo = Mc = 0xFFFFFFFF;
McDefined = false;
}
void Normalize();
public:
CDeflateProps() { Init(); }
bool IsMaximum() const { return Algo > 0; }
HRESULT SetCoderProperties(ICompressSetCoderProperties *setCoderProperties);
HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
};
}
#endif

View File

@@ -5,6 +5,8 @@
#include "../../Common/MyInitGuid.h" #include "../../Common/MyInitGuid.h"
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/Types.h" #include "../../Common/Types.h"
#include "../../Windows/NtCheck.h"
#include "../../Windows/PropVariant.h" #include "../../Windows/PropVariant.h"
#include "IArchive.h" #include "IArchive.h"
@@ -12,17 +14,8 @@
#include "../IPassword.h" #include "../IPassword.h"
HINSTANCE g_hInstance; HINSTANCE g_hInstance;
#ifndef _UNICODE
bool g_IsNT = false; #define NT_CHECK_FAIL_ACTION return FALSE;
static bool IsItWindowsNT()
{
OSVERSIONINFO versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
if (!::GetVersionEx(&versionInfo))
return false;
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
#endif
extern "C" extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
@@ -30,9 +23,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
if (dwReason == DLL_PROCESS_ATTACH) if (dwReason == DLL_PROCESS_ATTACH)
{ {
g_hInstance = hInstance; g_hInstance = hInstance;
#ifndef _UNICODE NT_CHECK;
g_IsNT = IsItWindowsNT();
#endif
} }
return TRUE; return TRUE;
} }

View File

@@ -3,43 +3,38 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../Common/MyInitGuid.h" #include "../../Common/MyInitGuid.h"
#include "../../Common/ComTry.h"
#include "../../Common/Types.h"
#include "../../Windows/PropVariant.h"
#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
#include "../../../C/Alloc.h" #include "../../../C/Alloc.h"
#endif #endif
#include "IArchive.h" #include "../../Common/ComTry.h"
#include "../../Windows/NtCheck.h"
#include "../../Windows/PropVariant.h"
#include "../ICoder.h" #include "../ICoder.h"
#include "../IPassword.h" #include "../IPassword.h"
#include "IArchive.h"
HINSTANCE g_hInstance; HINSTANCE g_hInstance;
#ifndef _UNICODE
#ifdef _WIN32 #define NT_CHECK_FAIL_ACTION return FALSE;
bool g_IsNT = false;
static bool IsItWindowsNT()
{
OSVERSIONINFO versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
if (!::GetVersionEx(&versionInfo))
return false;
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
#endif
#endif
extern "C" extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) BOOL WINAPI DllMain(
#ifdef UNDER_CE
HANDLE
#else
HINSTANCE
#endif
hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{ {
if (dwReason == DLL_PROCESS_ATTACH) if (dwReason == DLL_PROCESS_ATTACH)
{ {
g_hInstance = hInstance; g_hInstance = (HINSTANCE)hInstance;
#ifndef _UNICODE NT_CHECK;
#ifdef _WIN32
g_IsNT = IsItWindowsNT();
#endif
#endif
} }
return TRUE; return TRUE;
} }

View File

@@ -573,12 +573,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _files.Size(); numItems = _files.Size();
if (numItems == 0) if (numItems == 0)
@@ -635,14 +634,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
// const CItemEx &item = _files[index]; // const CItemEx &item = _files[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -652,7 +651,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
realOutStream.Release(); realOutStream.Release();
Int32 opRes = NArchive::NExtract::NOperationResult::kOK; Int32 opRes = NExtract::NOperationResult::kOK;
#ifdef DMG_SHOW_RAW #ifdef DMG_SHOW_RAW
if (index > _fileIndices.Size()) if (index > _fileIndices.Size())
{ {
@@ -688,7 +687,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
packPos += block.PackSize; packPos += block.PackSize;
if (block.UnpPos != unpPos) if (block.UnpPos != unpPos)
{ {
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
break; break;
} }
@@ -705,13 +704,13 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
case METHOD_ZERO_2: case METHOD_ZERO_2:
realMethod = false; realMethod = false;
if (block.PackSize != 0) if (block.PackSize != 0)
opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; opRes = NExtract::NOperationResult::kUnSupportedMethod;
break; break;
case METHOD_COPY: case METHOD_COPY:
if (block.UnpSize != block.PackSize) if (block.UnpSize != block.PackSize)
{ {
opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; opRes = NExtract::NOperationResult::kUnSupportedMethod;
break; break;
} }
res = copyCoder->Code(inStream, outStream, NULL, NULL, progress); res = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
@@ -730,26 +729,26 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
res = bzip2Coder->Code(inStream, outStream, NULL, NULL, progress); res = bzip2Coder->Code(inStream, outStream, NULL, NULL, progress);
if (res == S_OK) if (res == S_OK)
if (streamSpec->GetSize() != block.PackSize) if (streamSpec->GetSize() != block.PackSize)
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
break; break;
} }
default: default:
opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; opRes = NExtract::NOperationResult::kUnSupportedMethod;
break; break;
} }
if (res != S_OK) if (res != S_OK)
{ {
if (res != S_FALSE) if (res != S_FALSE)
return res; return res;
if (opRes == NArchive::NExtract::NOperationResult::kOK) if (opRes == NExtract::NOperationResult::kOK)
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
} }
unpPos += block.UnpSize; unpPos += block.UnpSize;
if (!outStreamSpec->IsFinishedOK()) if (!outStreamSpec->IsFinishedOK())
{ {
if (realMethod && opRes == NArchive::NExtract::NOperationResult::kOK) if (realMethod && opRes == NExtract::NOperationResult::kOK)
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
while (outStreamSpec->GetRem() != 0) while (outStreamSpec->GetRem() != 0)
{ {

View File

@@ -466,12 +466,11 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _sections.Size(); numItems = _sections.Size();
if (numItems == 0) if (numItems == 0)
@@ -501,8 +500,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
lps->InSize = lps->OutSize = currentTotalSize; lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur()); RINOK(lps->SetCur());
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
const CSegment &item = _sections[index]; const CSegment &item = _sections[index];
currentItemSize = item.PSize; currentItemSize = item.PSize;
@@ -518,8 +517,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View File

@@ -456,8 +456,11 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
const Byte *p = ByteBuf + pos; const Byte *p = ByteBuf + pos;
if (p[0] == 0) if (p[0] == 0)
{ {
/*
// FreeDOS formats FAT partition with cluster chain longer than required.
if (clusterMode && !Header.IsEoc(cluster)) if (clusterMode && !Header.IsEoc(cluster))
return S_FALSE; return S_FALSE;
*/
break; break;
} }
if (p[0] == 0xE5) if (p[0] == 0xE5)
@@ -883,12 +886,11 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = Items.Size(); numItems = Items.Size();
if (numItems == 0) if (numItems == 0)
@@ -923,8 +925,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
const CItem &item = Items[index]; const CItem &item = Items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
@@ -932,14 +934,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (item.IsDir()) if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
totalPackSize += Header.GetFilePackSize(item.Size); totalPackSize += Header.GetFilePackSize(item.Size);
totalSize += item.Size; totalSize += item.Size;
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -947,7 +949,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
realOutStream.Release(); realOutStream.Release();
outStreamSpec->Init(); outStreamSpec->Init();
int res = NArchive::NExtract::NOperationResult::kDataError; int res = NExtract::NOperationResult::kDataError;
CMyComPtr<ISequentialInStream> inStream; CMyComPtr<ISequentialInStream> inStream;
HRESULT hres = GetStream(index, &inStream); HRESULT hres = GetStream(index, &inStream);
if (hres != S_FALSE) if (hres != S_FALSE)
@@ -957,7 +959,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
{ {
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize == item.Size) if (copyCoderSpec->TotalSize == item.Size)
res = NArchive::NExtract::NOperationResult::kOK; res = NExtract::NOperationResult::kOK;
} }
} }
outStreamSpec->ReleaseStream(); outStreamSpec->ReleaseStream();

544
CPP/7zip/Archive/FlvHandler.cpp Executable file
View File

@@ -0,0 +1,544 @@
// FlvHandler.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "Common/Buffer.h"
#include "Common/ComTry.h"
// #include "Common/Defs.h"
#include "Common/MyString.h"
#include "Windows/PropVariant.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
#define GetBe24(p) ( \
((UInt32)((const Byte *)(p))[0] << 16) | \
((UInt32)((const Byte *)(p))[1] << 8) | \
((const Byte *)(p))[2] )
#define Get16(p) GetBe16(p)
#define Get24(p) GetBe24(p)
#define Get32(p) GetBe32(p)
namespace NArchive {
namespace NFlv {
static const UInt32 kFileSizeMax = (UInt32)1 << 30;
static const int kNumChunksMax = (UInt32)1 << 23;
const UInt32 kTagHeaderSize = 11;
static const Byte kFlag_Video = 1;
static const Byte kFlag_Audio = 4;
static const Byte kType_Audio = 8;
static const Byte kType_Video = 9;
static const Byte kType_Meta = 18;
static const int kNumTypes = 19;
struct CItem
{
UInt32 Offset;
UInt32 Size;
// UInt32 Time;
Byte Type;
};
struct CItem2
{
Byte Type;
Byte SubType;
Byte Props;
bool SameSubTypes;
int NumChunks;
size_t Size;
CReferenceBuf *BufSpec;
CMyComPtr<IUnknown> RefBuf;
bool IsAudio() const { return Type == kType_Audio; }
};
class CHandler:
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{
int _isRaw;
CMyComPtr<IInStream> _stream;
CObjectVector<CItem2> _items2;
// CByteBuffer _metadata;
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
AString GetComment();
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
STATPROPSTG kProps[] =
{
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidNumBlocks, VT_UI4},
{ NULL, kpidComment, VT_BSTR}
};
/*
STATPROPSTG kArcProps[] =
{
{ NULL, kpidComment, VT_BSTR}
};
*/
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO
static const char *g_AudioTypes[16] =
{
"pcm",
"adpcm",
"mp3",
"pcm_le",
"nellymoser16",
"nellymoser8",
"nellymoser",
"g711a",
"g711m",
"audio9",
"aac",
"speex",
"audio12",
"audio13",
"mp3",
"audio15"
};
static const char *g_VideoTypes[16] =
{
"video0",
"jpeg",
"h263",
"screen",
"vp6",
"vp6alpha",
"screen2",
"avc",
"video8",
"video9",
"video10",
"video11",
"video12",
"video13",
"video14",
"video15"
};
static const char *g_Rates[4] =
{
"5.5 kHz",
"11 kHz",
"22 kHz",
"44 kHz"
};
static void MyStrCat(char *d, const char *s)
{
MyStringCopy(d + MyStringLen(d), s);
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
const CItem2 &item = _items2[index];
switch(propID)
{
case kpidExtension:
prop = _isRaw ?
(item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) :
(item.IsAudio() ? "audio.flv" : "video.flv");
break;
case kpidSize:
case kpidPackSize:
prop = (UInt64)item.Size;
break;
case kpidNumBlocks: prop = (UInt32)item.NumChunks; break;
case kpidComment:
{
char sz[64];
MyStringCopy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) );
if (item.IsAudio())
{
MyStrCat(sz, " ");
MyStrCat(sz, g_Rates[(item.Props >> 2) & 3]);
MyStrCat(sz, (item.Props & 2) ? " 16-bit" : " 8-bit");
MyStrCat(sz, (item.Props & 1) ? " stereo" : " mono");
}
prop = sz;
break;
}
}
prop.Detach(value);
return S_OK;
}
/*
AString CHandler::GetComment()
{
const Byte *p = _metadata;
size_t size = _metadata.GetCapacity();
AString res;
if (size > 0)
{
p++;
size--;
for (;;)
{
if (size < 2)
break;
int len = Get16(p);
p += 2;
size -= 2;
if (len == 0 || (size_t)len > size)
break;
{
AString temp;
char *sz = temp.GetBuffer(len);
memcpy(sz, p, len);
sz[len] = 0;
temp.ReleaseBuffer();
if (!res.IsEmpty())
res += '\n';
res += temp;
}
p += len;
size -= len;
if (size < 1)
break;
Byte type = *p++;
size--;
bool ok = false;
switch(type)
{
case 0:
{
if (size < 8)
break;
ok = true;
Byte reverse[8];
for (int i = 0; i < 8; i++)
{
bool little_endian = 1;
if (little_endian)
reverse[i] = p[7 - i];
else
reverse[i] = p[i];
}
double d = *(double *)reverse;
char temp[32];
sprintf(temp, " = %.3f", d);
res += temp;
p += 8;
size -= 8;
break;
}
case 8:
{
if (size < 4)
break;
ok = true;
// UInt32 numItems = Get32(p);
p += 4;
size -= 4;
break;
}
}
if (!ok)
break;
}
}
return res;
}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidComment: prop = GetComment(); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
*/
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{
CRecordVector<CItem> items;
const UInt32 kHeaderSize = 13;
Byte header[kHeaderSize];
RINOK(ReadStream_FALSE(stream, header, kHeaderSize));
if (header[0] != 'F' ||
header[1] != 'L' ||
header[2] != 'V' ||
header[3] != 1 ||
(header[4] & 0xFA) != 0)
return S_FALSE;
UInt32 offset = Get32(header + 5);
if (offset != 9 || Get32(header + 9) != 0)
return S_FALSE;
offset += 4;
CByteBuffer inBuf;
size_t fileSize;
{
UInt64 fileSize64;
RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize64));
if (fileSize64 > kFileSizeMax)
return S_FALSE;
if (callback)
RINOK(callback->SetTotal(NULL, &fileSize64))
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
fileSize = (size_t)fileSize64;
inBuf.SetCapacity(fileSize);
for (size_t pos = 0; pos < fileSize;)
{
UInt64 offset64 = pos;
if (callback)
RINOK(callback->SetCompleted(NULL, &offset64))
size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20));
RINOK(ReadStream_FALSE(stream, inBuf + pos, rem));
pos += rem;
}
}
int lasts[kNumTypes];
int i;
for (i = 0; i < kNumTypes; i++)
lasts[i] = -1;
while (offset < fileSize)
{
CItem item;
item.Offset = offset;
const Byte *buf = inBuf + offset;
offset += kTagHeaderSize;
if (offset > fileSize)
return S_FALSE;
item.Type = buf[0];
UInt32 size = Get24(buf + 1);
if (size < 1)
return S_FALSE;
// item.Time = Get24(buf + 4);
// item.Time |= (UInt32)buf[7] << 24;
if (Get24(buf + 8) != 0) // streamID
return S_FALSE;
UInt32 curSize = kTagHeaderSize + size + 4;
item.Size = curSize;
offset += curSize - kTagHeaderSize;
if (offset > fileSize)
return S_FALSE;
if (Get32(buf + kTagHeaderSize + size) != kTagHeaderSize + size)
return S_FALSE;
// printf("\noffset = %6X type = %2d time = %6d size = %6d", (UInt32)offset, item.Type, item.Time, item.Size);
if (item.Type == kType_Meta)
{
// _metadata = item.Buf;
}
else
{
if (item.Type != kType_Audio && item.Type != kType_Video)
return S_FALSE;
if (items.Size() >= kNumChunksMax)
return S_FALSE;
Byte firstByte = buf[kTagHeaderSize];
Byte subType, props;
if (item.Type == kType_Audio)
{
subType = firstByte >> 4;
props = firstByte & 0xF;
}
else
{
subType = firstByte & 0xF;
props = firstByte >> 4;
}
int last = lasts[item.Type];
if (last < 0)
{
CItem2 item2;
item2.RefBuf = item2.BufSpec = new CReferenceBuf;
item2.Size = curSize;
item2.Type = item.Type;
item2.SubType = subType;
item2.Props = props;
item2.NumChunks = 1;
item2.SameSubTypes = true;
lasts[item.Type] = _items2.Add(item2);
}
else
{
CItem2 &item2 = _items2[last];
if (subType != item2.SubType)
item2.SameSubTypes = false;
item2.Size += curSize;
item2.NumChunks++;
}
items.Add(item);
}
}
_isRaw = (_items2.Size() == 1);
for (i = 0; i < _items2.Size(); i++)
{
CItem2 &item2 = _items2[i];
CByteBuffer &itemBuf = item2.BufSpec->Buf;
if (_isRaw)
{
if (!item2.SameSubTypes)
return S_FALSE;
itemBuf.SetCapacity((size_t)item2.Size - (kTagHeaderSize + 4 + 1) * item2.NumChunks);
item2.Size = 0;
}
else
{
itemBuf.SetCapacity(kHeaderSize + (size_t)item2.Size);
memcpy(itemBuf, header, kHeaderSize);
itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video;
item2.Size = kHeaderSize;
}
}
for (i = 0; i < items.Size(); i++)
{
const CItem &item = items[i];
CItem2 &item2 = _items2[lasts[item.Type]];
size_t size = item.Size;
const Byte *src = inBuf + item.Offset;
if (_isRaw)
{
src += kTagHeaderSize + 1;
size -= (kTagHeaderSize + 4 + 1);
}
memcpy(item2.BufSpec->Buf + item2.Size, src, size);
item2.Size += size;
}
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
{
COM_TRY_BEGIN
Close();
HRESULT res;
try
{
res = Open2(inStream, callback);
if (res == S_OK)
_stream = inStream;
}
catch(...) { res = S_FALSE; }
if (res != S_OK)
{
Close();
return S_FALSE;
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_stream.Release();
_items2.Clear();
// _metadata.SetCapacity(0);
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _items2.Size();
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
numItems = _items2.Size();
if (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
totalSize += _items2[allFilesMode ? i : indices[i]].Size;
extractCallback->SetTotal(totalSize);
totalSize = 0;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
for (i = 0; i < numItems; i++)
{
lps->InSize = lps->OutSize = totalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i];
const CItem2 &item = _items2[index];
RINOK(extractCallback->GetStream(index, &outStream, askMode));
totalSize += item.Size;
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (outStream)
{
RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.GetCapacity()));
}
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
*stream = 0;
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
streamSpec->Init(_items2[index].BufSpec);
*stream = streamTemp.Detach();
return S_OK;
COM_TRY_END
}
static IInArchive *CreateArc() { return new CHandler; }
static CArcInfo g_ArcInfo =
{ L"FLV", L"flv", 0, 0xD6, { 'F', 'L', 'V' }, 3, false, CreateArc, 0 };
REGISTER_ARC(Flv)
}}

View File

@@ -20,7 +20,8 @@
#include "Common/InStreamWithCRC.h" #include "Common/InStreamWithCRC.h"
#include "Common/OutStreamWithCRC.h" #include "Common/OutStreamWithCRC.h"
#include "Common/ParseProperties.h"
#include "DeflateProps.h"
#define Get32(p) GetUi32(p) #define Get32(p) GetUi32(p)
@@ -288,54 +289,6 @@ HRESULT CItem::WriteFooter(ISequentialOutStream *stream)
return WriteStream(stream, buf, 8); return WriteStream(stream, buf, 8);
} }
static const UInt32 kAlgoX1 = 0;
static const UInt32 kAlgoX5 = 1;
static const UInt32 kNumPassesX1 = 1;
static const UInt32 kNumPassesX7 = 3;
static const UInt32 kNumPassesX9 = 10;
static const UInt32 kNumFastBytesX1 = 32;
static const UInt32 kNumFastBytesX7 = 64;
static const UInt32 kNumFastBytesX9 = 128;
struct CCompressMode
{
UInt32 NumPasses;
UInt32 NumFastBytes;
UInt32 Algo;
UInt32 Mc;
bool McDefined;
bool IsMaximum() const { return Algo > 0; }
void Init()
{
NumPasses = NumFastBytes = Mc = Algo = 0xFFFFFFFF;
McDefined = false;
}
void Normalize(UInt32 level)
{
if (level == 0xFFFFFFFF)
level = 5;
if (NumPasses == 0xFFFFFFFF)
NumPasses =
(level >= 9 ? kNumPassesX9 :
(level >= 7 ? kNumPassesX7 :
kNumPassesX1));
if (NumFastBytes == 0xFFFFFFFF)
NumFastBytes =
(level >= 9 ? kNumFastBytesX9 :
(level >= 7 ? kNumFastBytesX7 :
kNumFastBytesX1));
if (Algo == 0xFFFFFFFF)
Algo = (level >= 5 ?
kAlgoX5 :
kAlgoX1);
}
};
class CHandler: class CHandler:
public IInArchive, public IInArchive,
public IArchiveOpenSeq, public IArchiveOpenSeq,
@@ -352,14 +305,7 @@ class CHandler:
CMyComPtr<ICompressCoder> _decoder; CMyComPtr<ICompressCoder> _decoder;
NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec; NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec;
CCompressMode _method; CDeflateProps _method;
UInt32 _level;
void InitMethodProperties()
{
_level = 0xFFFFFFFF;
_method.Init();
}
public: public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
@@ -370,7 +316,6 @@ public:
CHandler() CHandler()
{ {
InitMethodProperties();
_decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; _decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
_decoder = _decoderSpec; _decoder = _decoderSpec;
} }
@@ -496,28 +441,23 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (!allFilesMode)
{
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
if (numItems != 1 || indices[0] != 0) if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG; return E_INVALIDARG;
}
bool testMode = (_aTestMode != 0);
if (_stream) if (_stream)
extractCallback->SetTotal(_packSize); extractCallback->SetTotal(_packSize);
UInt64 currentTotalPacked = 0; UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked)); RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream) if (!testMode && !realOutStream)
return S_OK; return S_OK;
@@ -557,8 +497,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (result != S_FALSE) if (result != S_FALSE)
return result; return result;
opRes = firstItem ? opRes = firstItem ?
NArchive::NExtract::NOperationResult::kDataError : NExtract::NOperationResult::kDataError :
NArchive::NExtract::NOperationResult::kOK; NExtract::NOperationResult::kOK;
break; break;
} }
} }
@@ -572,20 +512,20 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
{ {
if (result != S_FALSE) if (result != S_FALSE)
return result; return result;
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
break; break;
} }
_decoderSpec->AlignToByte(); _decoderSpec->AlignToByte();
if (item.ReadFooter1(_decoderSpec) != S_OK) if (item.ReadFooter1(_decoderSpec) != S_OK)
{ {
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
break; break;
} }
if (item.Crc != outStreamSpec->GetCRC() || if (item.Crc != outStreamSpec->GetCRC() ||
item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset)) item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset))
{ {
opRes = NArchive::NExtract::NOperationResult::kCRCError; opRes = NExtract::NOperationResult::kCRCError;
break; break;
} }
} }
@@ -605,7 +545,7 @@ static HRESULT UpdateArchive(
ISequentialOutStream *outStream, ISequentialOutStream *outStream,
UInt64 unpackSize, UInt64 unpackSize,
const CItem &newItem, const CItem &newItem,
const CCompressMode &compressionMode, CDeflateProps &deflateProps,
IArchiveUpdateCallback *updateCallback) IArchiveUpdateCallback *updateCallback)
{ {
UInt64 complexity = 0; UInt64 complexity = 0;
@@ -627,7 +567,7 @@ static HRESULT UpdateArchive(
CItem item = newItem; CItem item = newItem;
item.Method = NHeader::NCompressionMethod::kDeflate; item.Method = NHeader::NCompressionMethod::kDeflate;
item.ExtraFlags = compressionMode.IsMaximum() ? item.ExtraFlags = deflateProps.IsMaximum() ?
NHeader::NExtraFlags::kMaximum : NHeader::NExtraFlags::kMaximum :
NHeader::NExtraFlags::kFastest; NHeader::NExtraFlags::kFastest;
@@ -637,26 +577,7 @@ static HRESULT UpdateArchive(
NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder; NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder;
CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec; CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec;
{ RINOK(deflateProps.SetCoderProperties(deflateEncoderSpec));
NWindows::NCOM::CPropVariant props[] =
{
compressionMode.Algo,
compressionMode.NumPasses,
compressionMode.NumFastBytes,
compressionMode.Mc
};
PROPID propIDs[] =
{
NCoderPropID::kAlgorithm,
NCoderPropID::kNumPasses,
NCoderPropID::kNumFastBytes,
NCoderPropID::kMatchFinderCycles
};
int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
if (!compressionMode.McDefined)
numProps--;
RINOK(deflateEncoderSpec->SetCoderProperties(propIDs, props, numProps));
}
RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress));
item.Crc = inStreamSpec->GetCRC(); item.Crc = inStreamSpec->GetCRC();
@@ -738,7 +659,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
size = prop.uhVal.QuadPart; size = prop.uhVal.QuadPart;
} }
_method.Normalize(_level);
return UpdateArchive(outStream, size, newItem, _method, updateCallback); return UpdateArchive(outStream, size, newItem, _method, updateCallback);
} }
@@ -760,49 +680,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{ {
InitMethodProperties(); return _method.SetProperties(names, values, numProps);
for (int i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &prop = values[i];
if (name[0] == L'X')
{
UInt32 level = 9;
RINOK(ParsePropValue(name.Mid(1), prop, level));
_level = level;
}
else if (name.Left(4) == L"PASS")
{
UInt32 num = kNumPassesX9;
RINOK(ParsePropValue(name.Mid(4), prop, num));
_method.NumPasses = num;
}
else if (name.Left(2) == L"FB")
{
UInt32 num = kNumFastBytesX9;
RINOK(ParsePropValue(name.Mid(2), prop, num));
_method.NumFastBytes = num;
}
else if (name.Left(2) == L"MC")
{
UInt32 num = 0xFFFFFFFF;
RINOK(ParsePropValue(name.Mid(2), prop, num));
_method.Mc = num;
_method.McDefined = true;
}
else if (name.Left(1) == L"A")
{
UInt32 num = kAlgoX5;
RINOK(ParsePropValue(name.Mid(1), prop, num));
_method.Algo = num;
}
else
return E_INVALIDARG;
}
return S_OK;
} }
static IInArchive *CreateArc() { return new CHandler; } static IInArchive *CreateArc() { return new CHandler; }
@@ -813,7 +691,7 @@ static IOutArchive *CreateArcOut() { return new CHandler; }
#endif #endif
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"GZip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut }; { L"gzip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut };
REGISTER_ARC(GZip) REGISTER_ARC(GZip)

View File

@@ -137,12 +137,11 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _db.Items.Size(); numItems = _db.Items.Size();
if (numItems == 0) if (numItems == 0)
@@ -174,27 +173,27 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (item.IsDir()) if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
UInt64 pos = 0; UInt64 pos = 0;
int res = NArchive::NExtract::NOperationResult::kOK; int res = NExtract::NOperationResult::kOK;
int i; int i;
for (i = 0; i < item.Extents.Size(); i++) for (i = 0; i < item.Extents.Size(); i++)
{ {
if (item.Size == pos) if (item.Size == pos)
break; break;
if (res != NArchive::NExtract::NOperationResult::kOK) if (res != NExtract::NOperationResult::kOK)
break; break;
const CExtent &e = item.Extents[i]; const CExtent &e = item.Extents[i];
RINOK(_stream->Seek((UInt64)e.Pos << _db.Header.BlockSizeLog, STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek((UInt64)e.Pos << _db.Header.BlockSizeLog, STREAM_SEEK_SET, NULL));
@@ -207,7 +206,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (rem == 0) if (rem == 0)
{ {
if (extentSize >= (UInt64)((UInt32)1 << _db.Header.BlockSizeLog)) if (extentSize >= (UInt64)((UInt32)1 << _db.Header.BlockSizeLog))
res = NArchive::NExtract::NOperationResult::kDataError; res = NExtract::NOperationResult::kDataError;
break; break;
} }
UInt32 curSize = kBufSize; UInt32 curSize = kBufSize;
@@ -227,7 +226,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
} }
} }
if (i != item.Extents.Size() || item.Size != pos) if (i != item.Extents.Size() || item.Size != pos)
res = NArchive::NExtract::NOperationResult::kDataError; res = NExtract::NOperationResult::kDataError;
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult(res)); RINOK(extractCallback->SetOperationResult(res));
} }

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -152,12 +152,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _archive.Refs.Size(); numItems = _archive.Refs.Size();
if (numItems == 0) if (numItems == 0)
@@ -203,8 +202,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
currentItemSize = 0; currentItemSize = 0;
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode; Int32 askMode = testMode ?
askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
@@ -217,7 +217,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (item.IsDir()) if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
currentItemSize = item.DataLength; currentItemSize = item.DataLength;
@@ -231,7 +231,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
blockIndex = be.LoadRBA; blockIndex = be.LoadRBA;
} }
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
outStreamSpec->SetStream(realOutStream); outStreamSpec->SetStream(realOutStream);
@@ -242,8 +242,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStreamSpec->ReleaseStream(); outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult(outStreamSpec->IsFinishedOK() ? RINOK(extractCallback->SetOperationResult(outStreamSpec->IsFinishedOK() ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View File

@@ -168,13 +168,11 @@ struct CItem
AString GetName() const AString GetName() const
{ {
AString dirName = GetDirName(); AString dirName = GetDirName();
dirName.Replace((char)(unsigned char)0xFF, '\\'); const char kDirSeparator = '\\';
if (!dirName.IsEmpty()) // check kDirSeparator in Linux
{ dirName.Replace((char)(unsigned char)0xFF, kDirSeparator);
char c = dirName[dirName.Length() - 1]; if (!dirName.IsEmpty() && dirName.Back() != kDirSeparator)
if (c != '\\') dirName += kDirSeparator;
dirName += '\\';
}
return dirName + GetFileName(); return dirName + GetFileName();
} }
}; };
@@ -469,7 +467,7 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *pro
{ {
UInt32 realProcessedSize; UInt32 realProcessedSize;
HRESULT result; HRESULT result;
if(!_stream) if (!_stream)
{ {
realProcessedSize = size; realProcessedSize = size;
result = S_OK; result = S_OK;
@@ -477,7 +475,7 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *pro
else else
result = _stream->Write(data, size, &realProcessedSize); result = _stream->Write(data, size, &realProcessedSize);
_crc.Update(data, realProcessedSize); _crc.Update(data, realProcessedSize);
if(processedSize != NULL) if (processedSize != NULL)
*processedSize = realProcessedSize; *processedSize = realProcessedSize;
return result; return result;
} }
@@ -630,24 +628,19 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
//////////////////////////////////////
// CHandler::DecompressItems
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallback) Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (testModeSpec != 0); bool testMode = (testModeSpec != 0);
UInt64 totalUnPacked = 0, totalPacked = 0; UInt64 totalUnPacked = 0, totalPacked = 0;
bool allFilesMode = (numItems == UInt32(-1)); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = _items.Size(); numItems = _items.Size();
if(numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
UInt32 i; UInt32 i;
for(i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
const CItemEx &item = _items[allFilesMode ? i : indices[i]]; const CItemEx &item = _items[allFilesMode ? i : indices[i]];
totalUnPacked += item.Size; totalUnPacked += item.Size;
@@ -674,7 +667,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
CMyComPtr<ISequentialInStream> inStream(streamSpec); CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream); streamSpec->SetStream(_stream);
for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
currentTotalPacked += currentItemPacked) currentTotalPacked += currentItemPacked)
{ {
currentItemUnPacked = 0; currentItemUnPacked = 0;
@@ -702,7 +695,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
continue; continue;
} }
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));

View File

@@ -319,28 +319,23 @@ STDMETHODIMP CHandler::Close()
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (!allFilesMode)
{
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
if (numItems != 1 || indices[0] != 0) if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG; return E_INVALIDARG;
}
bool testMode = (_aTestMode != 0);
if (_stream) if (_stream)
extractCallback->SetTotal(_packSize); extractCallback->SetTotal(_packSize);
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream) if (!testMode && !realOutStream)
return S_OK; return S_OK;
@@ -368,7 +363,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
_lzma86, _seqStream); _lzma86, _seqStream);
RINOK(result); RINOK(result);
Int32 opRes = NArchive::NExtract::NOperationResult::kOK; Int32 opRes = NExtract::NOperationResult::kOK;
bool firstItem = true; bool firstItem = true;
for (;;) for (;;)
@@ -395,12 +390,12 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
result = decoder.Code(st, outStream, progress); result = decoder.Code(st, outStream, progress);
if (result == E_NOTIMPL) if (result == E_NOTIMPL)
{ {
opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; opRes = NExtract::NOperationResult::kUnSupportedMethod;
break; break;
} }
if (result == S_FALSE) if (result == S_FALSE)
{ {
opRes = NArchive::NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
break; break;
} }
RINOK(result); RINOK(result);

View File

@@ -399,12 +399,11 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _sections.Size(); numItems = _sections.Size();
if (numItems == 0) if (numItems == 0)
@@ -434,8 +433,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
lps->InSize = lps->OutSize = currentTotalSize; lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur()); RINOK(lps->SetCur());
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
const CSection &item = _sections[index]; const CSection &item = _sections[index];
currentItemSize = item.GetPackSize(); currentItemSize = item.GetPackSize();
@@ -451,8 +450,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View File

@@ -431,12 +431,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _items.Size(); numItems = _items.Size();
if (numItems == 0) if (numItems == 0)
@@ -467,14 +466,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> outStream; CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index]; const CItem &item = _items[index];
const CPartition &part = item.Part; const CPartition &part = item.Part;
RINOK(extractCallback->GetStream(index, &outStream, askMode)); RINOK(extractCallback->GetStream(index, &outStream, askMode));
totalSize += item.Size; totalSize += item.Size;
if (!testMode && (!outStream)) if (!testMode && !outStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -483,8 +482,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

257
CPP/7zip/Archive/MslzHandler.cpp Executable file
View File

@@ -0,0 +1,257 @@
// MslzHandler.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "Common/ComTry.h"
#include "Common/MyString.h"
#include "Windows/PropVariant.h"
#include "../Common/InBuffer.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "Common/DummyOutStream.h"
namespace NArchive {
namespace NMslz {
class CHandler:
public IInArchive,
public CMyUnknownImp
{
CMyComPtr<IInStream> _stream;
UInt32 _size;
UInt64 _packSize;
UString _name;
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
};
STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = 1;
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidPath: if (!_name.IsEmpty()) prop = _name; break;
case kpidSize: prop = _size; break;
case kpidPackSize: prop = _packSize; break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
static const unsigned kSignatureSize = 9;
static const unsigned kHeaderSize = kSignatureSize + 1 + 4;
#define MSLZ_SIGNATURE { 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33, 0x41 }
// old signature: 53 5A 20 88 F0 27 33
static const Byte signature[kSignatureSize] = MSLZ_SIGNATURE;
static const wchar_t *g_Exts[] =
{
L"dll",
L"exe",
L"kmd",
L"sys"
};
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback *callback)
{
COM_TRY_BEGIN
{
Close();
Byte buffer[kHeaderSize];
RINOK(ReadStream_FALSE(stream, buffer, kHeaderSize));
if (memcmp(buffer, signature, kSignatureSize) != 0)
return S_FALSE;
_size = GetUi32(buffer + 10);
if (_size > 0xFFFFFFE0)
return S_FALSE;
RINOK(stream->Seek(0, STREAM_SEEK_END, &_packSize));
if (callback)
{
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
if (openVolumeCallback)
{
NWindows::NCOM::CPropVariant prop;
if (openVolumeCallback->GetProperty(kpidName, &prop) == S_OK && prop.vt == VT_BSTR)
{
UString baseName = prop.bstrVal;
if (!baseName.IsEmpty() && baseName.Back() == L'_')
{
baseName.DeleteBack();
Byte replaceByte = buffer[kSignatureSize];
if (replaceByte == 0)
{
for (int i = 0; i < sizeof(g_Exts) / sizeof(g_Exts[0]); i++)
{
UString s = g_Exts[i];
int len = s.Length();
Byte b = (Byte)s.Back();
s.DeleteBack();
if (baseName.Length() >= len &&
baseName[baseName.Length() - len] == '.' &&
s.CompareNoCase(baseName.Right(len - 1)) == 0)
{
replaceByte = b;
break;
}
}
}
if (replaceByte >= 0x20 && replaceByte < 0x80)
_name = baseName + (wchar_t)replaceByte;
}
}
}
}
_stream = stream;
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_stream.Release();
_name.Empty();
return S_OK;
}
// MslzDec is modified LZSS algorithm of Haruhiko Okumura:
// maxLen = 18; Okumura
// maxLen = 16; MS
#define PROGRESS_AND_WRITE \
if ((dest & kMask) == 0) { RINOK(WriteStream(outStream, buf, kBufSize)); \
if ((dest & ((1 << 20) - 1)) == 0) \
{ UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \
RINOK(progress->SetRatioInfo(&inSize, &outSize)); }}
static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, ICompressProgressInfo *progress)
{
const unsigned kBufSize = (1 << 12);
const unsigned kMask = kBufSize - 1;
Byte buf[kBufSize];
UInt32 dest = 0;
memset(buf, ' ', kBufSize);
while (dest < unpackSize)
{
Byte b;
if (!inStream.ReadByte(b))
return S_FALSE;
for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)
{
if (!inStream.ReadByte(b))
return S_FALSE;
if (mask & 1)
{
buf[dest++ & kMask] = b;
PROGRESS_AND_WRITE
}
else
{
Byte b1;
if (!inStream.ReadByte(b1))
return S_FALSE;
const unsigned kMaxLen = 16; // 18 in Okumura's code.
unsigned src = (((((unsigned)b1 & 0xF0) << 4) | b) + kMaxLen) & kMask;
unsigned len = (b1 & 0xF) + 3;
if (len > kMaxLen || dest + len > unpackSize)
return S_FALSE;
do
{
buf[dest++ & kMask] = buf[src++ & kMask];
PROGRESS_AND_WRITE
}
while (--len != 0);
}
}
}
return WriteStream(outStream, buf, dest & kMask);
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
extractCallback->SetTotal(_size);
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream)
return S_OK;
extractCallback->PrepareOperation(askMode);
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init();
realOutStream.Release();
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
CInBuffer s;
if (!s.Create(1 << 20))
return E_OUTOFMEMORY;
s.SetStream(_stream);
s.Init();
Byte buffer[kHeaderSize];
Int32 opRes = NExtract::NOperationResult::kDataError;
if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize)
{
HRESULT result = MslzDec(s, outStream, _size, progress);
if (result == S_OK)
opRes = NExtract::NOperationResult::kOK;
else if (result != S_FALSE)
return result;
}
outStream.Release();
return extractCallback->SetOperationResult(opRes);
COM_TRY_END
}
static IInArchive *CreateArc() { return new CHandler; }
static CArcInfo g_ArcInfo =
{ L"MsLZ", L"", 0, 0xD5, MSLZ_SIGNATURE, kSignatureSize, false, CreateArc, 0 };
REGISTER_ARC(Mslz)
}}

View File

@@ -187,12 +187,11 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = _numItems; numItems = _numItems;
if (numItems == 0) if (numItems == 0)
@@ -222,19 +221,19 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index]; const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
currentTotalSize += item.Size; currentTotalSize += item.Size;
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
if (testMode) if (testMode)
{ {
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL));
@@ -242,8 +241,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View File

@@ -263,12 +263,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
GetNumberOfItems(&numItems); GetNumberOfItems(&numItems);
if(numItems == 0) if(numItems == 0)
@@ -326,8 +325,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
currentItemSize = 0; currentItemSize = 0;
RINOK(extractCallback->SetCompleted(&currentTotalSize)); RINOK(extractCallback->SetCompleted(&currentTotalSize));
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode; Int32 askMode = testMode ?
askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
@@ -336,7 +336,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (index >= (UInt32)_archive.Items.Size()) if (index >= (UInt32)_archive.Items.Size())
{ {
currentItemSize = _archive.Script.Length(); currentItemSize = _archive.Script.Length();
if(!testMode && (!realOutStream)) if(!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
if (!testMode) if (!testMode)
@@ -352,7 +352,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
else else
GetCompressedSize(index, currentItemSize); GetCompressedSize(index, currentItemSize);
if(!testMode && (!realOutStream)) if(!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -477,8 +477,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
} }
realOutStream.Release(); realOutStream.Release();
RINOK(extractCallback->SetOperationResult(dataError ? RINOK(extractCallback->SetOperationResult(dataError ?
NArchive::NExtract::NOperationResult::kDataError : NExtract::NOperationResult::kDataError :
NArchive::NExtract::NOperationResult::kOK)); NExtract::NOperationResult::kOK));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View File

@@ -1,30 +1,21 @@
// Archive/NsisIn.cpp // NsisIn.cpp
#include "StdAfx.h" #include "StdAfx.h"
// #include <stdio.h> #include "../../../../C/CpuArch.h"
#include "NsisIn.h" #include "Common/IntToString.h"
#include "NsisDecode.h"
#include "Windows/Defs.h"
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
#include "Common/StringConvert.h" #include "NsisIn.h"
#include "Common/IntToString.h"
#include "../../../../C/CpuArch.h"
#define Get32(p) GetUi32(p) #define Get32(p) GetUi32(p)
namespace NArchive { namespace NArchive {
namespace NNsis { namespace NNsis {
Byte kSignature[kSignatureSize] = { 0xEF + 1, 0xBE, 0xAD, 0xDE, Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74};
struct CSignatureInit { CSignatureInit() { kSignature[0]--; } } g_SignatureInit;
#ifdef NSIS_SCRIPT #ifdef NSIS_SCRIPT
static const char *kCrLf = "\x0D\x0A"; static const char *kCrLf = "\x0D\x0A";

View File

@@ -1,17 +1,12 @@
// Archive/NsisIn.h // NsisIn.h
#ifndef __ARCHIVE_NSIS_IN_H #ifndef __ARCHIVE_NSIS_IN_H
#define __ARCHIVE_NSIS_IN_H #define __ARCHIVE_NSIS_IN_H
#include "Common/Buffer.h" #include "Common/Buffer.h"
#include "Common/IntToString.h"
#include "Common/MyCom.h" #include "Common/MyCom.h"
#include "Common/StringConvert.h" #include "Common/StringConvert.h"
#include "../../Common/CreateCoder.h"
#include "../../IStream.h"
#include "NsisDecode.h" #include "NsisDecode.h"
// #define NSIS_SCRIPT // #define NSIS_SCRIPT
@@ -20,6 +15,8 @@ namespace NArchive {
namespace NNsis { namespace NNsis {
const int kSignatureSize = 16; const int kSignatureSize = 16;
#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74}
extern Byte kSignature[kSignatureSize]; extern Byte kSignature[kSignatureSize];
const UInt32 kFlagsMask = 0xF; const UInt32 kFlagsMask = 0xF;

View File

@@ -8,7 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NNsis::CHandler; } static IInArchive *CreateArc() { return new NArchive::NNsis::CHandler; }
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"Nsis", 0, 0, 0x9, { 0xEF, 0xBE, 0xAD, 0xDE, { L"Nsis", L"", 0, 0x9, NSIS_SIGNATURE, NArchive::NNsis::kSignatureSize, false, CreateArc, 0 };
0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74}, 16, false, CreateArc, 0 };
REGISTER_ARC(Nsis) REGISTER_ARC(Nsis)

View File

@@ -124,7 +124,11 @@ bool CHeader::Parse(const Byte *p)
// DriveNumber = p[0x24]; // DriveNumber = p[0x24];
if (p[0x25] != 0) // CurrentHead if (p[0x25] != 0) // CurrentHead
return false; return false;
if (p[0x26] != 0x80) // ExtendedBootSig /*
NTFS-HDD: p[0x26] = 0x80
NTFS-FLASH: p[0x26] = 0
*/
if (p[0x26] != 0x80 && p[0x26] != 0) // ExtendedBootSig
return false; return false;
if (p[0x27] != 0) // reserved if (p[0x27] != 0) // reserved
return false; return false;
@@ -916,6 +920,9 @@ struct CDataRef
int Num; int Num;
}; };
static const UInt32 kMagic_FILE = 0x454c4946;
static const UInt32 kMagic_BAAD = 0x44414142;
struct CMftRec struct CMftRec
{ {
UInt32 Magic; UInt32 Magic;
@@ -934,7 +941,6 @@ struct CMftRec
CSiAttr SiAttr; CSiAttr SiAttr;
void MoveAttrsFrom(CMftRec &src) void MoveAttrsFrom(CMftRec &src)
{ {
DataAttrs += src.DataAttrs; DataAttrs += src.DataAttrs;
@@ -954,6 +960,8 @@ struct CMftRec
bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs); bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs);
bool IsEmpty() const { return (Magic <= 2); } bool IsEmpty() const { return (Magic <= 2); }
bool IsFILE() const { return (Magic == kMagic_FILE); }
bool IsBAAD() const { return (Magic == kMagic_BAAD); }
bool InUse() const { return (Flags & 1) != 0; } bool InUse() const { return (Flags & 1) != 0; }
bool IsDir() const { return (Flags & 2) != 0; } bool IsDir() const { return (Flags & 2) != 0; }
@@ -1032,10 +1040,8 @@ bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNum
CObjectVector<CAttr> *attrs) CObjectVector<CAttr> *attrs)
{ {
G32(p, Magic); G32(p, Magic);
if (IsEmpty()) if (!IsFILE())
return true; return IsEmpty() || IsBAAD();
if (Magic != 0x454c4946)
return false;
UInt32 usaOffset; UInt32 usaOffset;
UInt32 numUsaItems; UInt32 numUsaItems;
@@ -1246,7 +1252,7 @@ HRESULT CDatabase::Open()
numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog); numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog);
if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0)) if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0))
return S_FALSE; return S_FALSE;
if (mftRec.IsEmpty()) if (!mftRec.IsFILE())
return S_FALSE; return S_FALSE;
mftRec.ParseDataNames(); mftRec.ParseDataNames();
if (mftRec.DataRefs.IsEmpty()) if (mftRec.DataRefs.IsEmpty())
@@ -1331,7 +1337,7 @@ HRESULT CDatabase::Open()
for (i = 0; i < Recs.Size(); i++) for (i = 0; i < Recs.Size(); i++)
{ {
CMftRec &rec = Recs[i]; CMftRec &rec = Recs[i];
if (rec.IsEmpty() || !rec.BaseMftRef.IsBaseItself()) if (!rec.IsFILE() || !rec.BaseMftRef.IsBaseItself())
continue; continue;
int numNames = 0; int numNames = 0;
// printf("\n%4d: ", i); // printf("\n%4d: ", i);
@@ -1610,12 +1616,11 @@ STDMETHODIMP CHandler::Close()
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (_aTestMode != 0); bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode) if (allFilesMode)
numItems = Items.Size(); numItems = Items.Size();
if (numItems == 0) if (numItems == 0)
@@ -1655,8 +1660,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
@@ -1664,11 +1669,11 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (item.IsDir()) if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
if (!testMode && (!realOutStream)) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -1679,12 +1684,12 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
const CMftRec &rec = Recs[item.RecIndex]; const CMftRec &rec = Recs[item.RecIndex];
const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
int res = NArchive::NExtract::NOperationResult::kDataError; int res = NExtract::NOperationResult::kDataError;
{ {
CMyComPtr<IInStream> inStream; CMyComPtr<IInStream> inStream;
HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream); HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream);
if (hres == S_FALSE) if (hres == S_FALSE)
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; res = NExtract::NOperationResult::kUnSupportedMethod;
else else
{ {
RINOK(hres); RINOK(hres);
@@ -1696,7 +1701,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(hres); RINOK(hres);
} }
if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK) if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK)
res = NArchive::NExtract::NOperationResult::kOK; res = NExtract::NOperationResult::kOK;
} }
} }
} }

View File

File diff suppressed because it is too large Load Diff

View File

@@ -350,7 +350,7 @@ HRESULT CHandler::Open2(IInStream *stream,
if (!openVolumeCallback) if (!openVolumeCallback)
break; break;
if(_archives.Size() == 1) if (_archives.Size() == 1)
{ {
if (!_archiveInfo.IsVolume()) if (!_archiveInfo.IsVolume())
break; break;
@@ -395,9 +395,14 @@ HRESULT CHandler::Open2(IInStream *stream,
CItemEx item; CItemEx item;
for (;;) for (;;)
{ {
HRESULT result = archive.GetNextItem(item, getTextPassword); bool decryptionError;
HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError);
if (result == S_FALSE) if (result == S_FALSE)
{
if (decryptionError && _items.IsEmpty())
return S_FALSE;
break; break;
}
RINOK(result); RINOK(result);
if (item.IgnoreItem()) if (item.IgnoreItem())
continue; continue;
@@ -470,27 +475,25 @@ struct CMethodItem
}; };
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
CMyComPtr<ICryptoGetTextPassword> getTextPassword; CMyComPtr<ICryptoGetTextPassword> getTextPassword;
bool testMode = (_aTestMode != 0);
CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;
UInt64 censoredTotalUnPacked = 0, UInt64 censoredTotalUnPacked = 0,
// censoredTotalPacked = 0, // censoredTotalPacked = 0,
importantTotalUnPacked = 0; importantTotalUnPacked = 0;
// importantTotalPacked = 0; // importantTotalPacked = 0;
bool allFilesMode = (numItems == UInt32(-1)); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = _refItems.Size(); numItems = _refItems.Size();
if(numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
int lastIndex = 0; int lastIndex = 0;
CRecordVector<int> importantIndexes; CRecordVector<int> importantIndexes;
CRecordVector<bool> extractStatuses; CRecordVector<bool> extractStatuses;
for(UInt32 t = 0; t < numItems; t++) for (UInt32 t = 0; t < numItems; t++)
{ {
int index = allFilesMode ? t : indices[t]; int index = allFilesMode ? t : indices[t];
const CRefItem &refItem = _refItems[index]; const CRefItem &refItem = _refItems[index];
@@ -498,11 +501,11 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
censoredTotalUnPacked += item.Size; censoredTotalUnPacked += item.Size;
// censoredTotalPacked += item.PackSize; // censoredTotalPacked += item.PackSize;
int j; int j;
for(j = lastIndex; j <= index; j++) for (j = lastIndex; j <= index; j++)
// if(!_items[_refItems[j].ItemIndex].IsSolid()) // if (!_items[_refItems[j].ItemIndex].IsSolid())
if(!IsSolid(j)) if (!IsSolid(j))
lastIndex = j; lastIndex = j;
for(j = lastIndex; j <= index; j++) for (j = lastIndex; j <= index; j++)
{ {
const CRefItem &refItem = _refItems[j]; const CRefItem &refItem = _refItems[j];
const CItemEx &item = _items[refItem.ItemIndex]; const CItemEx &item = _items[refItem.ItemIndex];
@@ -543,7 +546,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
bool solidStart = true; bool solidStart = true;
for(int i = 0; i < importantIndexes.Size(); i++, for (int i = 0; i < importantIndexes.Size(); i++,
currentImportantTotalUnPacked += currentUnPackSize, currentImportantTotalUnPacked += currentUnPackSize,
currentImportantTotalPacked += currentPackSize) currentImportantTotalPacked += currentPackSize)
{ {
@@ -553,12 +556,12 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode; Int32 askMode;
if(extractStatuses[i]) if (extractStatuses[i])
askMode = testMode ? askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
else else
askMode = NArchive::NExtract::NAskMode::kSkip; askMode = NExtract::NAskMode::kSkip;
UInt32 index = importantIndexes[i]; UInt32 index = importantIndexes[i];
@@ -569,22 +572,22 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
currentPackSize = GetPackSize(index); currentPackSize = GetPackSize(index);
if(item.IgnoreItem()) if (item.IgnoreItem())
continue; continue;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (!IsSolid(index)) if (!IsSolid(index))
solidStart = true; solidStart = true;
if(item.IsDir()) if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
bool mustBeProcessedAnywhere = false; bool mustBeProcessedAnywhere = false;
if(i < importantIndexes.Size() - 1) if (i < importantIndexes.Size() - 1)
{ {
// const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]]; // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];
// const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex]; // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex];
@@ -596,7 +599,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
continue; continue;
if (!realOutStream && !testMode) if (!realOutStream && !testMode)
askMode = NArchive::NExtract::NAskMode::kSkip; askMode = NExtract::NAskMode::kSkip;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -664,15 +667,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
else else
{ {
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
continue; continue;
} }
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,
&cryptoSetPassword)); &cryptoSetPassword));
if (!getTextPassword) if (!getTextPassword)
extractCallback.QueryInterface(IID_ICryptoGetTextPassword, extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
&getTextPassword);
if (getTextPassword) if (getTextPassword)
{ {
CMyComBSTR password; CMyComBSTR password;
@@ -729,7 +731,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (item.UnPackVersion >= 29) if (item.UnPackVersion >= 29)
{ {
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
continue; continue;
} }
*/ */
@@ -758,7 +760,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (mi.Coder == 0) if (mi.Coder == 0)
{ {
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
continue; continue;
} }
@@ -785,7 +787,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
} }
default: default:
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
continue; continue;
} }
HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress); HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);
@@ -794,7 +796,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (result == S_FALSE) if (result == S_FALSE)
{ {
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
continue; continue;
} }
if (result != S_OK) if (result != S_OK)
@@ -808,8 +810,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC; bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
outStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK: RINOK(extractCallback->SetOperationResult(crcOK ?
NArchive::NExtract::NOperationResult::kCRCError)); NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kCRCError));
} }
/* /*
else else
@@ -824,8 +827,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
break; break;
} }
} }
RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK: RINOK(extractCallback->SetOperationResult(crcOK ?
NArchive::NExtract::NOperationResult::kCRCError)); NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kCRCError));
} }
*/ */
} }

View File

@@ -372,8 +372,9 @@ void CInArchive::AddToSeekValue(UInt64 addValue)
m_Position += addValue; m_Position += addValue;
} }
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword) HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError)
{ {
decryptionError = false;
if (m_SeekOnArchiveComment) if (m_SeekOnArchiveComment)
SkipArchiveComment(); SkipArchiveComment();
for (;;) for (;;)
@@ -469,8 +470,11 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
AddToSeekValue(item.PackSize); // m_Position points to next header; AddToSeekValue(item.PackSize); // m_Position points to next header;
return S_OK; return S_OK;
} }
if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 12)) if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))
return E_FAIL; // it's for bad passwords {
decryptionError = true;
return S_FALSE;
}
if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0) if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
{ {
m_FileHeaderData.EnsureCapacity(7 + 4); m_FileHeaderData.EnsureCapacity(7 + 4);
@@ -480,7 +484,10 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
UInt32 dataSize = ReadUInt32(); UInt32 dataSize = ReadUInt32();
AddToSeekValue(dataSize); AddToSeekValue(dataSize);
if (m_CryptoMode && dataSize > (1 << 27)) if (m_CryptoMode && dataSize > (1 << 27))
return E_FAIL; // it's for bad passwords {
decryptionError = true;
return S_FALSE;
}
m_CryptoPos = m_BlockHeader.HeadSize; m_CryptoPos = m_BlockHeader.HeadSize;
} }
else else

View File

@@ -111,7 +111,7 @@ protected:
public: public:
HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit); HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
void Close(); void Close();
HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword); HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError);
void SkipArchiveComment(); void SkipArchiveComment();

View File

@@ -243,30 +243,25 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
if (numItems == UInt32(-1))
numItems = 1;
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
if (numItems != 1 || indices[0] != 0) if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG; return E_INVALIDARG;
bool testMode = (_aTestMode != 0);
RINOK(extractCallback->SetTotal(_size)); RINOK(extractCallback->SetTotal(_size));
CMyComPtr<ISequentialOutStream> outStream; CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &outStream, askMode)); RINOK(extractCallback->GetStream(0, &outStream, askMode));
if (!testMode && !outStream) if (!testMode && !outStream)
return S_OK; return S_OK;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
CLocalProgress *lps = new CLocalProgress; CLocalProgress *lps = new CLocalProgress;
@@ -276,7 +271,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL));
RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress));
outStream.Release(); outStream.Release();
return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
COM_TRY_END COM_TRY_END
} }

View File

@@ -294,24 +294,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
if (numItems == UInt32(-1))
numItems = 1;
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
if (numItems != 1 || indices[0] != 0) if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG; return E_INVALIDARG;
bool testMode = (_aTestMode != 0);
UInt64 currentTotalSize = 0; UInt64 currentTotalSize = 0;
RINOK(extractCallback->SetTotal(_totalSize)); RINOK(extractCallback->SetTotal(_totalSize));
CMyComPtr<ISequentialOutStream> outStream; CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &outStream, askMode)); RINOK(extractCallback->GetStream(0, &outStream, askMode));
if (!testMode && !outStream) if (!testMode && !outStream)
return S_OK; return S_OK;
@@ -334,7 +331,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
currentTotalSize += copyCoderSpec->TotalSize; currentTotalSize += copyCoderSpec->TotalSize;
} }
outStream.Release(); outStream.Release();
return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
COM_TRY_END COM_TRY_END
} }

706
CPP/7zip/Archive/SwfHandler.cpp Executable file
View File

@@ -0,0 +1,706 @@
// SwfHandler.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "Common/Buffer.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Common/MyString.h"
#include "Windows/PropVariant.h"
#include "../Common/InBuffer.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
#include "../Compress/ZlibDecoder.h"
#include "../Compress/ZlibEncoder.h"
#include "Common/DummyOutStream.h"
#include "DeflateProps.h"
using namespace NWindows;
namespace NArchive {
namespace NSwfc {
static const UInt32 kHeaderSize = 8;
static const Byte SWF_UNCOMPRESSED = 'F';
static const Byte SWF_COMPRESSED = 'C';
static const Byte SWF_MIN_COMPRESSED_VER = 6;
struct CItem
{
Byte Buf[kHeaderSize];
UInt32 GetSize() const { return GetUi32(Buf + 4); }
bool IsSwf(Byte c) const { return (Buf[0] == c && Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < 32); }
bool IsUncompressed() const { return IsSwf(SWF_UNCOMPRESSED); }
bool IsCompressed() const { return IsSwf(SWF_COMPRESSED); }
void MakeUncompressed() { Buf[0] = SWF_UNCOMPRESSED; }
void MakeCompressed()
{
Buf[0] = SWF_COMPRESSED;
if (Buf[3] < SWF_MIN_COMPRESSED_VER)
Buf[3] = SWF_MIN_COMPRESSED_VER;
}
HRESULT ReadHeader(ISequentialInStream *stream) { return ReadStream_FALSE(stream, Buf, kHeaderSize); }
HRESULT WriteHeader(ISequentialOutStream *stream) { return WriteStream(stream, Buf, kHeaderSize); }
};
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
public IOutArchive,
public ISetProperties,
public CMyUnknownImp
{
CItem _item;
UInt64 _packSize;
bool _packSizeDefined;
CMyComPtr<ISequentialInStream> _seqStream;
CMyComPtr<IInStream> _stream;
CDeflateProps _method;
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
};
STATPROPSTG kProps[] =
{
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO_Table
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch(propID)
{
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = 1;
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidSize: prop = (UInt64)_item.GetSize(); break;
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
{
RINOK(OpenSeq(stream));
_stream = stream;
return S_OK;
}
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
{
Close();
HRESULT res = _item.ReadHeader(stream);
if (res == S_OK)
if (_item.IsCompressed())
_seqStream = stream;
else
res = S_FALSE;
return res;
}
STDMETHODIMP CHandler::Close()
{
_packSizeDefined = false;
_seqStream.Release();
_stream.Release();
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
extractCallback->SetTotal(_item.GetSize());
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream)
return S_OK;
extractCallback->PrepareOperation(askMode);
NCompress::NZlib::CDecoder *_decoderSpec = new NCompress::NZlib::CDecoder;
CMyComPtr<ICompressCoder> _decoder = _decoderSpec;
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init();
realOutStream.Release();
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
lps->InSize = kHeaderSize;
lps->OutSize = outStreamSpec->GetSize();
RINOK(lps->SetCur());
CItem item = _item;
item.MakeUncompressed();
RINOK(item.WriteHeader(outStream));
if (_stream)
RINOK(_stream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));
HRESULT result = _decoderSpec->Code(_seqStream, outStream, NULL, NULL, progress);
Int32 opRes = NExtract::NOperationResult::kDataError;
if (result == S_OK)
{
if (_item.GetSize() == outStreamSpec->GetSize())
{
_packSizeDefined = true;
_packSize = _decoderSpec->GetInputProcessedSize() + kHeaderSize;
opRes = NExtract::NOperationResult::kOK;
}
}
else if (result != S_FALSE)
return result;
outStream.Release();
return extractCallback->SetOperationResult(opRes);
COM_TRY_END
}
static HRESULT UpdateArchive(ISequentialOutStream *outStream,
UInt64 size, CDeflateProps &deflateProps,
IArchiveUpdateCallback *updateCallback)
{
UInt64 complexity = 0;
RINOK(updateCallback->SetTotal(size));
RINOK(updateCallback->SetCompleted(&complexity));
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(0, &fileInStream));
CItem item;
HRESULT res = item.ReadHeader(fileInStream);
if (res == S_FALSE)
return E_INVALIDARG;
RINOK(res);
if (!item.IsUncompressed() || size != item.GetSize())
return E_INVALIDARG;
item.MakeCompressed();
item.WriteHeader(outStream);
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
encoderSpec->Create();
RINOK(deflateProps.SetCoderProperties(encoderSpec->DeflateEncoderSpec));
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress));
if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size)
return E_INVALIDARG;
return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);
}
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
{
*timeType = NFileTimeType::kUnix;
return S_OK;
}
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
if (numItems != 1)
return E_INVALIDARG;
Int32 newData, newProps;
UInt32 indexInArchive;
if (!updateCallback)
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
if (IntToBool(newProps))
{
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
if (prop.vt == VT_BOOL)
{
if (prop.boolVal != VARIANT_FALSE)
return E_INVALIDARG;
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
}
if (IntToBool(newData))
{
UInt64 size;
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
return UpdateArchive(outStream, size, _method, updateCallback);
}
if (indexInArchive != 0)
return E_INVALIDARG;
if (!_seqStream)
return E_NOTIMPL;
if (_stream)
{
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
}
else
_item.WriteHeader(outStream);
return NCompress::CopyStream(_seqStream, outStream, NULL);
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
return _method.SetProperties(names, values, numProps);
}
static IInArchive *CreateArc() { return new CHandler; }
#ifndef EXTRACT_ONLY
static IOutArchive *CreateArcOut() { return new CHandler; }
#else
#define CreateArcOut 0
#endif
static CArcInfo g_ArcInfo =
{ L"SWFc", L"swf", L"~.swf", 0xD8, { 'C', 'W', 'S' }, 3, true, CreateArc, CreateArcOut };
REGISTER_ARC(Swfc)
}
namespace NSwf {
static const UInt32 kFileSizeMax = (UInt32)1 << 30;
static const int kNumTagsMax = (UInt32)1 << 23;
struct CTag
{
UInt32 Type;
CByteBuffer Buf;
};
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
public CMyUnknownImp
{
CObjectVector<CTag> _tags;
NSwfc::CItem _item;
UInt64 _packSize;
HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback);
HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback);
public:
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
INTERFACE_IInArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
};
STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidComment, VT_BSTR}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO_Table
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch(propID)
{
case kpidPhySize: prop = _packSize; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _tags.Size();
return S_OK;
}
static const char *g_TagDesc[92] =
{
"End",
"ShowFrame",
"DefineShape",
NULL,
"PlaceObject",
"RemoveObject",
"DefineBits",
"DefineButton",
"JPEGTables",
"SetBackgroundColor",
"DefineFont",
"DefineText",
"DoAction",
"DefineFontInfo",
"DefineSound",
"StartSound",
NULL,
"DefineButtonSound",
"SoundStreamHead",
"SoundStreamBlock",
"DefineBitsLossless",
"DefineBitsJPEG2",
"DefineShape2",
"DefineButtonCxform",
"Protect",
NULL,
"PlaceObject2",
NULL,
"RemoveObject2",
NULL,
NULL,
NULL,
"DefineShape3",
"DefineText2",
"DefineButton2",
"DefineBitsJPEG3",
"DefineBitsLossless2",
"DefineEditText",
NULL,
"DefineSprite",
NULL,
"41",
NULL,
"FrameLabel",
NULL,
"SoundStreamHead2",
"DefineMorphShape",
NULL,
"DefineFont2",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"ExportAssets",
"ImportAssets",
"EnableDebugger",
"DoInitAction",
"DefineVideoStream",
"VideoFrame",
"DefineFontInfo2",
NULL,
"EnableDebugger2",
"ScriptLimits",
"SetTabIndex",
NULL,
NULL,
"FileAttributes",
"PlaceObject3",
"ImportAssets2",
NULL,
"DefineFontAlignZones",
"CSMTextSettings",
"DefineFont3",
"SymbolClass",
"Metadata",
"DefineScalingGrid",
NULL,
NULL,
NULL,
"DoABC",
"DefineShape4",
"DefineMorphShape2",
NULL,
"DefineSceneAndFrameLabelData",
"DefineBinaryData",
"DefineFontName",
"StartSound2",
"DefineBitsJPEG4",
"DefineFont4"
};
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
const CTag &tag = _tags[index];
switch(propID)
{
case kpidPath:
{
char s[32];
ConvertUInt32ToString(index, s);
size_t i = strlen(s);
s[i++] = '.';
ConvertUInt32ToString(tag.Type, s + i);
prop = s;
break;
}
case kpidSize:
case kpidPackSize:
prop = (UInt64)tag.Buf.GetCapacity(); break;
case kpidComment:
if (tag.Type < sizeof(g_TagDesc) / sizeof(g_TagDesc[0]))
{
const char *s = g_TagDesc[tag.Type];
if (s != NULL)
prop = s;
}
break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
{
return OpenSeq2(stream, callback);
}
static UInt16 Read16(CInBuffer &stream)
{
UInt16 res = 0;
for (int i = 0; i < 2; i++)
{
Byte b;
if (!stream.ReadByte(b))
throw 1;
res |= (UInt16)b << (i * 8);
}
return res;
}
static UInt32 Read32(CInBuffer &stream)
{
UInt32 res = 0;
for (int i = 0; i < 4; i++)
{
Byte b;
if (!stream.ReadByte(b))
throw 1;
res |= (UInt32)b << (i * 8);
}
return res;
}
struct CBitReader
{
CInBuffer *stream;
unsigned NumBits;
Byte Val;
CBitReader(): NumBits(0), Val(0) {}
UInt32 ReadBits(unsigned numBits);
};
UInt32 CBitReader::ReadBits(unsigned numBits)
{
UInt32 res = 0;
while (numBits > 0)
{
if (NumBits == 0)
{
Val = stream->ReadByte();
NumBits = 8;
}
if (numBits <= NumBits)
{
res <<= numBits;
NumBits -= numBits;
res |= (Val >> NumBits);
Val &= (1 << NumBits) - 1;
break;
}
else
{
res <<= NumBits;
res |= Val;
numBits -= NumBits;
NumBits = 0;
}
}
return res;
}
HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback)
{
RINOK(_item.ReadHeader(stream))
if (!_item.IsUncompressed())
return S_FALSE;
CInBuffer s;
if (!s.Create(1 << 20))
return E_OUTOFMEMORY;
s.SetStream(stream);
s.Init();
{
CBitReader br;
br.stream = &s;
unsigned numBits = br.ReadBits(5);
/* UInt32 xMin = */ br.ReadBits(numBits);
/* UInt32 xMax = */ br.ReadBits(numBits);
/* UInt32 yMin = */ br.ReadBits(numBits);
/* UInt32 yMax = */ br.ReadBits(numBits);
}
/* UInt32 frameDelay = */ Read16(s);
/* UInt32 numFrames = */ Read16(s);
_tags.Clear();
UInt64 offsetPrev = 0;
for (;;)
{
UInt32 pair = Read16(s);
UInt32 type = pair >> 6;
UInt32 length = pair & 0x3F;
if (length == 0x3F)
length = Read32(s);
if (type == 0)
break;
UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderSize + length;
if (offset > kFileSizeMax || _tags.Size() >= kNumTagsMax)
return S_FALSE;
_tags.Add(CTag());
CTag &tag = _tags.Back();
tag.Type = type;
tag.Buf.SetCapacity(length);
if (s.ReadBytes(tag.Buf, length) != length)
return S_FALSE;
if (callback && offset >= offsetPrev + (1 << 20))
{
UInt64 numItems = _tags.Size();
RINOK(callback->SetCompleted(&numItems, &offset));
offsetPrev = offset;
}
}
_packSize = s.GetProcessedSize() + NSwfc::kHeaderSize;
return S_OK;
}
HRESULT CHandler::OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback)
{
HRESULT res;
try { res = OpenSeq3(stream, callback); }
catch(...) { res = S_FALSE; }
return res;
}
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
{
return OpenSeq2(stream, NULL);
}
STDMETHODIMP CHandler::Close()
{
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
numItems = _tags.Size();
if (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
totalSize += _tags[allFilesMode ? i : indices[i]].Buf.GetCapacity();
extractCallback->SetTotal(totalSize);
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
totalSize = 0;
for (i = 0; i < numItems; i++)
{
lps->InSize = lps->OutSize = totalSize;
RINOK(lps->SetCur());
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i];
const CByteBuffer &buf = _tags[index].Buf;
totalSize += buf.GetCapacity();
CMyComPtr<ISequentialOutStream> outStream;
RINOK(extractCallback->GetStream(index, &outStream, askMode));
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (outStream)
RINOK(WriteStream(outStream, buf, buf.GetCapacity()));
outStream.Release();
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
}
return S_OK;
COM_TRY_END
}
static IInArchive *CreateArc() { return new CHandler; }
static CArcInfo g_ArcInfo =
{ L"SWF", L"swf", 0, 0xD7, { 'F', 'W', 'S' }, 3, true, CreateArc, 0 };
REGISTER_ARC(Swf)
}}

View File

@@ -227,8 +227,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems, HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback) Int32 testMode, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
ISequentialInStream *stream = _seqStream; ISequentialInStream *stream = _seqStream;
@@ -236,7 +236,6 @@ HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (!seqMode) if (!seqMode)
stream = _stream; stream = _stream;
bool testMode = (_aTestMode != 0);
bool allFilesMode = (numItems == (UInt32)-1); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = _items.Size(); numItems = _items.Size();
@@ -269,8 +268,8 @@ HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(lps->SetCur()); RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
const CItemEx *item; const CItemEx *item;
if (seqMode) if (seqMode)
@@ -290,7 +289,7 @@ HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (item->IsDir()) if (item->IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
bool skipMode = false; bool skipMode = false;
@@ -299,7 +298,7 @@ HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems,
if (!seqMode) if (!seqMode)
continue; continue;
skipMode = true; skipMode = true;
askMode = NArchive::NExtract::NAskMode::kSkip; askMode = NExtract::NAskMode::kSkip;
} }
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -320,8 +319,8 @@ HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems,
} }
outStreamSpec->ReleaseStream(); outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ? RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ?
NArchive::NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError)); NExtract::NOperationResult::kDataError));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View File

@@ -13,6 +13,6 @@ static IOutArchive *CreateArcOut() { return new NArchive::NTar::CHandler; }
#endif #endif
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"Tar", L"tar", 0, 0xEE, { 'u', 's', 't', 'a', 'r' }, 5, false, CreateArc, CreateArcOut }; { L"tar", L"tar", 0, 0xEE, { 'u', 's', 't', 'a', 'r' }, 5, false, CreateArc, CreateArcOut };
REGISTER_ARC(Tar) REGISTER_ARC(Tar)

Some files were not shown because too many files have changed in this diff Show More