This commit is contained in:
Igor Pavlov
2015-08-16 00:00:00 +00:00
committed by Kornel Lesiński
parent 54490d51d5
commit cba375916f
152 changed files with 6544 additions and 2001 deletions

View File

@@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder
2015-06-13 : Igor Pavlov : Public domain */
2015-08-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -144,11 +144,11 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
for (;;)
{
Byte *inBuf = NULL;
const void *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
res = inStream->Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK)
break;
@@ -197,11 +197,11 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
for (;;)
{
Byte *inBuf = NULL;
const void *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
res = inStream->Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK)
break;
@@ -237,11 +237,11 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
{
while (inSize > 0)
{
void *inBuf;
const void *inBuf;
size_t curSize = (1 << 18);
if (curSize > inSize)
curSize = (size_t)inSize;
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
RINOK(inStream->Look(inStream, &inBuf, &curSize));
if (curSize == 0)
return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize);

View File

@@ -1,10 +1,12 @@
#define MY_VER_MAJOR 15
#define MY_VER_MINOR 05
#define MY_VER_MINOR 06
#define MY_VER_BUILD 00
#define MY_VERSION "15.05 beta"
#define MY_DATE "2015-06-14"
#define MY_VERSION_NUMBERS "15.06"
#define MY_VERSION "15.06 beta"
#define MY_DATE "2015-08-09"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"

View File

@@ -1,5 +1,5 @@
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
2014-11-09 : Igor Pavlov : Public domain */
2015-08-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -178,8 +178,8 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
p->state =
p->bufs[BCJ2_STREAM_MAIN] ==
p->lims[BCJ2_STREAM_MAIN] ?
BCJ2_STREAM_MAIN :
BCJ2_DEC_STATE_ORIG;
(unsigned)BCJ2_STREAM_MAIN :
(unsigned)BCJ2_DEC_STATE_ORIG;
return SZ_OK;
}

48
C/Blake2.h Normal file
View File

@@ -0,0 +1,48 @@
/* Blake2.h -- BLAKE2 Hash
2015-06-30 : Igor Pavlov : Public domain
2015 : Samuel Neves : Public domain */
#ifndef __BLAKE2_H
#define __BLAKE2_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define BLAKE2S_BLOCK_SIZE 64
#define BLAKE2S_DIGEST_SIZE 32
#define BLAKE2SP_PARALLEL_DEGREE 8
typedef struct
{
UInt32 h[8];
UInt32 t[2];
UInt32 f[2];
Byte buf[BLAKE2S_BLOCK_SIZE];
UInt32 bufPos;
UInt32 lastNode_f1;
UInt32 dummy[2]; /* for sizeof(CBlake2s) alignment */
} CBlake2s;
/* You need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
/*
void Blake2s_Init0(CBlake2s *p);
void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size);
void Blake2s_Final(CBlake2s *p, Byte *digest);
*/
typedef struct
{
CBlake2s S[BLAKE2SP_PARALLEL_DEGREE];
unsigned bufPos;
} CBlake2sp;
void Blake2sp_Init(CBlake2sp *p);
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);
void Blake2sp_Final(CBlake2sp *p, Byte *digest);
EXTERN_C_END
#endif

244
C/Blake2s.c Normal file
View File

@@ -0,0 +1,244 @@
/* Blake2s.c -- BLAKE2s and BLAKE2sp Hash
2015-06-30 : Igor Pavlov : Public domain
2015 : Samuel Neves : Public domain */
#include <string.h>
#include "Blake2.h"
#include "CpuArch.h"
#include "RotateDefs.h"
#define rotr32 rotrFixed
#define BLAKE2S_NUM_ROUNDS 10
#define BLAKE2S_FINAL_FLAG (~(UInt32)0)
static const UInt32 k_Blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const Byte k_Blake2s_Sigma[BLAKE2S_NUM_ROUNDS][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
};
void Blake2s_Init0(CBlake2s *p)
{
unsigned i;
for (i = 0; i < 8; i++)
p->h[i] = k_Blake2s_IV[i];
p->t[0] = 0;
p->t[1] = 0;
p->f[0] = 0;
p->f[1] = 0;
p->bufPos = 0;
p->lastNode_f1 = 0;
}
static void Blake2s_Compress(CBlake2s *p)
{
UInt32 m[16];
UInt32 v[16];
{
unsigned i;
for (i = 0; i < 16; i++)
m[i] = GetUi32(p->buf + i * sizeof(m[i]));
for (i = 0; i < 8; i++)
v[i] = p->h[i];
}
v[ 8] = k_Blake2s_IV[0];
v[ 9] = k_Blake2s_IV[1];
v[10] = k_Blake2s_IV[2];
v[11] = k_Blake2s_IV[3];
v[12] = p->t[0] ^ k_Blake2s_IV[4];
v[13] = p->t[1] ^ k_Blake2s_IV[5];
v[14] = p->f[0] ^ k_Blake2s_IV[6];
v[15] = p->f[1] ^ k_Blake2s_IV[7];
#define G(r,i,a,b,c,d) \
a += b + m[sigma[2*i+0]]; d ^= a; d = rotr32(d, 16); c += d; b ^= c; b = rotr32(b, 12); \
a += b + m[sigma[2*i+1]]; d ^= a; d = rotr32(d, 8); c += d; b ^= c; b = rotr32(b, 7); \
#define R(r) \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
{
unsigned r;
for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++)
{
const Byte *sigma = k_Blake2s_Sigma[r];
R(r);
}
/* R(0); R(1); R(2); R(3); R(4); R(5); R(6); R(7); R(8); R(9); */
}
#undef G
#undef R
{
unsigned i;
for (i = 0; i < 8; i++)
p->h[i] ^= v[i] ^ v[i + 8];
}
}
#define Blake2s_Increment_Counter(S, inc) \
{ p->t[0] += (inc); p->t[1] += (p->t[0] < (inc)); }
#define Blake2s_Set_LastBlock(p) \
{ p->f[0] = BLAKE2S_FINAL_FLAG; p->f[1] = p->lastNode_f1; }
static void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size)
{
while (size != 0)
{
unsigned pos = (unsigned)p->bufPos;
unsigned rem = BLAKE2S_BLOCK_SIZE - pos;
if (size <= rem)
{
memcpy(p->buf + pos, data, size);
p->bufPos += (UInt32)size;
return;
}
memcpy(p->buf + pos, data, rem);
Blake2s_Increment_Counter(S, BLAKE2S_BLOCK_SIZE);
Blake2s_Compress(p);
p->bufPos = 0;
data += rem;
size -= rem;
}
}
static void Blake2s_Final(CBlake2s *p, Byte *digest)
{
unsigned i;
Blake2s_Increment_Counter(S, (UInt32)p->bufPos);
Blake2s_Set_LastBlock(p);
memset(p->buf + p->bufPos, 0, BLAKE2S_BLOCK_SIZE - p->bufPos);
Blake2s_Compress(p);
for (i = 0; i < 8; i++)
SetUi32(digest + sizeof(p->h[i]) * i, p->h[i]);
}
/* ---------- BLAKE2s ---------- */
/* we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
/*
typedef struct
{
Byte digest_length;
Byte key_length;
Byte fanout;
Byte depth;
UInt32 leaf_length;
Byte node_offset[6];
Byte node_depth;
Byte inner_length;
Byte salt[BLAKE2S_SALTBYTES];
Byte personal[BLAKE2S_PERSONALBYTES];
} CBlake2sParam;
*/
static void Blake2sp_Init_Spec(CBlake2s *p, unsigned node_offset, unsigned node_depth)
{
Blake2s_Init0(p);
p->h[0] ^= (BLAKE2S_DIGEST_SIZE | ((UInt32)BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24));
p->h[2] ^= ((UInt32)node_offset);
p->h[3] ^= ((UInt32)node_depth << 16) | ((UInt32)BLAKE2S_DIGEST_SIZE << 24);
/*
P->digest_length = BLAKE2S_DIGEST_SIZE;
P->key_length = 0;
P->fanout = BLAKE2SP_PARALLEL_DEGREE;
P->depth = 2;
P->leaf_length = 0;
store48(P->node_offset, node_offset);
P->node_depth = node_depth;
P->inner_length = BLAKE2S_DIGEST_SIZE;
*/
}
void Blake2sp_Init(CBlake2sp *p)
{
unsigned i;
p->bufPos = 0;
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
Blake2sp_Init_Spec(&p->S[i], i, 0);
p->S[BLAKE2SP_PARALLEL_DEGREE - 1].lastNode_f1 = BLAKE2S_FINAL_FLAG;
}
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size)
{
unsigned pos = p->bufPos;
while (size != 0)
{
unsigned index = pos / BLAKE2S_BLOCK_SIZE;
unsigned rem = BLAKE2S_BLOCK_SIZE - (pos & (BLAKE2S_BLOCK_SIZE - 1));
if (rem > size)
rem = (unsigned)size;
Blake2s_Update(&p->S[index], data, rem);
size -= rem;
data += rem;
pos += rem;
pos &= (BLAKE2S_BLOCK_SIZE * BLAKE2SP_PARALLEL_DEGREE - 1);
}
p->bufPos = pos;
}
void Blake2sp_Final(CBlake2sp *p, Byte *digest)
{
CBlake2s R;
unsigned i;
Blake2sp_Init_Spec(&R, 0, 1);
R.lastNode_f1 = BLAKE2S_FINAL_FLAG;
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
{
Byte hash[BLAKE2S_DIGEST_SIZE];
Blake2s_Final(&p->S[i], hash);
Blake2s_Update(&R, hash, BLAKE2S_DIGEST_SIZE);
}
Blake2s_Final(&R, digest);
}

View File

@@ -1,5 +1,5 @@
/* Compiler.h
2015-03-25 : Igor Pavlov : Public domain */
2015-08-02 : Igor Pavlov : Public domain */
#ifndef __7Z_COMPILER_H
#define __7Z_COMPILER_H
@@ -18,6 +18,7 @@
#else
#pragma warning(disable : 4511) // copy constructor could not be generated
#pragma warning(disable : 4512) // assignment operator could not be generated
#pragma warning(disable : 4514) // unreferenced inline function has been removed
#pragma warning(disable : 4702) // unreachable code
#pragma warning(disable : 4710) // not inlined
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
2015-03-25: Igor Pavlov : Public domain */
2015-08-02: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
@@ -90,9 +90,10 @@ Stop_Compiling_Bad_Endian
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
#define SetUi16(p, v) *(UInt16 *)(p) = (v);
#define SetUi32(p, v) *(UInt32 *)(p) = (v);
#define SetUi64(p, v) *(UInt64 *)(p) = (v);
#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
#else

View File

@@ -1,5 +1,5 @@
/* LzmaDec.c -- LZMA Decoder
2015-05-14 : Igor Pavlov : Public domain */
2015-06-23 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -438,10 +438,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (checkDicSize == 0)
{
if (distance >= processedPos)
{
p->dicPos = dicPos;
return SZ_ERROR_DATA;
}
}
else if (distance >= checkDicSize)
{
p->dicPos = dicPos;
return SZ_ERROR_DATA;
}
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
}
@@ -453,7 +459,10 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
SizeT pos;
if ((rem = limit - dicPos) == 0)
{
p->dicPos = dicPos;
return SZ_ERROR_DATA;
}
curLen = ((rem < len) ? (unsigned)rem : len);
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);

View File

@@ -1,5 +1,5 @@
/* 7zMain.c - Test application for 7z Decoder
2015-05-11 : Igor Pavlov : Public domain */
2015-08-02 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -328,22 +328,20 @@ void PrintError(char *sz)
printf("\nERROR: %s\n", sz);
}
#ifdef USE_WINDOWS_FILE
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
{
#ifdef USE_WINDOWS_FILE
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.');
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.');
s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.');
s[5] = '\0';
s[5] = 0;
#else
s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.');
s[1] = 0;
#endif
}
#else
static void GetAttribString(UInt32, Bool, char *s)
{
s[0] = '\0';
}
#endif
// #define NUM_PARENTS_MAX 128

View File

@@ -1,10 +1,10 @@
PROG = 7zDec
CXX = g++
CXX = gcc
LIB =
RM = rm -f
CFLAGS = -c -O2 -Wall
OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o Delta.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o BraIA64.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
all: $(PROG)
@@ -38,6 +38,9 @@ $(PROG): $(OBJS)
CpuArch.o: ../../CpuArch.c
$(CXX) $(CFLAGS) ../../CpuArch.c
Delta.o: ../../Delta.c
$(CXX) $(CFLAGS) ../../Delta.c
LzmaDec.o: ../../LzmaDec.c
$(CXX) $(CFLAGS) ../../LzmaDec.c
@@ -50,6 +53,9 @@ Bra.o: ../../Bra.c
Bra86.o: ../../Bra86.c
$(CXX) $(CFLAGS) ../../Bra86.c
BraIA64.o: ../../BraIA64.c
$(CXX) $(CFLAGS) ../../BraIA64.c
Bcj2.o: ../../Bcj2.c
$(CXX) $(CFLAGS) ../../Bcj2.c

View File

@@ -1,5 +1,5 @@
/* 7zipInnstall.c - 7-Zip Installer
2015-06-13 : Igor Pavlov : Public domain */
/* 7zipInstall.c - 7-Zip Installer
2015-08-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -37,7 +37,7 @@ static const WCHAR *k_Reg_Software_7zip = L"Software\\7-Zip";
#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
#ifdef _64BIT_INSTALLER
#define k_7zip_with_Ver k_7zip_with_Ver_base L" x64"
#define k_7zip_with_Ver k_7zip_with_Ver_base L" (x64)"
#else
#define k_7zip_with_Ver k_7zip_with_Ver_base
#endif
@@ -84,6 +84,8 @@ static HWND g_Path_HWND;
static HWND g_InfoLine_HWND;
static HWND g_Progress_HWND;
static DWORD g_TotalSize;
static WCHAR path[MAX_PATH * 2 + 40];
@@ -143,7 +145,7 @@ static WRes CreateComplexDir()
if (IS_DRIVE_PATH(s))
prefixSize = 3;
else if (IS_SEPAR(s[1]) && IS_SEPAR(s[1]))
else if (IS_SEPAR(s[0]) && IS_SEPAR(s[1]))
prefixSize = 2;
else
return ERROR_INVALID_NAME;
@@ -796,16 +798,30 @@ static void WriteShellEx()
// wcscpy(destPath, path);
// wcscat(destPath, L"7zFM.exe");
MyRegistry_SetString(destKey, L"DisplayName", k_7zip_with_Ver_str);
MyRegistry_SetString(destKey, L"DisplayVersion", LLL(MY_VERSION_NUMBERS));
MyRegistry_SetString(destKey, L"DisplayIcon", destPath);
wcscpy(destPath, path);
// MyRegistry_SetString(destKey, L"InstallLocation", destPath);
MyRegistry_SetString(destKey, L"InstallLocation", destPath);
wcscat(destPath, L"Uninstall.exe");
// wcscat(destPath, L"\"");
MyRegistry_SetString(destKey, L"UninstallString", destPath);
MyRegistry_SetDWORD(destKey, L"NoModify", 1);
MyRegistry_SetDWORD(destKey, L"NoRepair", 1);
MyRegistry_SetDWORD(destKey, L"EstimatedSize", g_TotalSize >> 10);
MyRegistry_SetDWORD(destKey, L"VersionMajor", MY_VER_MAJOR);
MyRegistry_SetDWORD(destKey, L"VersionMinor", MY_VER_MINOR);
MyRegistry_SetString(destKey, L"Publisher", LLL(MY_AUTHOR_NAME));
// MyRegistry_SetString(destKey, L"HelpLink", L"http://www.7-zip.org/support.html");
// MyRegistry_SetString(destKey, L"URLInfoAbout", L"http://www.7-zip.org/");
// MyRegistry_SetString(destKey, L"URLUpdateInfo", L"http://www.7-zip.org/");
RegCloseKey(destKey);
}
}
@@ -1108,6 +1124,23 @@ if (res == SZ_OK)
FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False);
{
// Remove post spaces
unsigned endPos = 0;
unsigned i = 0;
for (;;)
{
wchar_t c = path[i++];
if (c == 0)
break;
if (c != ' ')
endPos = i;
}
path[endPos] = 0;
}
NormalizePrefix(path);
winRes = CreateComplexDir();
@@ -1132,6 +1165,8 @@ if (res == SZ_OK)
Byte *outBuf = NULL; /* it must be NULL before first call for each new archive. */
size_t outBufSize = 0; /* it can have any value before first call, if(!outBuf) */
g_TotalSize = 0;
if (!g_SilentMode)
{
ShowWindow(g_Progress_HWND, SW_SHOW);
@@ -1309,6 +1344,8 @@ if (res == SZ_OK)
res = SZ_ERROR_FAIL;
}
g_TotalSize += (DWORD)outSizeProcessed;
#ifdef USE_WINDOWS_FILE
if (SzBitWithVals_Check(&db.MTime, i))
{

View File

@@ -1,5 +1,5 @@
/* 7zipUninstall.c - 7-Zip Uninstaller
2015-06-13 : Igor Pavlov : Public domain */
2015-08-09 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -31,7 +31,7 @@
#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
#ifdef _64BIT_INSTALLER
#define k_7zip_with_Ver k_7zip_with_Ver_base L" x64"
#define k_7zip_with_Ver k_7zip_with_Ver_base L" (x64)"
#else
#define k_7zip_with_Ver k_7zip_with_Ver_base
#endif

View File

@@ -301,6 +301,12 @@ HRESULT CDecoder::Decode(
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
#ifndef _SFX
// we don't support RAR codecs here
if ((coderInfo.MethodID >> 8) == 0x403)
return E_NOTIMPL;
#endif
CCreatedCoder cod;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS

View File

@@ -44,6 +44,7 @@ public:
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
bool _useTypeSorting;
bool _compressHeaders;
bool _encryptHeadersSpecified;

View File

@@ -507,6 +507,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.Name = name;
if (ui.NewData)
{
ui.Size = 0;
if (!ui.IsDir)
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
@@ -516,6 +519,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.Size != 0 && ui.IsAnti)
return E_INVALIDARG;
}
}
updateItems.Add(ui);
}
@@ -613,6 +618,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.NumSolidFiles = _numSolidFiles;
options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension;
options.UseTypeSorting = _useTypeSorting;
options.RemoveSfxBlock = _removeSfxBlock;
// options.VolumeMode = _volumeMode;
@@ -701,6 +708,7 @@ void COutHandler::InitProps()
// _volumeMode = false;
InitSolid();
_useTypeSorting = false;
}
HRESULT COutHandler::SetSolidFromString(const UString &s)
@@ -821,6 +829,8 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
}
return CMultiMethodProps::SetProperty(name, value);

View File

@@ -554,11 +554,11 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param
}
static const char *g_Exts =
" lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"
" 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo"
" zip jar ear war msi"
" 3gp avi mov mpeg mpg mpe wmv"
" aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
" swf "
" swf"
" chm hxi hxs"
" gif jpeg jpg jp2 png tiff bmp ico psd psp"
" awg ps eps cgm dxf svg vrml wmf emf ai md"
@@ -569,9 +569,9 @@ static const char *g_Exts =
" vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
" inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"
" f77 f f90 f95"
" asm sql manifest dep "
" mak clw csproj vcproj sln dsp dsw "
" class "
" asm sql manifest dep"
" mak clw csproj vcproj sln dsp dsw"
" class"
" bat cmd"
" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
" awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
@@ -580,7 +580,7 @@ static const char *g_Exts =
" abw afp cwk lwp wpd wps wpt wrf wri"
" abf afm bdf fon mgf otf pcf pfa snf ttf"
" dbf mdb nsf ntf wdb db fdb gdb"
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so"
" pdb pch idb ncb opt";
static unsigned GetExtIndex(const char *ext)
@@ -2251,7 +2251,7 @@ HRESULT Update(
continue;
CRecordVector<CRefItem> refItems;
refItems.ClearAndSetSize(numFiles);
bool sortByType = (numSolidFiles > 1);
bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
for (i = 0; i < numFiles; i++)
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
CSortParam sortParam;

View File

@@ -97,6 +97,9 @@ struct CUpdateOptions
UInt64 NumSolidFiles;
UInt64 NumSolidBytes;
bool SolidExtension;
bool UseTypeSorting;
bool RemoveSfxBlock;
bool MultiThreadMixer;
@@ -109,6 +112,7 @@ struct CUpdateOptions
NumSolidFiles((UInt64)(Int64)(-1)),
NumSolidBytes((UInt64)(Int64)(-1)),
SolidExtension(false),
UseTypeSorting(true),
RemoveSfxBlock(false),
MultiThreadMixer(true)
{}

View File

@@ -1,5 +1,5 @@
PROG = 7z.dll
DEF_FILE = ../../Archive/Archive2.def
DEF_FILE = ../Archive.def
CFLAGS = $(CFLAGS) \
-DEXTERNAL_CODECS \
@@ -60,9 +60,11 @@ WIN_OBJS = \
$O\StreamUtils.obj \
$O\VirtThread.obj \
COMPRESS_OBJS = \
$O\CopyCoder.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
@@ -76,4 +78,6 @@ C_OBJS = \
$O\CpuArch.obj \
$O\Threads.obj \
!include "../../Crc.mak"
!include "../../7zip.mak"

View File

@@ -1,19 +0,0 @@
// CoderMixer.cpp
#include "StdAfx.h"
#include "CoderMixer.h"
namespace NCoderMixer {
void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize)
{
InSizeAssigned = (inSize != 0);
if (InSizeAssigned)
InSizeValue = *inSize;
OutSizeAssigned = (outSize != 0);
if (OutSizeAssigned)
OutSizeValue = *outSize;
}
}

View File

@@ -1,32 +0,0 @@
// CoderMixer.h
#ifndef __CODER_MIXER_H
#define __CODER_MIXER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
namespace NCoderMixer {
struct CCoderInfo
{
CMyComPtr<ICompressCoder> Coder;
CMyComPtr<ISequentialInStream> InStream;
CMyComPtr<ISequentialOutStream> OutStream;
CMyComPtr<ICompressProgressInfo> Progress;
UInt64 InSizeValue;
UInt64 OutSizeValue;
bool InSizeAssigned;
bool OutSizeAssigned;
void ReInit()
{
InSizeAssigned = OutSizeAssigned = false;
}
void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize);
};
}
#endif

View File

@@ -1,254 +0,0 @@
// CoderMixer2MT.cpp
#include "StdAfx.h"
#include "CoderMixer2MT.h"
namespace NCoderMixer2 {
void CCoderMT::Execute() { Code(NULL); }
void CCoderMT::Code(ICompressProgressInfo *progress)
{
unsigned numInStreams = EncodeMode ? 1 : NumStreams;
unsigned numOutStreams = EncodeMode ? NumStreams : 1;
InStreamPointers.ClearAndReserve(numInStreams);
OutStreamPointers.ClearAndReserve(numOutStreams);
unsigned i;
for (i = 0; i < numInStreams; i++)
InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
for (i = 0; i < numOutStreams; i++)
OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
// we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
/*
if (UnpackSizePointer)
UnpackSizePointer = &UnpackSize;
for (i = 0; i < NumStreams; i++)
if (PackSizePointers[i])
PackSizePointers[i] = &PackSizes[i];
*/
if (Coder)
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
EncodeMode ? UnpackSizePointer : PackSizePointers[0],
EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
progress);
else
Result = Coder2->Code(
&InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
&OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
progress);
InStreamPointers.Clear();
OutStreamPointers.Clear();
for (i = 0; i < InStreams.Size(); i++)
InStreams[i].Release();
for (i = 0; i < OutStreams.Size(); i++)
OutStreams[i].Release();
}
HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
{
CMixer::SetBindInfo(bindInfo);
_streamBinders.Clear();
FOR_VECTOR (i, _bi.Bonds)
{
RINOK(_streamBinders.AddNew().CreateEvents());
}
return S_OK;
}
void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
{
const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
CCoderMT &c2 = _coders.AddNew();
c2.NumStreams = c.NumStreams;
c2.EncodeMode = EncodeMode;
c2.Coder = coder;
c2.Coder2 = coder2;
IsFilter_Vector.Add(isFilter);
}
CCoder &CMixerMT::GetCoder(unsigned index)
{
return _coders[index];
}
void CMixerMT::ReInit()
{
FOR_VECTOR (i, _streamBinders)
_streamBinders[i].ReInit();
}
void CMixerMT::SelectMainCoder(bool useFirst)
{
unsigned ci = _bi.UnpackCoder;
if (!useFirst)
for (;;)
{
if (_coders[ci].NumStreams != 1)
break;
if (!IsFilter_Vector[ci])
break;
UInt32 st = _bi.Coder_to_Stream[ci];
if (_bi.IsStream_in_PackStreams(st))
break;
int bond = _bi.FindBond_for_PackStream(st);
if (bond < 0)
throw 20150213;
ci = _bi.Bonds[bond].UnpackIndex;
}
MainCoderIndex = ci;
}
HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
{
unsigned i;
for (i = 0; i < _coders.Size(); i++)
{
CCoderMT &coderInfo = _coders[i];
const CCoderStreamsInfo &csi = _bi.Coders[i];
UInt32 j;
unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
coderInfo.InStreams.Clear();
for (j = 0; j < numInStreams; j++)
coderInfo.InStreams.AddNew();
coderInfo.OutStreams.Clear();
for (j = 0; j < numOutStreams; j++)
coderInfo.OutStreams.AddNew();
}
for (i = 0; i < _bi.Bonds.Size(); i++)
{
const CBond &bond = _bi.Bonds[i];
UInt32 inCoderIndex, inCoderStreamIndex;
UInt32 outCoderIndex, outCoderStreamIndex;
{
UInt32 coderIndex, coderStreamIndex;
_bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
}
_streamBinders[i].CreateStreams(
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
&_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
_coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
_coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
if (inSetSize && outSetSize)
{
const UInt32 kBufSize = 1 << 19;
inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
}
}
{
CCoderMT &cod = _coders[_bi.UnpackCoder];
if (EncodeMode)
cod.InStreams[0] = inStreams[0];
else
cod.OutStreams[0] = outStreams[0];
}
for (i = 0; i < _bi.PackStreams.Size(); i++)
{
UInt32 coderIndex, coderStreamIndex;
_bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
CCoderMT &cod = _coders[coderIndex];
if (EncodeMode)
cod.OutStreams[coderStreamIndex] = outStreams[i];
else
cod.InStreams[coderStreamIndex] = inStreams[i];
}
return S_OK;
}
HRESULT CMixerMT::ReturnIfError(HRESULT code)
{
FOR_VECTOR (i, _coders)
if (_coders[i].Result == code)
return code;
return S_OK;
}
HRESULT CMixerMT::Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress)
{
Init(inStreams, outStreams);
unsigned i;
for (i = 0; i < _coders.Size(); i++)
if (i != MainCoderIndex)
{
RINOK(_coders[i].Create());
}
for (i = 0; i < _coders.Size(); i++)
if (i != MainCoderIndex)
_coders[i].Start();
_coders[MainCoderIndex].Code(progress);
for (i = 0; i < _coders.Size(); i++)
if (i != MainCoderIndex)
_coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
RINOK(ReturnIfError(E_OUTOFMEMORY));
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
if (result != S_OK
&& result != k_My_HRESULT_WritingWasCut
&& result != S_FALSE
&& result != E_FAIL)
return result;
}
RINOK(ReturnIfError(S_FALSE));
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
return result;
}
return S_OK;
}
UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
{
return _streamBinders[bondIndex].ProcessedSize;
}
}

View File

@@ -1,77 +0,0 @@
// CoderMixer2MT.h
#ifndef __CODER_MIXER2_MT_H
#define __CODER_MIXER2_MT_H
#include "../../../Common/MyCom.h"
#include "../../Common/StreamBinder.h"
#include "../../Common/VirtThread.h"
#include "CoderMixer2.h"
namespace NCoderMixer2 {
class CCoderMT: public CCoder, public CVirtThread
{
CLASS_NO_COPY(CCoderMT)
CRecordVector<ISequentialInStream*> InStreamPointers;
CRecordVector<ISequentialOutStream*> OutStreamPointers;
private:
void Execute();
public:
bool EncodeMode;
HRESULT Result;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
CCoderMT(): EncodeMode(false) {}
~CCoderMT() { CVirtThread::WaitThreadFinish(); }
void Code(ICompressProgressInfo *progress);
};
class CMixerMT:
public IUnknown,
public CMixer,
public CMyUnknownImp
{
CObjectVector<CStreamBinder> _streamBinders;
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
HRESULT ReturnIfError(HRESULT code);
public:
CObjectVector<CCoderMT> _coders;
MY_UNKNOWN_IMP
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual void ReInit();
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
};
}
#endif

View File

@@ -1,562 +0,0 @@
// CoderMixer2ST.cpp
#include "StdAfx.h"
#include "CoderMixer2ST.h"
STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessed = 0;
HRESULT result = S_OK;
if (_stream)
result = _stream->Read(data, size, &realProcessed);
_size += realProcessed;
if (size != 0 && realProcessed == 0)
_wasFinished = true;
if (processedSize)
*processedSize = realProcessed;
return result;
}
STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
HRESULT result = S_OK;
if (_stream)
result = _stream->Write(data, size, &size);
_size += size;
if (processedSize)
*processedSize = size;
return result;
}
STDMETHODIMP COutStreamCalcSize::Flush()
{
HRESULT result = S_OK;
if (_stream)
{
CMyComPtr<IOutStreamFlush> outStreamFlush;
_stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush);
if (outStreamFlush)
result = outStreamFlush->Flush();;
}
return result;
}
namespace NCoderMixer2 {
CMixerST::CMixerST(bool encodeMode):
CMixer(encodeMode)
{}
CMixerST::~CMixerST() {}
void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
{
IsFilter_Vector.Add(isFilter);
const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
CCoderST &c2 = _coders.AddNew();
c2.NumStreams = c.NumStreams;
c2.Coder = coder;
c2.Coder2 = coder2;
/*
if (isFilter)
{
c2.CanRead = true;
c2.CanWrite = true;
}
else
*/
{
IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2);
{
CMyComPtr<ISequentialInStream> s;
unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
c2.CanRead = (s != NULL);
}
{
CMyComPtr<ISequentialOutStream> s;
unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
c2.CanWrite = (s != NULL);
}
}
}
CCoder &CMixerST::GetCoder(unsigned index)
{
return _coders[index];
}
void CMixerST::ReInit() {}
HRESULT CMixerST::GetInStream2(
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
{
UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
if (EncodeMode)
{
_bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
if (coderStreamIndex != 0)
return E_NOTIMPL;
}
const CCoder &coder = _coders[coderIndex];
CMyComPtr<ISequentialInStream> seqInStream;
coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
if (!seqInStream)
return E_NOTIMPL;
UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
bool isSet = false;
if (numInStreams == 1)
{
CMyComPtr<ICompressSetInStream> setStream;
coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
if (setStream)
{
CMyComPtr<ISequentialInStream> seqInStream2;
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
RINOK(setStream->SetInStream(seqInStream2));
isSet = true;
}
}
if (!isSet && numInStreams != 0)
{
CMyComPtr<ICompressSetInStream2> setStream2;
coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
if (!setStream2)
return E_NOTIMPL;
for (UInt32 i = 0; i < numInStreams; i++)
{
CMyComPtr<ISequentialInStream> seqInStream2;
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
RINOK(setStream2->SetInStream2(i, seqInStream2));
}
}
*inStreamRes = seqInStream.Detach();
return S_OK;
}
HRESULT CMixerST::GetInStream(
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
{
CMyComPtr<ISequentialInStream> seqInStream;
{
int index = -1;
if (EncodeMode)
{
if (_bi.UnpackCoder == inStreamIndex)
index = 0;
}
else
index = _bi.FindStream_in_PackStreams(inStreamIndex);
if (index >= 0)
{
seqInStream = inStreams[index];
*inStreamRes = seqInStream.Detach();
return S_OK;
}
}
int bond = FindBond_for_Stream(
true, // forInputStream
inStreamIndex);
if (bond < 0)
return E_INVALIDARG;
RINOK(GetInStream2(inStreams, /* inSizes, */
_bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
while (_binderStreams.Size() <= (unsigned)bond)
_binderStreams.AddNew();
CStBinderStream &bs = _binderStreams[bond];
if (bs.StreamRef || bs.InStreamSpec)
return E_NOTIMPL;
CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
bs.StreamRef = spec;
bs.InStreamSpec = spec;
spec->SetStream(seqInStream);
spec->Init();
seqInStream = bs.InStreamSpec;
*inStreamRes = seqInStream.Detach();
return S_OK;
}
HRESULT CMixerST::GetOutStream(
ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
{
CMyComPtr<ISequentialOutStream> seqOutStream;
{
int index = -1;
if (!EncodeMode)
{
if (_bi.UnpackCoder == outStreamIndex)
index = 0;
}
else
index = _bi.FindStream_in_PackStreams(outStreamIndex);
if (index >= 0)
{
seqOutStream = outStreams[index];
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
}
int bond = FindBond_for_Stream(
false, // forInputStream
outStreamIndex);
if (bond < 0)
return E_INVALIDARG;
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
UInt32 coderIndex = inStreamIndex;
UInt32 coderStreamIndex = 0;
if (!EncodeMode)
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
CCoder &coder = _coders[coderIndex];
/*
if (!coder.Coder)
return E_NOTIMPL;
*/
coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
if (!seqOutStream)
return E_NOTIMPL;
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
bool isSet = false;
if (numOutStreams == 1)
{
CMyComPtr<ICompressSetOutStream> setOutStream;
coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
if (setOutStream)
{
CMyComPtr<ISequentialOutStream> seqOutStream2;
RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
RINOK(setOutStream->SetOutStream(seqOutStream2));
isSet = true;
}
}
if (!isSet && numOutStreams != 0)
{
// return E_NOTIMPL;
// /*
CMyComPtr<ICompressSetOutStream2> setStream2;
coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
if (!setStream2)
return E_NOTIMPL;
for (UInt32 i = 0; i < numOutStreams; i++)
{
CMyComPtr<ISequentialOutStream> seqOutStream2;
RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
RINOK(setStream2->SetOutStream2(i, seqOutStream2));
}
// */
}
while (_binderStreams.Size() <= (unsigned)bond)
_binderStreams.AddNew();
CStBinderStream &bs = _binderStreams[bond];
if (bs.StreamRef || bs.OutStreamSpec)
return E_NOTIMPL;
COutStreamCalcSize *spec = new COutStreamCalcSize;
bs.StreamRef = (ISequentialOutStream *)spec;
bs.OutStreamSpec = spec;
spec->SetStream(seqOutStream);
spec->Init();
seqOutStream = bs.OutStreamSpec;
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
static HRESULT GetError(HRESULT res, HRESULT res2)
{
if (res == res2)
return res;
if (res == S_OK)
return res2;
if (res == k_My_HRESULT_WritingWasCut)
{
if (res2 != S_OK)
return res2;
}
return res;
}
HRESULT CMixerST::FlushStream(UInt32 streamIndex)
{
{
int index = -1;
if (!EncodeMode)
{
if (_bi.UnpackCoder == streamIndex)
index = 0;
}
else
index = _bi.FindStream_in_PackStreams(streamIndex);
if (index >= 0)
return S_OK;
}
int bond = FindBond_for_Stream(
false, // forInputStream
streamIndex);
if (bond < 0)
return E_INVALIDARG;
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
UInt32 coderIndex = inStreamIndex;
UInt32 coderStreamIndex = 0;
if (!EncodeMode)
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
CCoder &coder = _coders[coderIndex];
CMyComPtr<IOutStreamFlush> flush;
coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush);
HRESULT res = S_OK;
if (flush)
{
res = flush->Flush();
}
return GetError(res, FlushCoder(coderIndex));
}
HRESULT CMixerST::FlushCoder(UInt32 coderIndex)
{
CCoder &coder = _coders[coderIndex];
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
HRESULT res = S_OK;
for (unsigned i = 0; i < numOutStreams; i++)
res = GetError(res, FlushStream(startIndex + i));
return res;
}
void CMixerST::SelectMainCoder(bool useFirst)
{
unsigned ci = _bi.UnpackCoder;
int firstNonFilter = -1;
int firstAllowed = ci;
for (;;)
{
const CCoderST &coder = _coders[ci];
// break;
if (ci != _bi.UnpackCoder)
if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
{
firstAllowed = ci;
firstNonFilter = -2;
}
if (coder.NumStreams != 1)
break;
UInt32 st = _bi.Coder_to_Stream[ci];
if (_bi.IsStream_in_PackStreams(st))
break;
int bond = _bi.FindBond_for_PackStream(st);
if (bond < 0)
throw 20150213;
if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
break;
if (firstNonFilter == -1 && !IsFilter_Vector[ci])
firstNonFilter = ci;
ci = _bi.Bonds[bond].UnpackIndex;
}
ci = firstNonFilter;
if (firstNonFilter < 0 || useFirst)
ci = firstAllowed;
MainCoderIndex = ci;
}
HRESULT CMixerST::Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress)
{
_binderStreams.Clear();
unsigned ci = MainCoderIndex;
const CCoder &mainCoder = _coders[MainCoderIndex];
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
UInt32 i;
for (i = 0; i < numInStreams; i++)
{
CMyComPtr<ISequentialInStream> seqInStream;
RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
seqInStreams.Add(seqInStream);
}
for (i = 0; i < numOutStreams; i++)
{
CMyComPtr<ISequentialOutStream> seqOutStream;
RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
seqOutStreams.Add(seqOutStream);
}
CRecordVector< ISequentialInStream * > seqInStreamsSpec;
CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
for (i = 0; i < numInStreams; i++)
seqInStreamsSpec.Add(seqInStreams[i]);
for (i = 0; i < numOutStreams; i++)
seqOutStreamsSpec.Add(seqOutStreams[i]);
for (i = 0; i < _coders.Size(); i++)
{
if (i == ci)
continue;
CCoder &coder = _coders[i];
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
if (setOutStreamSize)
{
RINOK(setOutStreamSize->SetOutStreamSize(
EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
}
}
const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
HRESULT res;
if (mainCoder.Coder)
{
res = mainCoder.Coder->Code(
seqInStreamsSpec[0], seqOutStreamsSpec[0],
isSizes2[0], outSizes2[0],
progress);
}
else
{
res = mainCoder.Coder2->Code(
&seqInStreamsSpec.Front(), isSizes2, numInStreams,
&seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
progress);
}
if (res == k_My_HRESULT_WritingWasCut)
res = S_OK;
if (res == S_OK || res == S_FALSE)
{
res = GetError(res, FlushCoder(ci));
}
for (i = 0; i < _binderStreams.Size(); i++)
{
const CStBinderStream &bs = _binderStreams[i];
if (bs.InStreamSpec)
bs.InStreamSpec->ReleaseStream();
else
bs.OutStreamSpec->ReleaseStream();
}
if (res == k_My_HRESULT_WritingWasCut)
res = S_OK;
return res;
}
HRESULT CMixerST::GetMainUnpackStream(
ISequentialInStream * const *inStreams,
ISequentialInStream **inStreamRes)
{
CMyComPtr<ISequentialInStream> seqInStream;
RINOK(GetInStream2(inStreams, /* inSizes, */
_bi.UnpackCoder, &seqInStream))
FOR_VECTOR (i, _coders)
{
CCoder &coder = _coders[i];
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
if (setOutStreamSize)
{
RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
}
}
*inStreamRes = seqInStream.Detach();
return S_OK;
}
UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
{
const CStBinderStream &bs = _binderStreams[bondIndex];
if (bs.InStreamSpec)
return bs.InStreamSpec->GetSize();
return bs.OutStreamSpec->GetSize();
}
}

View File

@@ -1,129 +0,0 @@
// CoderMixer2ST.h
#ifndef __CODER_MIXER2_ST_H
#define __CODER_MIXER2_ST_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "CoderMixer2.h"
class CSequentialInStreamCalcSize:
public ISequentialInStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
private:
CMyComPtr<ISequentialInStream> _stream;
UInt64 _size;
bool _wasFinished;
public:
void SetStream(ISequentialInStream *stream) { _stream = stream; }
void Init()
{
_size = 0;
_wasFinished = false;
}
void ReleaseStream() { _stream.Release(); }
UInt64 GetSize() const { return _size; }
bool WasFinished() const { return _wasFinished; }
};
class COutStreamCalcSize:
public ISequentialOutStream,
public IOutStreamFlush,
public CMyUnknownImp
{
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _size;
public:
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Flush)();
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
void ReleaseStream() { _stream.Release(); }
void Init() { _size = 0; }
UInt64 GetSize() const { return _size; }
};
namespace NCoderMixer2 {
struct CCoderST: public CCoder
{
bool CanRead;
bool CanWrite;
CCoderST(): CanRead(false), CanWrite(false) {}
};
struct CStBinderStream
{
CSequentialInStreamCalcSize *InStreamSpec;
COutStreamCalcSize *OutStreamSpec;
CMyComPtr<IUnknown> StreamRef;
CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
};
class CMixerST:
public IUnknown,
public CMixer,
public CMyUnknownImp
{
HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
HRESULT FlushStream(UInt32 streamIndex);
HRESULT FlushCoder(UInt32 coderIndex);
public:
CObjectVector<CCoderST> _coders;
CObjectVector<CStBinderStream> _binderStreams;
MY_UNKNOWN_IMP
CMixerST(bool encodeMode);
~CMixerST();
virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual void ReInit();
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
HRESULT GetMainUnpackStream(
ISequentialInStream * const *inStreams,
ISequentialInStream **inStreamRes);
};
}
#endif

View File

@@ -1,99 +0,0 @@
// CoderMixerMT.cpp
#include "StdAfx.h"
#include "CoderMixerMT.h"
namespace NCoderMixer {
void CCoder::Execute() { Code(NULL); }
void CCoder::Code(ICompressProgressInfo *progress)
{
Result = Coder->Code(InStream, OutStream,
InSizeAssigned ? &InSizeValue : NULL,
OutSizeAssigned ? &OutSizeValue : NULL,
progress);
InStream.Release();
OutStream.Release();
}
void CCoderMixerMT::AddCoder(ICompressCoder *coder)
{
_coders.Add(CCoder());
_coders.Back().Coder = coder;
}
void CCoderMixerMT::ReInit()
{
for(int i = 0; i < _coders.Size(); i++)
_coders[i].ReInit();
}
HRESULT CCoderMixerMT::ReturnIfError(HRESULT code)
{
for (int i = 0; i < _coders.Size(); i++)
if (_coders[i].Result == code)
return code;
return S_OK;
}
STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */,
ICompressProgressInfo *progress)
{
_coders.Front().InStream = inStream;
int i;
_coders.Back().OutStream = outStream;
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
{
RINOK(_coders[i].Create());
}
_streamBinders.Clear();
for (i = 0; i + 1 < _coders.Size(); i++)
{
_streamBinders.Add(CStreamBinder());
CStreamBinder &sb = _streamBinders[i];
RINOK(sb.CreateEvents());
sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);
}
for(i = 0; i < _streamBinders.Size(); i++)
_streamBinders[i].ReInit();
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
_coders[i].Start();
_coders[_progressCoderIndex].Code(progress);
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
_coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
RINOK(ReturnIfError(E_OUTOFMEMORY));
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
if (result != S_OK && result != E_FAIL && result != S_FALSE)
return result;
}
RINOK(ReturnIfError(S_FALSE));
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
if (result != S_OK)
return result;
}
return S_OK;
}
}

View File

@@ -1,70 +0,0 @@
// CoderMixerMT.h
#ifndef __CODER_MIXER_MT_H
#define __CODER_MIXER_MT_H
#include "../../../Common/MyVector.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/StreamBinder.h"
#include "../../Common/VirtThread.h"
#include "CoderMixer.h"
namespace NCoderMixer {
struct CCoder: public CCoderInfo, public CVirtThread
{
HRESULT Result;
virtual void Execute();
void Code(ICompressProgressInfo *progress);
virtual ~CCoder() { CVirtThread::WaitThreadFinish(); }
};
/*
for each coder
AddCoder()
SetProgressIndex(UInt32 coderIndex);
for each file
{
ReInit()
for each coder
SetCoderInfo
Code
}
*/
class CCoderMixerMT:
public ICompressCoder,
public CMyUnknownImp
{
CObjectVector<CStreamBinder> _streamBinders;
int _progressCoderIndex;
HRESULT ReturnIfError(HRESULT code);
public:
CObjectVector<CCoder> _coders;
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
void AddCoder(ICompressCoder *coder);
void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; }
void ReInit();
void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize)
{ _coders[coderIndex].SetCoderInfo(inSize, outSize); }
/*
UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
{ return _streamBinders[binderIndex].ProcessedSize; }
*/
};
}
#endif

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include <string.h>
#include "../../../Common/MyBuffer.h"
#include "../../Common/StreamUtils.h"

View File

@@ -1,7 +1,7 @@
// FindSignature.h
#ifndef __FINDSIGNATURE_H
#define __FINDSIGNATURE_H
#ifndef __FIND_SIGNATURE_H
#define __FIND_SIGNATURE_H
#include "../../IStream.h"

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../Common/MyWindows.h"
#include "../../Common/MyInitGuid.h"
#if defined(_7ZIP_LARGE_PAGES)

View File

@@ -16,7 +16,7 @@
/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.
The code is much larger in that case. */
#define NSIS_SCRIPT
// #define NSIS_SCRIPT
namespace NArchive {
namespace NNsis {

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,410 @@
// Rar5Handler.h
#ifndef __RAR5_HANDLER_H
#define __RAR5_HANDLER_H
#include "../../../../C/Blake2.h"
#include "../../../Common/MyBuffer.h"
#include "../../../Windows/PropVariant.h"
#include "../../Common/CreateCoder.h"
#include "../IArchive.h"
namespace NArchive {
namespace NRar5 {
namespace NHeaderFlags
{
const unsigned kExtra = 1 << 0;
const unsigned kData = 1 << 1;
// const unsigned kUnknown = 1 << 2;
const unsigned kPrevVol = 1 << 3;
const unsigned kNextVol = 1 << 4;
// const unsigned kIsChild = 1 << 5;
// const unsigned kPreserveChild = 1 << 6;
}
namespace NHeaderType
{
enum
{
kArc = 1,
kFile,
kService,
kArcEncrypt,
kEndOfArc
};
}
namespace NArcFlags
{
const unsigned kVol = 1 << 0;
const unsigned kVolNumber = 1 << 1;
const unsigned kSolid = 1 << 2;
// const unsigned kRecovery = 1 << 3;
// const unsigned kLocked = 1 << 4;
}
const unsigned kArcExtraRecordType_Locator = 1;
namespace NLocatorFlags
{
const unsigned kQuickOpen = 1 << 0;
const unsigned kRecovery = 1 << 1;
}
namespace NFileFlags
{
const unsigned kIsDir = 1 << 0;
const unsigned kUnixTime = 1 << 1;
const unsigned kCrc32 = 1 << 2;
const unsigned kUnknownSize = 1 << 3;
}
namespace NMethodFlags
{
// const unsigned kVersionMask = 0x3F;
const unsigned kSolid = 1 << 6;
}
namespace NArcEndFlags
{
const unsigned kMoreVols = 1 << 0;
}
enum EHostOS
{
kHost_Windows = 0,
kHost_Unix
};
// ---------- Extra ----------
namespace NExtraRecordType
{
enum
{
kCrypto = 1,
kHash,
kTime,
kVersion,
kLink,
kUnixOwner,
kSubdata
};
}
// const unsigned kCryptoAlgo_AES = 0;
namespace NCryptoFlags
{
const unsigned kPswCheck = 1 << 0;
const unsigned kUseMAC = 1 << 1;
}
struct CCryptoInfo
{
UInt64 Algo;
UInt64 Flags;
Byte Cnt;
bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }
bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; }
bool Parse(const Byte *p, size_t size);
};
const unsigned kHashID_Blake2sp = 0;
namespace NTimeRecord
{
enum
{
k_Index_MTime = 0,
k_Index_CTime,
k_Index_ATime
};
namespace NFlags
{
const unsigned kUnixTime = 1 << 0;
const unsigned kMTime = 1 << 1;
// const unsigned kCTime = 1 << 2;
// const unsigned kATime = 1 << 3;
}
}
namespace NLinkType
{
enum
{
kUnixSymLink = 1,
kWinSymLink,
kWinJunction,
kHardLink,
kFileCopy
};
}
namespace NLinkFlags
{
const unsigned kTargetIsDir = 1 << 0;
}
struct CItem
{
UInt32 CommonFlags;
UInt32 Flags;
Byte RecordType;
bool Version_Defined;
int ACL;
AString Name;
int VolIndex;
int NextItem;
UInt32 UnixMTime;
UInt32 CRC;
UInt32 Attrib;
UInt32 Method;
CByteBuffer Extra;
UInt64 Size;
UInt64 PackSize;
UInt64 HostOS;
UInt64 DataPos;
UInt64 Version;
CItem() { Clear(); }
void Clear()
{
CommonFlags = 0;
Flags = 0;
VolIndex = 0;
NextItem = -1;
Version_Defined = false;
Version = 0;
Name.Empty();
Extra.Free();
ACL = -1;
}
bool IsSplitBefore() const { return (CommonFlags & NHeaderFlags::kPrevVol) != 0; }
bool IsSplitAfter() const { return (CommonFlags & NHeaderFlags::kNextVol) != 0; }
bool IsSplit() const { return (CommonFlags & (NHeaderFlags::kPrevVol | NHeaderFlags::kNextVol)) != 0; }
bool IsDir() const { return (Flags & NFileFlags::kIsDir) != 0; }
bool Has_UnixMTime() const { return (Flags & NFileFlags::kUnixTime) != 0; }
bool Has_CRC() const { return (Flags & NFileFlags::kCrc32) != 0; }
bool Is_UnknownSize() const { return (Flags & NFileFlags::kUnknownSize) != 0; }
bool IsNextForItem(const CItem &prev) const
{
return !IsDir() && !prev.IsDir() && IsSplitBefore() && prev.IsSplitAfter() && (Name == prev.Name);
// && false;
}
bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; }
unsigned GetAlgoVersion() const { return (unsigned)Method & 0x3F; }
unsigned GetMethod() const { return ((unsigned)Method >> 7) & 0x7; }
UInt32 GetDictSize() const { return (((UInt32)Method >> 10) & 0xF); }
bool IsService() const { return RecordType == NHeaderType::kService; }
bool Is_STM() const { return IsService() && Name == "STM"; }
bool Is_CMT() const { return IsService() && Name == "CMT"; }
bool Is_ACL() const { return IsService() && Name == "ACL"; }
// bool Is_QO() const { return IsService() && Name == "QO"; }
int FindExtra(unsigned type, unsigned &recordDataSize) const;
bool IsEncrypted() const
{
unsigned size;
return FindExtra(NExtraRecordType::kCrypto, size) >= 0;
}
int FindExtra_Blake() const
{
unsigned size = 0;
int offset = FindExtra(NExtraRecordType::kHash, size);
if (offset >= 0
&& size == BLAKE2S_DIGEST_SIZE + 1
&& Extra[(unsigned)offset] == kHashID_Blake2sp)
return offset + 1;
return -1;
}
bool FindExtra_Version(UInt64 &version) const;
struct CLinkInfo
{
UInt64 Type;
UInt64 Flags;
unsigned NameOffset;
unsigned NameLen;
};
bool FindExtra_Link(CLinkInfo &link) const;
void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const;
bool Is_CopyLink() const;
bool NeedUse_as_CopyLink() const { return PackSize == 0 && Is_CopyLink(); }
bool GetAltStreamName(AString &name) const;
UInt32 GetWinAttrib() const
{
UInt32 a;
switch (HostOS)
{
case kHost_Windows: a = Attrib; break;
case kHost_Unix: a = (Attrib << 16); break;
default: a = 0;
}
// if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY;
return a;
}
UInt64 GetDataPosition() const { return DataPos; }
};
struct CInArcInfo
{
UInt64 Flags;
UInt64 VolNumber;
UInt64 StartPos;
UInt64 EndPos;
UInt64 EndFlags;
bool EndOfArchive_was_Read;
bool IsEncrypted;
// CByteBuffer Extra;
/*
struct CLocator
{
UInt64 Flags;
UInt64 QuickOpen;
UInt64 Recovery;
bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; }
bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }
};
int FindExtra(unsigned type, unsigned &recordDataSize) const;
bool FindExtra_Locator(CLocator &locator) const;
*/
CInArcInfo():
Flags(0),
VolNumber(0),
StartPos(0),
EndPos(0),
EndFlags(0),
EndOfArchive_was_Read(false),
IsEncrypted(false)
{}
/*
void Clear()
{
Flags = 0;
VolNumber = 0;
StartPos = 0;
EndPos = 0;
EndFlags = 0;
EndOfArchive_was_Read = false;
Extra.Free();
}
*/
UInt64 GetPhySize() const { return EndPos - StartPos; }
bool AreMoreVolumes() const { return (EndFlags & NArcEndFlags::kMoreVols) != 0; }
bool IsVolume() const { return (Flags & NArcFlags::kVol) != 0; }
bool IsSolid() const { return (Flags & NArcFlags::kSolid) != 0; }
bool Is_VolNumber_Defined() const { return (Flags & NArcFlags::kVolNumber) != 0; }
UInt64 GetVolIndex() const { return Is_VolNumber_Defined() ? VolNumber : 0; }
};
struct CRefItem
{
unsigned Item;
unsigned Last;
int Parent;
int Link;
};
struct CArc
{
CMyComPtr<IInStream> Stream;
CInArcInfo Info;
};
class CHandler:
public IInArchive,
public IArchiveGetRawProps,
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
public:
CRecordVector<CRefItem> _refs;
CObjectVector<CItem> _items;
private:
CObjectVector<CArc> _arcs;
CObjectVector<CByteBuffer> _acls;
UInt32 _errorFlags;
// UInt32 _warningFlags;
bool _isArc;
CByteBuffer _comment;
DECL_EXTERNAL_CODECS_VARS
UInt64 GetPackSize(unsigned refIndex) const;
void FillLinks();
HRESULT Open2(IInStream *stream,
const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openCallback);
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
INTERFACE_IArchiveGetRawProps(;)
DECL_ISetCompressCodecsInfo
};
}}
#endif

View File

@@ -30,6 +30,7 @@
#include "../Common/ItemNameUtils.h"
#include "../Common/OutStreamWithCRC.h"
#include "RarVol.h"
#include "RarHandler.h"
using namespace NWindows;
@@ -44,6 +45,8 @@ namespace NRar {
static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE;
const unsigned kPasswordLen_MAX = 127;
bool CItem::IgnoreItem() const
{
switch (HostOS)
@@ -131,7 +134,7 @@ class CInArchive
CByteBuffer _comment;
CByteBuffer m_FileHeaderData;
NHeader::NBlock::CBlock m_BlockHeader;
NCrypto::NRar29::CDecoder *m_RarAESSpec;
NCrypto::NRar3::CDecoder *m_RarAESSpec;
CMyComPtr<ICompressFilter> m_RarAES;
CBuffer<Byte> m_DecryptedData;
Byte *m_DecryptedDataAligned;
@@ -362,6 +365,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
_ttt_ .DosTime = Get32(p); p += 4; size -= 4; \
READ_TIME(_mask_, _ttt_); } \
bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
{
const Byte *pStart = p;
@@ -500,7 +504,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
}
if (!m_RarAES)
{
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
m_RarAESSpec = new NCrypto::NRar3::CDecoder;
m_RarAES = m_RarAESSpec;
}
m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
@@ -518,7 +522,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
unsigned len = 0;
if (password)
len = MyStringLen(password);
CByteBuffer buffer(len * 2);
if (len > kPasswordLen_MAX)
len = kPasswordLen_MAX;
CByteArr buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
wchar_t c = password[i];
@@ -526,7 +533,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);
const UInt32 kDecryptedBufferSize = (1 << 12);
if (m_DecryptedData.Size() == 0)
@@ -990,121 +997,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
static bool IsDigit(wchar_t c)
{
return c >= L'0' && c <= L'9';
}
class CVolumeName
{
bool _first;
bool _newStyle;
UString _unchangedPart;
UString _changedPart;
UString _afterPart;
public:
CVolumeName(): _newStyle(true) {};
bool InitName(const UString &name, bool newStyle)
{
_first = true;
_newStyle = newStyle;
int dotPos = name.ReverseFind_Dot();
UString basePart = name;
if (dotPos >= 0)
{
UString ext = name.Ptr(dotPos + 1);
if (ext.IsEqualTo_Ascii_NoCase("rar"))
{
_afterPart = name.Ptr(dotPos);
basePart = name.Left(dotPos);
}
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
{
_afterPart.SetFromAscii(".rar");
basePart = name.Left(dotPos);
}
else if (!_newStyle)
{
if (ext.IsEqualTo_Ascii_NoCase("000") ||
ext.IsEqualTo_Ascii_NoCase("001") ||
ext.IsEqualTo_Ascii_NoCase("r00") ||
ext.IsEqualTo_Ascii_NoCase("r01"))
{
_afterPart.Empty();
_first = false;
_changedPart = ext;
_unchangedPart = name.Left(dotPos + 1);
return true;
}
}
}
if (!_newStyle)
{
_afterPart.Empty();
_unchangedPart = basePart;
_unchangedPart += L'.';
_changedPart.SetFromAscii("r00");
return true;
}
if (basePart.IsEmpty())
return false;
unsigned i = basePart.Len();
do
if (!IsDigit(basePart[i - 1]))
break;
while (--i);
_unchangedPart = basePart.Left(i);
_changedPart = basePart.Ptr(i);
return true;
}
/*
void MakeBeforeFirstName()
{
unsigned len = _changedPart.Len();
_changedPart.Empty();
for (unsigned i = 0; i < len; i++)
_changedPart += L'0';
}
*/
UString GetNextName()
{
if (_newStyle || !_first)
{
unsigned i = _changedPart.Len();
for (;;)
{
wchar_t c = _changedPart[--i];
if (c == L'9')
{
c = L'0';
_changedPart.ReplaceOneCharAtPos(i, c);
if (i == 0)
{
_changedPart.InsertAtFront(L'1');
break;
}
continue;
}
c++;
_changedPart.ReplaceOneCharAtPos(i, c);
break;
}
}
_first = false;
return _unchangedPart + _changedPart + _afterPart;
}
};
static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
{
areThereNonZeros = false;
numZeros = 0;
@@ -1136,7 +1030,6 @@ HRESULT CHandler::Open2(IInStream *stream,
{
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
CVolumeName seqName;
@@ -1145,8 +1038,8 @@ HRESULT CHandler::Open2(IInStream *stream,
if (openCallback)
{
openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
}
CInArchive archive;
@@ -1363,108 +1256,91 @@ struct CMethodItem
};
class CFolderInStream:
class CVolsInStream:
public ISequentialInStream,
public CMyUnknownImp
{
UInt64 _rem;
ISequentialInStream *_stream;
const CObjectVector<CArc> *_arcs;
const CObjectVector<CItem> *_items;
CRefItem _refItem;
unsigned _curIndex;
UInt32 _crc;
bool _calcCrc;
public:
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
private:
const CObjectVector<CArc> *_archives;
const CObjectVector<CItem> *_items;
CRefItem _refItem;
unsigned _curIndex;
UInt32 _crc;
bool _fileIsOpen;
CMyComPtr<ISequentialInStream> _stream;
HRESULT OpenStream();
HRESULT CloseStream();
public:
void Init(const CObjectVector<CArc> *archives,
const CObjectVector<CItem> *items,
const CRefItem &refItem);
CRecordVector<UInt32> CRCs;
};
ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const
{
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
Stream->Seek(offset, STREAM_SEEK_SET, NULL);
streamSpec->SetStream(Stream);
streamSpec->Init(size);
return inStream.Detach();
}
void CFolderInStream::Init(
const CObjectVector<CArc> *archives,
void Init(const CObjectVector<CArc> *arcs,
const CObjectVector<CItem> *items,
const CRefItem &refItem)
{
_archives = archives;
{
_arcs = arcs;
_items = items;
_refItem = refItem;
_curIndex = 0;
CRCs.Clear();
_fileIsOpen = false;
}
_stream = NULL;
CrcIsOK = true;
}
HRESULT CFolderInStream::OpenStream()
bool CrcIsOK;
};
STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
while (_curIndex < _refItem.NumItems)
if (processedSize)
*processedSize = 0;
UInt32 realProcessedSize = 0;
while (size != 0)
{
if (!_stream)
{
if (_curIndex >= _refItem.NumItems)
break;
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream;
RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
_stream = s;
_calcCrc = (CrcIsOK && item.IsSplitAfter());
_crc = CRC_INIT_VAL;
_rem = item.PackSize;
}
{
UInt32 cur = size;
if (cur > _rem)
cur = (UInt32)_rem;
UInt32 num = cur;
HRESULT res = _stream->Read(data, cur, &cur);
if (_calcCrc)
_crc = CrcUpdate(_crc, data, cur);
realProcessedSize += cur;
if (processedSize)
*processedSize = realProcessedSize;
data = (Byte *)data + cur;
size -= cur;
_rem -= cur;
if (_rem == 0)
{
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
_stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex].
CreateLimitedStream(item.GetDataPosition(), item.PackSize));
_curIndex++;
_fileIsOpen = true;
_crc = CRC_INIT_VAL;
if (_calcCrc && CRC_GET_DIGEST(_crc) != item.FileCRC)
CrcIsOK = false;
_stream = NULL;
}
if (res != S_OK)
return res;
if (realProcessedSize != 0)
return S_OK;
if (cur == 0 && num != 0)
return S_OK;
}
return S_OK;
}
}
HRESULT CFolderInStream::CloseStream()
{
CRCs.Add(CRC_GET_DIGEST(_crc));
_stream.Release();
_fileIsOpen = false;
return S_OK;
}
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize = 0;
while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
{
if (_fileIsOpen)
{
UInt32 localProcessedSize;
RINOK(_stream->Read(
((Byte *)data) + realProcessedSize, size, &localProcessedSize));
_crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize);
if (localProcessedSize == 0)
{
RINOK(CloseStream());
continue;
}
realProcessedSize += localProcessedSize;
size -= localProcessedSize;
break;
}
else
{
RINOK(OpenStream());
}
}
if (processedSize != 0)
*processedSize = realProcessedSize;
return S_OK;
}
@@ -1526,13 +1402,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL;
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
CMyComPtr<ICompressFilter> rar29CryptoDecoder;
NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL;
CMyComPtr<ICompressFilter> rar3CryptoDecoder;
CFolderInStream *folderInStreamSpec = NULL;
CMyComPtr<ISequentialInStream> folderInStream;
CVolsInStream *volsInStreamSpec = NULL;
CMyComPtr<ISequentialInStream> volsInStream;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
@@ -1602,26 +1478,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStreamSpec->Init();
realOutStream.Release();
/*
for (unsigned partIndex = 0; partIndex < 1; partIndex++)
if (!volsInStream)
{
CMyComPtr<ISequentialInStream> inStream;
// item redefinition
const CItem &item = _items[refItem.ItemIndex + partIndex];
CInArchive &archive = _arcs[refItem.VolumeIndex + partIndex];
inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),
item.PackSize));
*/
if (!folderInStream)
{
folderInStreamSpec = new CFolderInStream;
folderInStream = folderInStreamSpec;
volsInStreamSpec = new CVolsInStream;
volsInStream = volsInStreamSpec;
}
folderInStreamSpec->Init(&_arcs, &_items, refItem);
volsInStreamSpec->Init(&_arcs, &_items, refItem);
UInt64 packSize = currentPackSize;
@@ -1632,29 +1495,29 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (item.IsEncrypted())
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
// CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
if (item.UnPackVersion >= 29)
{
if (!rar29CryptoDecoder)
if (!rar3CryptoDecoder)
{
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
rar29CryptoDecoder = rar29CryptoDecoderSpec;
rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder;
rar3CryptoDecoder = rar3CryptoDecoderSpec;
}
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
/*
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
&cryptoProperties));
*/
RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
filterStreamSpec->Filter = rar29CryptoDecoder;
RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
filterStreamSpec->Filter = rar3CryptoDecoder;
}
else if (item.UnPackVersion >= 20)
{
if (!rar20CryptoDecoder)
{
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder;
rar20CryptoDecoder = rar20CryptoDecoderSpec;
}
filterStreamSpec->Filter = rar20CryptoDecoder;
@@ -1666,49 +1529,66 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue;
}
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
// RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
if (!getTextPassword)
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
if (getTextPassword)
if (!getTextPassword)
{
outStream.Release();
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
continue;
}
// if (getTextPassword)
{
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password));
if (item.UnPackVersion >= 29)
{
UString unicodePassword;
unsigned len = 0;
if (password)
len = MyStringLen(password);
CByteBuffer buffer(len * 2);
if (len > kPasswordLen_MAX)
len = kPasswordLen_MAX;
CByteArr buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
wchar_t c = password[i];
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2);
}
else
{
AString oemPassword;
if (password)
oemPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()));
{
UString unicode = (LPCOLESTR)password;
if (unicode.Len() > kPasswordLen_MAX)
unicode.DeleteFrom(kPasswordLen_MAX);
oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP);
}
rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len());
}
}
/*
else
{
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
}
*/
filterStreamSpec->SetInStream(folderInStream);
filterStreamSpec->SetInStream(volsInStream);
filterStreamSpec->SetOutStreamSize(NULL);
inStream = filterStream;
}
else
{
inStream = folderInStream;
inStream = volsInStream;
}
CMyComPtr<ICompressCoder> commonCoder;
@@ -1766,7 +1646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
if (solidStart)
{
isSolid = false;
isSolid = 0;
solidStart = false;
}
@@ -1786,46 +1666,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (item.IsEncrypted())
filterStreamSpec->ReleaseInStream();
if (result == S_FALSE)
{
outStream.Release();
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
continue;
}
if (result != S_OK)
return result;
/*
if (refItem.NumItems == 1 &&
!item.IsSplitBefore() && !item.IsSplitAfter())
*/
{
const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kCRCError;
outStream.Release();
RINOK(extractCallback->SetOperationResult(crcOK ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kCRCError));
}
/*
if (result != S_OK)
{
if (result == S_FALSE)
opRes = NExtract::NOperationResult::kDataError;
else if (result == E_NOTIMPL)
opRes = NExtract::NOperationResult::kUnsupportedMethod;
else
{
bool crcOK = true;
for (unsigned partIndex = 0; partIndex < refItem.NumItems; partIndex++)
{
const CItem &item = _items[refItem.ItemIndex + partIndex];
if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])
{
crcOK = false;
break;
return result;
}
RINOK(extractCallback->SetOperationResult(opRes));
}
RINOK(extractCallback->SetOperationResult(crcOK ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kCRCError));
}
*/
}
return S_OK;
COM_TRY_END
}

View File

@@ -0,0 +1,129 @@
// RarVol.h
#ifndef __ARCHIVE_RAR_VOL_H
#define __ARCHIVE_RAR_VOL_H
#include "../../../Common/StringConvert.h"
#include "RarHeader.h"
namespace NArchive {
namespace NRar {
inline bool IsDigit(wchar_t c)
{
return c >= L'0' && c <= L'9';
}
class CVolumeName
{
bool _first;
bool _newStyle;
UString _unchangedPart;
UString _changedPart;
UString _afterPart;
public:
CVolumeName(): _newStyle(true) {};
bool InitName(const UString &name, bool newStyle = true)
{
_first = true;
_newStyle = newStyle;
int dotPos = name.ReverseFind_Dot();
UString basePart = name;
if (dotPos >= 0)
{
UString ext = name.Ptr(dotPos + 1);
if (ext.IsEqualTo_Ascii_NoCase("rar"))
{
_afterPart = name.Ptr(dotPos);
basePart = name.Left(dotPos);
}
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
{
_afterPart.SetFromAscii(".rar");
basePart = name.Left(dotPos);
}
else if (!_newStyle)
{
if (ext.IsEqualTo_Ascii_NoCase("000") ||
ext.IsEqualTo_Ascii_NoCase("001") ||
ext.IsEqualTo_Ascii_NoCase("r00") ||
ext.IsEqualTo_Ascii_NoCase("r01"))
{
_afterPart.Empty();
_first = false;
_changedPart = ext;
_unchangedPart = name.Left(dotPos + 1);
return true;
}
}
}
if (!_newStyle)
{
_afterPart.Empty();
_unchangedPart = basePart;
_unchangedPart += L'.';
_changedPart.SetFromAscii("r00");
return true;
}
if (basePart.IsEmpty())
return false;
unsigned i = basePart.Len();
do
if (!IsDigit(basePart[i - 1]))
break;
while (--i);
_unchangedPart = basePart.Left(i);
_changedPart = basePart.Ptr(i);
return true;
}
/*
void MakeBeforeFirstName()
{
unsigned len = _changedPart.Len();
_changedPart.Empty();
for (unsigned i = 0; i < len; i++)
_changedPart += L'0';
}
*/
UString GetNextName()
{
if (_newStyle || !_first)
{
unsigned i = _changedPart.Len();
for (;;)
{
wchar_t c = _changedPart[--i];
if (c == L'9')
{
c = L'0';
_changedPart.ReplaceOneCharAtPos(i, c);
if (i == 0)
{
_changedPart.InsertAtFront(L'1');
break;
}
continue;
}
c++;
_changedPart.ReplaceOneCharAtPos(i, c);
break;
}
}
_first = false;
return _unchangedPart + _changedPart + _afterPart;
}
};
}}
#endif

View File

@@ -29,11 +29,13 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(index, propId, &prop));
if (prop.vt == VT_BSTR)
{
UString s = prop.bstrVal;
if (convertSlash)
s = NItemName::MakeLegalName(s);
if (codePage == CP_UTF8)
{
ConvertUnicodeToUTF8(s, res);
@@ -44,9 +46,11 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
return S_OK;
}
// sort old files with original order.
static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
@@ -57,33 +61,39 @@ static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
{
if (u2.NewProps)
return -1;
return MyCompare(u1.IndexInArchive, u2.IndexInArchive);
return MyCompare(u1.IndexInArc, u2.IndexInArc);
}
if (!u2.NewProps)
return 1;
return MyCompare(u1.IndexInClient, u2.IndexInClient);
}
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream)
return E_NOTIMPL;
CObjectVector<CUpdateItem> updateItems;
UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
for (UInt32 i = 0; i < numItems; i++)
{
CUpdateItem ui;
Int32 newData;
Int32 newProps;
UInt32 indexInArchive;
UInt32 indexInArc;
if (!callback)
return E_FAIL;
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc));
ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
ui.IndexInArchive = indexInArchive;
ui.IndexInArc = indexInArc;
ui.IndexInClient = i;
if (IntToBool(newProps))
@@ -109,6 +119,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
ui.Mode = prop.ulVal;
}
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidMTime, &prop));
@@ -119,6 +130,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
}
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true));
if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
ui.Name += '/';
@@ -139,14 +151,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
*/
}
updateItems.Add(ui);
}
if (_thereIsPaxExtendedHeader)
{
// we restore original order of files, if there is pax header block
updateItems.Sort(CompareUpdateItems, NULL);
}
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback);
COM_TRY_END
}

View File

@@ -43,7 +43,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (ui.NewData)
complexity += ui.Size;
else
complexity += inputItems[ui.IndexInArchive].GetFullSize();
complexity += inputItems[ui.IndexInArc].GetFullSize();
}
RINOK(updateCallback->SetTotal(complexity));
@@ -68,12 +68,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
const CUpdateItem &ui = updateItems[i];
CItem item;
if (ui.NewProps)
{
item.Mode = ui.Mode;
item.Name = ui.Name;
item.User = ui.User;
item.Group = ui.Group;
if (ui.IsDir)
{
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
@@ -84,6 +86,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
item.PackSize = ui.Size;
}
item.MTime = ui.MTime;
item.DeviceMajorDefined = false;
item.DeviceMinorDefined = false;
@@ -92,7 +95,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8);
}
else
item = inputItems[ui.IndexInArchive];
item = inputItems[ui.IndexInArc];
AString symLink;
if (ui.NewData || ui.NewProps)
@@ -116,6 +119,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
CMyComPtr<ISequentialInStream> fileInStream;
bool needWrite = true;
if (!symLink.IsEmpty())
{
item.PackSize = 0;
@@ -124,6 +128,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
else
{
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
if (res == S_FALSE)
needWrite = false;
else
@@ -141,10 +146,17 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
{
item.PackSize = size2;
item.Size = size2;
item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
}
}
}
else
{
item.PackSize = 0;
item.Size = 0;
}
{
AString hardLink;
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true));
@@ -183,13 +195,15 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
RINOK(outArchive.FillDataResidual(item.PackSize));
}
}
complexity += item.PackSize;
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
else
{
const CItemEx &existItem = inputItems[ui.IndexInArchive];
const CItemEx &existItem = inputItems[ui.IndexInArc];
UInt64 size;
if (ui.NewProps)
{
// memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8);
@@ -225,12 +239,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
size = existItem.GetFullSize();
}
streamSpec->Init(size);
if (opCallback)
{
RINOK(opCallback->ReportOperation(
NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive,
NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,
NUpdateNotifyOp::kReplicate))
}
@@ -242,6 +257,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
complexity += size;
}
}
lps->InSize = lps->OutSize = complexity;
RINOK(lps->SetCur());
return outArchive.WriteFinishHeader();

View File

@@ -4,6 +4,7 @@
#define __TAR_UPDATE_H
#include "../IArchive.h"
#include "TarItem.h"
namespace NArchive {
@@ -11,10 +12,10 @@ namespace NTar {
struct CUpdateItem
{
int IndexInArchive;
int IndexInArc;
int IndexInClient;
Int64 MTime;
UInt64 Size;
Int64 MTime;
UInt32 Mode;
bool NewData;
bool NewProps;
@@ -22,6 +23,8 @@ struct CUpdateItem
AString Name;
AString User;
AString Group;
CUpdateItem(): Size(0), IsDir(false) {}
};
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,

View File

@@ -358,15 +358,24 @@ HRESULT CHandler::Open2(IInStream *stream)
return S_FALSE;
UInt64 totalPackSize = 0;
unsigned numMainFiles = 0;
FOR_VECTOR(i, _files)
{
const CFile &file = _files[i];
file.UpdateTotalPackSize(totalPackSize);
if (file.Name == "Payload")
{
_mainSubfile = i;
numMainFiles++;
}
if (file.Name == "PackageInfo")
_is_pkg = true;
}
if (numMainFiles > 1)
_mainSubfile = -1;
_phySize = _dataStartPos + totalPackSize;
return S_OK;

View File

@@ -207,7 +207,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
if (IntToBool(newData))
{
UInt64 size;
UInt64 size = 0;
if (!ui.IsDir)
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidSize, &prop));
@@ -219,6 +220,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
largestSizeDefined = true;
}
ui.Size = size;
// ui.Size -= ui.Size / 2;
}
updateItems.Add(ui);

View File

@@ -591,6 +591,29 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2)
return ((i1.Flags & mask) == (i2.Flags & mask));
}
// #ifdef _WIN32
static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2)
{
for (;;)
{
char c1 = *s1++;
char c2 = *s2++;
if (c1 == c2)
{
if (c1 == 0)
return true;
}
else
{
if (c1 == '\\') c1 = '/';
if (c2 == '\\') c2 = '/';
if (c1 != c2)
return false;
}
}
}
// #endif
static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
{
if (!FlagsAreSame(cdItem, localItem))
@@ -611,7 +634,30 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
return false;
*/
if (cdItem.Name != localItem.Name)
{
// #ifdef _WIN32
// some xap files use backslash in central dir items.
// we can ignore such errors in windows, where all slashes are converted to backslashes
unsigned hostOs = cdItem.GetHostOS();
if (hostOs == NFileHeader::NHostOS::kFAT ||
hostOs == NFileHeader::NHostOS::kNTFS)
{
if (!AreEqualPaths_IgnoreSlashes(cdItem.Name, localItem.Name))
{
// pkzip 2.50 uses DOS encoding in central dir and WIN encoding in local header.
// so we ignore that error
if (hostOs != NFileHeader::NHostOS::kFAT
|| cdItem.MadeByVersion.Version != 25)
return false;
}
}
/*
else
#endif
return false;
*/
}
return true;
}

View File

@@ -103,7 +103,8 @@ static void SetFileHeader(
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
item.Method = kMethodForDirectory;
item.PackSize = 0;
item.Crc = 0; // test it
item.Size = 0;
item.Crc = 0;
}
}

View File

@@ -332,14 +332,6 @@ SOURCE=..\..\Archive\7z\7zUpdate.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Archive\Common\CoderMixer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\CoderMixer.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\CoderMixer2.cpp
# End Source File
# Begin Source File

View File

@@ -141,6 +141,7 @@ NSIS_OBJS = \
RAR_OBJS = \
$O\RarHandler.obj \
$O\Rar5Handler.obj \
TAR_OBJS = \
$O\TarHandler.obj \
@@ -212,6 +213,7 @@ COMPRESS_OBJS = \
$O\Rar2Decoder.obj \
$O\Rar3Decoder.obj \
$O\Rar3Vm.obj \
$O\Rar5Decoder.obj \
$O\RarCodecsRegister.obj \
$O\ShrinkDecoder.obj \
$O\ZlibDecoder.obj \
@@ -222,11 +224,13 @@ CRYPTO_OBJS = \
$O\7zAes.obj \
$O\7zAesRegister.obj \
$O\HmacSha1.obj \
$O\HmacSha256.obj \
$O\MyAes.obj \
$O\MyAesReg.obj \
$O\Pbkdf2HmacSha1.obj \
$O\RandGen.obj \
$O\Rar20Crypto.obj \
$O\Rar5Aes.obj \
$O\RarAes.obj \
$O\WzAes.obj \
$O\ZipCrypto.obj \
@@ -239,6 +243,7 @@ C_OBJS = \
$O\Alloc.obj \
$O\Bcj2.obj \
$O\Bcj2Enc.obj \
$O\Blake2s.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \

View File

@@ -243,6 +243,10 @@ SOURCE=..\..\..\Common\CrcReg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Defs.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\DynamicBuffer.h
# End Source File
# Begin Source File
@@ -452,6 +456,24 @@ SOURCE=..\..\Compress\Rar3Vm.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Rar5Decoder.cpp
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Rar5Decoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\RarCodecsRegister.cpp
# End Source File
# End Group
@@ -821,6 +843,14 @@ SOURCE=..\..\Crypto\HmacSha1.h
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\HmacSha256.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\HmacSha256.h
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\MyAes.cpp
# End Source File
# Begin Source File
@@ -887,6 +917,14 @@ SOURCE=..\..\Crypto\Rar20Crypto.h
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\Rar5Aes.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\Rar5Aes.h
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\RarAes.cpp
# End Source File
# Begin Source File
@@ -1319,6 +1357,26 @@ SOURCE=..\..\..\..\C\Bcj2Enc.c
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Blake2.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Blake2s.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra.c
!IF "$(CFG)" == "7z - Win32 Release"
@@ -1874,6 +1932,14 @@ SOURCE=..\..\Archive\7z\7zUpdateItem.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Archive\Rar\Rar5Handler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Rar\Rar5Handler.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Rar\RarHandler.cpp
# End Source File
# Begin Source File
@@ -1888,6 +1954,10 @@ SOURCE=..\..\Archive\Rar\RarHeader.h
SOURCE=..\..\Archive\Rar\RarItem.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Rar\RarVol.h
# End Source File
# End Group
# Begin Group "Cab"

View File

@@ -12,7 +12,7 @@
#define MY_SET_BINARY_MODE(file)
#endif
// #include "../../../Common/MyWindows.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../../C/7zVersion.h"

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include <Shlwapi.h>
#include "../../../Common/MyInitGuid.h"

View File

@@ -19,7 +19,7 @@
struct CAlignedMidBuffer
{
#ifndef _WIN32
#ifdef _WIN32
Byte *_buf;

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include <string.h>
#include "LimitedStreams.h"
#include "../../Common/Defs.h"

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../Common/MyWindows.h"
#include "../PropID.h"
// VARTYPE
@@ -101,5 +103,6 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
VT_UI8,
VT_UI8,
VT_BOOL,
VT_BSTR // kpidOutName
VT_BSTR,
VT_BSTR
};

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include <string.h>
#include "UniqBlocks.h"
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)

View File

@@ -2,3 +2,5 @@ EXPORTS
CreateObject PRIVATE
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE
CreateDecoder PRIVATE
CreateEncoder PRIVATE

View File

@@ -130,14 +130,14 @@ CCoder::CCoder(bool deflate64Mode):
m_Values(0),
m_Tables(0)
{
{
CEncProps props;
SetProps(&props);
}
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
{
CEncProps props;
SetProps(&props);
}
MatchFinder_Construct(&_lzInWindow);
}

View File

@@ -22,11 +22,13 @@ public:
bool SetCodeLengths(const Byte *lens)
{
unsigned lenCounts[kNumBitsMax + 1];
UInt32 lenCounts[kNumBitsMax + 1];
UInt32 tmpPositions[kNumBitsMax + 1];
unsigned i;
for (i = 1; i <= kNumBitsMax; i++)
lenCounts[i] = 0;
UInt32 symbol;
for (symbol = 0; symbol < m_NumSymbols; symbol++)
@@ -42,7 +44,7 @@ public:
m_Positions[0] = m_Limits[0] = 0;
UInt32 startPos = 0;
UInt32 index = 0;
const UInt32 kMaxValue = (1 << kNumBitsMax);
const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
for (i = 1; i <= kNumBitsMax; i++)
{
@@ -74,14 +76,15 @@ public:
UInt32 DecodeSymbol(TBitDecoder *bitStream)
{
unsigned numBits;
UInt32 value = bitStream->GetValue(kNumBitsMax);
if (value < m_Limits[kNumTableBits])
numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
UInt32 val = bitStream->GetValue(kNumBitsMax);
if (val < m_Limits[kNumTableBits])
numBits = m_Lengths[val >> (kNumBitsMax - kNumTableBits)];
else
for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
for (numBits = kNumTableBits + 1; val >= m_Limits[numBits]; numBits++);
bitStream->MovePos(numBits);
UInt32 index = m_Positions[numBits] +
((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
UInt32 index = m_Positions[numBits] + ((val - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
if (index >= m_NumSymbols)
// throw CDecoderException(); // test it
return 0xFFFFFFFF;

View File

@@ -486,7 +486,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size < 1)
return E_INVALIDARG;
m_IsSolid = (data[0] != 0);
m_IsSolid = ((data[0] & 1) != 0);
return S_OK;
}

View File

@@ -394,7 +394,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size < 1)
return E_INVALIDARG;
m_IsSolid = (data[0] != 0);
m_IsSolid = ((data[0] & 1) != 0);
return S_OK;
}

View File

@@ -140,6 +140,8 @@ void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)
NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
CFilter *filter = _filters[tempFilter->FilterIndex];
if (!filter->IsSupported)
_unsupportedFilter = true;
_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);
delete tempFilter;
_tempFilters[tempFilterIndex] = 0;
@@ -226,12 +228,15 @@ void CDecoder::InitFilters()
_filters.Clear();
}
static const unsigned MAX_UNPACK_FILTERS = 8192;
bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
{
CMemBitDecoder inp;
inp.Init(_vmData, codeSize);
UInt32 filterIndex;
if (firstByte & 0x80)
{
filterIndex = inp.ReadEncodedUInt32();
@@ -242,6 +247,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
}
else
filterIndex = _lastFilter;
if (filterIndex > (UInt32)_filters.Size())
return false;
_lastFilter = filterIndex;
@@ -251,7 +257,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
if (newFilter)
{
// check if too many filters
if (filterIndex > 1024)
if (filterIndex > MAX_UNPACK_FILTERS)
return false;
filter = new CFilter;
_filters.Add(filter);
@@ -301,6 +307,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
if (initMask & (1 << i))
tempFilter->InitR[i] = inp.ReadEncodedUInt32();
}
bool isOK = true;
if (newFilter)
{
UInt32 vmCodeSize = inp.ReadEncodedUInt32();
@@ -308,7 +316,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
return false;
for (UInt32 i = 0; i < vmCodeSize; i++)
_vmCode[i] = (Byte)inp.ReadBits(8);
filter->PrepareProgram(_vmCode, vmCodeSize);
isOK = filter->PrepareProgram(_vmCode, vmCodeSize);
}
Byte *globalData = &tempFilter->GlobalData[0];
@@ -331,7 +339,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
for (UInt32 i = 0; i < dataSize; i++)
dest[i] = (Byte)inp.ReadBits(8);
}
return true;
return isOK;
}
bool CDecoder::ReadVmCodeLZ()
@@ -796,6 +805,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
{
_writtenFileSize = 0;
_unsupportedFilter = false;
if (!m_IsSolid)
{
_lzSize = 0;
@@ -843,6 +853,10 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
if (_writtenFileSize < _unpackSize)
return S_FALSE;
if (_unsupportedFilter)
return E_NOTIMPL;
return S_OK;
}
@@ -892,7 +906,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size < 1)
return E_INVALIDARG;
m_IsSolid = (data[0] != 0);
m_IsSolid = ((data[0] & 1) != 0);
return S_OK;
}

View File

@@ -194,6 +194,7 @@ class CDecoder:
bool m_IsSolid;
bool _lzMode;
bool _unsupportedFilter;
UInt32 PrevAlignBits;
UInt32 PrevAlignCount;

View File

@@ -12,6 +12,8 @@ Note:
#include "StdAfx.h"
#include <stdlib.h>
#include "../../../C/7zCrc.h"
#include "../../../C/Alloc.h"
@@ -55,6 +57,8 @@ namespace NVm {
static const UInt32 kStackRegIndex = kNumRegs - 1;
#ifdef RARVM_VM_ENABLE
static const UInt32 FLAG_C = 1;
static const UInt32 FLAG_Z = 2;
static const UInt32 FLAG_S = 0x80000000;
@@ -113,11 +117,14 @@ static const Byte kCmdFlags[]=
/* CMD_PRINT */ CF_OP0
};
#endif
CVm::CVm(): Mem(NULL) {}
bool CVm::Create()
{
if (Mem == NULL)
if (!Mem)
Mem = (Byte *)::MyAlloc(kSpaceSize + 4);
return (Mem != NULL);
}
@@ -145,12 +152,14 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);
bool res = true;
#ifdef RARVM_STANDARD_FILTERS
if (prg->StandardFilterIndex >= 0)
ExecuteStandardFilter(prg->StandardFilterIndex);
else
#endif
{
#ifdef RARVM_VM_ENABLE
res = ExecuteCode(prg);
if (!res)
{
@@ -158,7 +167,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
prg->Commands.Add(CCommand());
prg->Commands.Back().OpCode = CMD_RET;
}
#else
res = false;
#endif
}
UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;
UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;
if (newBlockPos + newBlockSize >= kSpaceSize)
@@ -175,9 +188,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
outGlobalData.ClearAndSetSize(dataSize);
memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize);
}
return res;
}
#ifdef RARVM_VM_ENABLE
#define SET_IP(IP) \
if ((IP) >= numCommands) return true; \
@@ -191,7 +206,7 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
UInt32 CVm::GetOperand32(const COperand *op) const
{
switch(op->Type)
switch (op->Type)
{
case OP_TYPE_REG: return R[op->Data];
case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);
@@ -201,7 +216,7 @@ UInt32 CVm::GetOperand32(const COperand *op) const
void CVm::SetOperand32(const COperand *op, UInt32 val)
{
switch(op->Type)
switch (op->Type)
{
case OP_TYPE_REG: R[op->Data] = val; return;
case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return;
@@ -210,7 +225,7 @@ void CVm::SetOperand32(const COperand *op, UInt32 val)
Byte CVm::GetOperand8(const COperand *op) const
{
switch(op->Type)
switch (op->Type)
{
case OP_TYPE_REG: return (Byte)R[op->Data];
case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];;
@@ -220,7 +235,7 @@ Byte CVm::GetOperand8(const COperand *op) const
void CVm::SetOperand8(const COperand *op, Byte val)
{
switch(op->Type)
switch (op->Type)
{
case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;
case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return;
@@ -253,10 +268,8 @@ bool CVm::ExecuteCode(const CProgram *prg)
for (;;)
{
switch(cmd->OpCode)
switch (cmd->OpCode)
{
#ifndef RARVM_NO_VM
case CMD_MOV:
SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));
break;
@@ -619,8 +632,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
}
break;
#endif
case CMD_RET:
{
if (R[kStackRegIndex] >= kSpaceSize)
@@ -638,7 +649,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
}
}
//////////////////////////////////////////////////////
// Read program
@@ -682,25 +692,31 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
inp.Init(code, codeSize);
StaticData.Clear();
if (inp.ReadBit())
{
UInt32 dataSize = inp.ReadEncodedUInt32() + 1;
for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)
StaticData.Add((Byte)inp.ReadBits(8));
}
while (inp.Avail())
{
Commands.Add(CCommand());
CCommand *cmd = &Commands.Back();
if (inp.ReadBit() == 0)
cmd->OpCode = (ECommand)inp.ReadBits(3);
else
cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));
if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE)
cmd->ByteMode = (inp.ReadBit()) ? true : false;
else
cmd->ByteMode = 0;
int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK);
if (opNum > 0)
{
DecodeArg(inp, cmd->Op1, cmd->ByteMode);
@@ -727,6 +743,7 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
}
}
}
if (cmd->ByteMode)
{
switch (cmd->OpCode)
@@ -751,6 +768,9 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
}
}
#endif
#ifdef RARVM_STANDARD_FILTERS
enum EStandardFilter
@@ -760,8 +780,8 @@ enum EStandardFilter
SF_ITANIUM,
SF_RGB,
SF_AUDIO,
SF_DELTA,
SF_UPCASE
SF_DELTA
// SF_UPCASE
};
static const struct CStandardFilterSignature
@@ -777,8 +797,8 @@ kStdFilters[]=
{ 120, 0x3769893f, SF_ITANIUM },
{ 29, 0x0e06077d, SF_DELTA },
{ 149, 0x1c2c5dc8, SF_RGB },
{ 216, 0xbc85e701, SF_AUDIO },
{ 40, 0x46b9c560, SF_UPCASE }
{ 216, 0xbc85e701, SF_AUDIO }
// { 40, 0x46b9c560, SF_UPCASE }
};
static int FindStandardFilter(const Byte *code, UInt32 codeSize)
@@ -795,28 +815,48 @@ static int FindStandardFilter(const Byte *code, UInt32 codeSize)
#endif
void CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
{
Byte xorSum = 0;
for (UInt32 i = 1; i < codeSize; i++)
xorSum ^= code[i];
bool CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
{
IsSupported = false;
#ifdef RARVM_VM_ENABLE
Commands.Clear();
#endif
#ifdef RARVM_STANDARD_FILTERS
StandardFilterIndex = -1;
#endif
if (xorSum == code[0] && codeSize > 0)
bool isOK = false;
Byte xorSum = 0;
for (UInt32 i = 0; i < codeSize; i++)
xorSum ^= code[i];
if (xorSum == 0 && codeSize != 0)
{
IsSupported = true;
isOK = true;
#ifdef RARVM_STANDARD_FILTERS
StandardFilterIndex = FindStandardFilter(code, codeSize);
if (StandardFilterIndex >= 0)
return;
return true;
#endif
#ifdef RARVM_VM_ENABLE
ReadProgram(code + 1, codeSize - 1);
#else
IsSupported = false;
#endif
}
#ifdef RARVM_VM_ENABLE
Commands.Add(CCommand());
Commands.Back().OpCode = CMD_RET;
#endif
return isOK;
}
void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)
@@ -833,12 +873,11 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
return;
dataSize -= 4;
const UInt32 kFileSize = 0x1000000;
Byte cmpByte2 = (Byte)(e9 ? 0xE9 : 0xE8);
Byte cmpMask = (Byte)(e9 ? 0xFE : 0xFF);
for (UInt32 curPos = 0; curPos < dataSize;)
{
Byte curByte = *(data++);
curPos++;
if (curByte == 0xE8 || curByte == cmpByte2)
if (((*data++) & cmpMask) == 0xE8)
{
UInt32 offset = curPos + fileOffset;
UInt32 addr = (Int32)GetValue32(data);
@@ -852,9 +891,9 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
}
}
static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos)
static inline UInt32 ItaniumGetOpType(const Byte *data, unsigned bitPos)
{
return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF;
return (data[bitPos >> 3] >> (bitPos & 7)) & 0xF;
}
static const Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
@@ -870,20 +909,20 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
{
Byte cmdMask = kCmdMasks[b];
if (cmdMask != 0)
for (int i = 0; i < 3; i++)
for (unsigned i = 0; i < 3; i++)
if (cmdMask & (1 << i))
{
int startPos = i * 41 + 18;
unsigned startPos = i * 41 + 18;
if (ItaniumGetOpType(data, startPos + 24) == 5)
{
const UInt32 kMask = 0xFFFFF;
Byte *p = data + ((unsigned int)startPos >> 3);
Byte *p = data + (startPos >> 3);
UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);
int inBit = (startPos & 7);
unsigned inBit = (startPos & 7);
UInt32 offset = (bitField >> inBit) & kMask;
UInt32 andMask = ~(kMask << inBit);
bitField = ((offset - fileOffset) & kMask) << inBit;
for (int j = 0; j < 3; j++)
for (unsigned j = 0; j < 3; j++)
{
p[j] &= andMask;
p[j] |= bitField;
@@ -1016,6 +1055,7 @@ static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)
}
}
/*
static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
{
UInt32 srcPos = 0, destPos = dataSize;
@@ -1028,6 +1068,7 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
}
return destPos - dataSize;
}
*/
void CVm::ExecuteStandardFilter(unsigned filterIndex)
{
@@ -1068,6 +1109,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
SetBlockPos(dataSize);
AudioDecode(Mem, dataSize, R[0]);
break;
/*
case SF_UPCASE:
if (dataSize >= kGlobalOffset / 2)
break;
@@ -1075,6 +1117,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
SetBlockSize(destSize);
SetBlockPos(dataSize);
break;
*/
}
}

View File

@@ -7,10 +7,10 @@
#include "../../../C/CpuArch.h"
#include "../../Common/MyTypes.h"
#include "../../Common/MyVector.h"
#define RARVM_STANDARD_FILTERS
// #define RARVM_VM_ENABLE
namespace NCompress {
namespace NRar3 {
@@ -39,12 +39,12 @@ namespace NVm {
inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }
inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); }
const int kNumRegBits = 3;
const unsigned kNumRegBits = 3;
const UInt32 kNumRegs = 1 << kNumRegBits;
const UInt32 kNumGpRegs = kNumRegs - 1;
const UInt32 kSpaceSize = 0x40000;
const UInt32 kSpaceMask = kSpaceSize -1;
const UInt32 kSpaceMask = kSpaceSize - 1;
const UInt32 kGlobalOffset = 0x3C000;
const UInt32 kGlobalSize = 0x2000;
const UInt32 kFixedGlobalSize = 64;
@@ -57,6 +57,9 @@ namespace NGlobalOffset
const UInt32 kGlobalMemOutSize = 0x30;
}
#ifdef RARVM_VM_ENABLE
enum ECommand
{
CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC,
@@ -89,27 +92,36 @@ struct CCommand
COperand Op1, Op2;
};
#endif
struct CBlockRef
{
UInt32 Offset;
UInt32 Size;
};
class CProgram
{
#ifdef RARVM_VM_ENABLE
void ReadProgram(const Byte *code, UInt32 codeSize);
public:
CRecordVector<CCommand> Commands;
#endif
public:
#ifdef RARVM_STANDARD_FILTERS
int StandardFilterIndex;
#endif
bool IsSupported;
CRecordVector<Byte> StaticData;
private:
void ReadProgram(const Byte *code, UInt32 codeSize);
public:
void PrepareProgram(const Byte *code, UInt32 codeSize);
bool PrepareProgram(const Byte *code, UInt32 codeSize);
};
struct CProgramInitState
{
UInt32 InitR[kNumGpRegs];
@@ -122,6 +134,7 @@ struct CProgramInitState
}
};
class CVm
{
static UInt32 GetValue(bool byteMode, const void *addr)
@@ -146,15 +159,18 @@ class CVm
void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }
public:
static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }
private:
#ifdef RARVM_VM_ENABLE
UInt32 GetOperand32(const COperand *op) const;
void SetOperand32(const COperand *op, UInt32 val);
Byte GetOperand8(const COperand *op) const;
void SetOperand8(const COperand *op, Byte val);
UInt32 GetOperand(bool byteMode, const COperand *op) const;
void SetOperand(bool byteMode, const COperand *op, UInt32 val);
bool ExecuteCode(const CProgram *prg);
#endif
#ifdef RARVM_STANDARD_FILTERS
void ExecuteStandardFilter(unsigned filterIndex);
@@ -163,6 +179,7 @@ private:
Byte *Mem;
UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)
UInt32 Flags;
public:
CVm();
~CVm();
@@ -171,7 +188,6 @@ public:
bool Execute(CProgram *prg, const CProgramInitState *initState,
CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);
const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }
};
#endif

View File

@@ -0,0 +1,960 @@
// Rar5Decoder.cpp
// According to unRAR license, this code may not be used to develop
// a program that creates RAR archives
#include "StdAfx.h"
// #include <stdio.h>
#include "../Common/StreamUtils.h"
#include "Rar5Decoder.h"
namespace NCompress {
namespace NRar5 {
static const size_t kInputBufSize = 1 << 20;
void CBitDecoder::Prepare2() throw()
{
const unsigned kSize = 16;
if (_buf > _bufLim)
return;
size_t rem = _bufLim - _buf;
if (rem != 0)
memcpy(_bufBase, _buf, rem);
_bufLim = _bufBase + rem;
_processedSize += (_buf - _bufBase);
_buf = _bufBase;
if (!_wasFinished)
{
UInt32 processed = (UInt32)(kInputBufSize - rem);
_hres = _stream->Read(_bufLim, (UInt32)processed, &processed);
_bufLim += processed;
_wasFinished = (processed == 0);
if (_hres != S_OK)
{
_wasFinished = true;
// throw CInBufferException(result);
}
}
rem = _bufLim - _buf;
_bufCheck = _buf;
if (rem < kSize)
memset(_bufLim, 0xFF, kSize - rem);
else
_bufCheck = _bufLim - kSize;
SetCheck2();
}
enum FilterType
{
FILTER_DELTA = 0,
FILTER_E8,
FILTER_E8E9,
FILTER_ARM
};
static const size_t kWriteStep = (size_t)1 << 22;
CDecoder::CDecoder():
_window(NULL),
_winPos(0),
_winSizeAllocated(0),
_lzSize(0),
_lzEnd(0),
_writtenFileSize(0),
_dictSizeLog(0),
_isSolid(false),
_wasInit(false),
_inputBuf(NULL)
{
}
CDecoder::~CDecoder()
{
::MidFree(_window);
::MidFree(_inputBuf);
}
HRESULT CDecoder::WriteData(const Byte *data, size_t size)
{
HRESULT res = S_OK;
if (!_unpackSize_Defined || _writtenFileSize < _unpackSize)
{
size_t cur = size;
if (_unpackSize_Defined)
{
UInt64 rem = _unpackSize - _writtenFileSize;
if (cur > rem)
cur = (size_t)rem;
}
res = WriteStream(_outStream, data, cur);
if (res != S_OK)
_writeError = true;
}
_writtenFileSize += size;
return res;
}
HRESULT CDecoder::ExecuteFilter(const CFilter &f)
{
bool useDest = false;
Byte *data = _filterSrc;
UInt32 dataSize = f.Size;
// printf("\nType = %d offset = %9d size = %5d", f.Type, (unsigned)(f.Start - _lzFileStart), dataSize);
switch (f.Type)
{
case FILTER_E8:
case FILTER_E8E9:
{
// printf(" FILTER_E8");
if (dataSize > 4)
{
dataSize -= 4;
UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart);
const UInt32 kFileSize = (UInt32)1 << 24;
Byte cmpMask = (Byte)(f.Type == FILTER_E8 ? 0xFF : 0xFE);
for (UInt32 curPos = 0; curPos < dataSize;)
{
curPos++;
if (((*data++) & cmpMask) == 0xE8)
{
UInt32 offset = (curPos + fileOffset) & (kFileSize - 1);
UInt32 addr = GetUi32(data);
if (addr < kFileSize)
{
SetUi32(data, addr - offset);
}
else if (addr > ((UInt32)0xFFFFFFFF - offset)) // (addr > ~(offset))
{
SetUi32(data, addr + kFileSize);
}
data += 4;
curPos += 4;
}
}
}
break;
}
case FILTER_ARM:
{
if (dataSize >= 4)
{
dataSize -= 4;
UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart);
for (UInt32 curPos = 0; curPos <= dataSize; curPos += 4)
{
Byte *d = data + curPos;
if (d[3] == 0xEB)
{
UInt32 offset = d[0] | ((UInt32)d[1] << 8) | ((UInt32)d[2] << 16);
offset -= (fileOffset + curPos) >> 2;
d[0] = (Byte)offset;
d[1] = (Byte)(offset >> 8);
d[2] = (Byte)(offset >> 16);
}
}
}
break;
}
case FILTER_DELTA:
{
// printf(" channels = %d", f.Channels);
_filterDst.AllocAtLeast(dataSize);
if (!_filterDst.IsAllocated())
return E_OUTOFMEMORY;
Byte *dest = _filterDst;
UInt32 numChannels = f.Channels;
for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
{
Byte prevByte = 0;
for (UInt32 destPos = curChannel; destPos < dataSize; destPos += numChannels)
dest[destPos] = (prevByte = (Byte)(prevByte - *data++));
}
useDest = true;
break;
}
default:
_unsupportedFilter = true;
}
return WriteData(useDest ?
(const Byte *)_filterDst :
(const Byte *)_filterSrc,
f.Size);
}
HRESULT CDecoder::WriteBuf()
{
DeleteUnusedFilters();
for (unsigned i = 0; i < _filters.Size();)
{
const CFilter &f = _filters[i];
UInt64 blockStart = f.Start;
size_t lzAvail = (size_t)(_lzSize - _lzWritten);
if (lzAvail == 0)
break;
if (blockStart > _lzWritten)
{
UInt64 rem = blockStart - _lzWritten;
size_t size = lzAvail;
if (size > rem)
size = (size_t)rem;
if (size != 0)
{
RINOK(WriteData(_window + _winPos - lzAvail, size));
_lzWritten += size;
}
continue;
}
UInt32 blockSize = f.Size;
size_t offset = (size_t)(_lzWritten - blockStart);
if (offset == 0)
{
_filterSrc.AllocAtLeast(blockSize);
if (!_filterSrc.IsAllocated())
return E_OUTOFMEMORY;
}
size_t blockRem = (size_t)blockSize - offset;
size_t size = lzAvail;
if (size > blockRem)
size = blockRem;
memcpy(_filterSrc + offset, _window + _winPos - lzAvail, size);
_lzWritten += size;
offset += size;
if (offset != blockSize)
return S_OK;
_numUnusedFilters = ++i;
RINOK(ExecuteFilter(f));
}
DeleteUnusedFilters();
if (!_filters.IsEmpty())
return S_OK;
size_t lzAvail = (size_t)(_lzSize - _lzWritten);
RINOK(WriteData(_window + _winPos - lzAvail, lzAvail));
_lzWritten += lzAvail;
return S_OK;
}
static UInt32 ReadUInt32(CBitDecoder &bi)
{
unsigned numBytes = bi.ReadBits9fix(2) + 1;
UInt32 v = 0;
for (unsigned i = 0; i < numBytes; i++)
v += ((UInt32)bi.ReadBits9fix(8) << (i * 8));
return v;
}
static const unsigned MAX_UNPACK_FILTERS = 8192;
HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
{
DeleteUnusedFilters();
if (_filters.Size() >= MAX_UNPACK_FILTERS)
{
RINOK(WriteBuf());
DeleteUnusedFilters();
if (_filters.Size() >= MAX_UNPACK_FILTERS)
{
_unsupportedFilter = true;
InitFilters();
}
}
_bitStream.Prepare();
CFilter f;
UInt32 blockStart = ReadUInt32(_bitStream);
f.Size = ReadUInt32(_bitStream);
// if (f.Size > ((UInt32)1 << 16)) _unsupportedFilter = true;
f.Type = (Byte)_bitStream.ReadBits9fix(3);
if (f.Type == FILTER_DELTA)
f.Channels = (Byte)(_bitStream.ReadBits9fix(5) + 1);
f.Start = _lzSize + blockStart;
if (f.Start < _filterEnd)
_unsupportedFilter = true;
else
{
_filterEnd = f.Start + f.Size;
if (f.Size != 0)
_filters.Add(f);
}
return S_OK;
}
#define RIF(x) { if (!(x)) return S_FALSE; }
HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
{
if (_progress)
{
UInt64 packSize = _bitStream.GetProcessedSize();
RINOK(_progress->SetRatioInfo(&packSize, &_writtenFileSize));
}
_bitStream.AlignToByte();
_bitStream.Prepare();
unsigned flags = _bitStream.ReadByteInAligned();
unsigned checkSum = _bitStream.ReadByteInAligned();
checkSum ^= flags;
UInt32 blockSize;
{
unsigned num = (flags >> 3) & 3;
if (num == 3)
return S_FALSE;
blockSize = _bitStream.ReadByteInAligned();
if (num > 0)
{
blockSize += (UInt32)_bitStream.ReadByteInAligned() << 8;
if (num > 1)
blockSize += (UInt32)_bitStream.ReadByteInAligned() << 16;
}
}
checkSum ^= blockSize ^ (blockSize >> 8) ^ (blockSize >> 16);
if ((Byte)checkSum != 0x5A)
return S_FALSE;
unsigned blockSizeBits7 = (flags & 7) + 1;
if (blockSize == 0 && blockSizeBits7 != 8)
return S_FALSE;
blockSize += (blockSizeBits7 >> 3);
blockSize--;
_bitStream._blockEndBits7 = (Byte)(blockSizeBits7 & 7);
_bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize;
_bitStream.SetCheck2();
_isLastBlock = ((flags & 0x40) != 0);
if ((flags & 0x80) == 0)
{
if (!_tableWasFilled && blockSize != 0)
return S_FALSE;
return S_OK;
}
_tableWasFilled = false;
{
Byte lens2[kLevelTableSize];
for (unsigned i = 0; i < kLevelTableSize;)
{
_bitStream.Prepare();
unsigned len = (unsigned)_bitStream.ReadBits9fix(4);
if (len == 15)
{
unsigned num = (unsigned)_bitStream.ReadBits9fix(4);
if (num != 0)
{
num += 2;
num += i;
if (num > kLevelTableSize)
num = kLevelTableSize;
do
lens2[i++] = 0;
while (i < num);
continue;
}
}
lens2[i++] = (Byte)len;
}
if (_bitStream.IsBlockOverRead())
return S_FALSE;
RIF(m_LevelDecoder.SetCodeLengths(lens2));
}
Byte lens[kTablesSizesSum];
unsigned i = 0;
while (i < kTablesSizesSum)
{
if (_bitStream._buf >= _bitStream._bufCheck2)
{
if (_bitStream._buf >= _bitStream._bufCheck)
_bitStream.Prepare();
if (_bitStream.IsBlockOverRead())
return S_FALSE;
}
UInt32 sym = m_LevelDecoder.DecodeSymbol(&_bitStream);
if (sym < 16)
lens[i++] = (Byte)sym;
else if (sym > kLevelTableSize)
return S_FALSE;
else
{
sym -= 16;
unsigned sh = ((sym & 1) << 2);
unsigned num = (unsigned)_bitStream.ReadBits9(3 + sh) + 3 + (sh << 1);
num += i;
if (num > kTablesSizesSum)
num = kTablesSizesSum;
if (sym < 2)
{
if (i == 0)
{
// return S_FALSE;
continue; // original unRAR
}
Byte v = lens[i - 1];
do
lens[i++] = v;
while (i < num);
}
else
{
do
lens[i++] = 0;
while (i < num);
}
}
}
if (_bitStream.IsBlockOverRead())
return S_FALSE;
if (_bitStream.InputEofError())
return S_FALSE;
RIF(m_MainDecoder.SetCodeLengths(&lens[0]));
RIF(m_DistDecoder.SetCodeLengths(&lens[kMainTableSize]));
RIF(m_AlignDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize]));
RIF(m_LenDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]));
_useAlignBits = false;
// _useAlignBits = true;
for (i = 0; i < kAlignTableSize; i++)
if (lens[kMainTableSize + kDistTableSize + i] != kNumAlignBits)
{
_useAlignBits = true;
break;
}
_tableWasFilled = true;
return S_OK;
}
static inline unsigned SlotToLen(CBitDecoder &_bitStream, unsigned slot)
{
if (slot < 8)
return slot + 2;
unsigned numBits = (slot >> 2) - 1;
return 2 + ((4 | (slot & 3)) << numBits) + _bitStream.ReadBits9(numBits);
}
static const UInt32 kSymbolRep = 258;
// static const unsigned kMaxMatchLen = 0x1001 + 3;
HRESULT CDecoder::DecodeLZ()
{
CBitDecoder _bitStream;
_bitStream._stream = _inStream;
_bitStream._bufBase = _inputBuf;
_bitStream.Init();
UInt32 rep0 = _reps[0];
UInt32 remLen = 0;
size_t limit;
{
size_t rem = _winSize - _winPos;
if (rem > kWriteStep)
rem = kWriteStep;
limit = _winPos + rem;
}
for (;;)
{
if (_winPos >= limit)
{
RINOK(WriteBuf());
if (_unpackSize_Defined && _writtenFileSize > _unpackSize)
break; // return S_FALSE;
{
size_t rem = _winSize - _winPos;
if (rem == 0)
{
_winPos = 0;
rem = _winSize;
}
if (rem > kWriteStep)
rem = kWriteStep;
limit = _winPos + rem;
}
if (remLen != 0)
{
size_t winPos = _winPos;
size_t winMask = _winMask;
size_t pos = (winPos - (size_t)rep0 - 1) & winMask;
Byte *win = _window;
do
{
if (winPos >= limit)
break;
win[winPos] = win[pos];
winPos++;
pos = (pos + 1) & winMask;
}
while (--remLen != 0);
_lzSize += winPos - _winPos;
_winPos = winPos;
continue;
}
}
if (_bitStream._buf >= _bitStream._bufCheck2)
{
if (_bitStream.InputEofError())
break; // return S_FALSE;
if (_bitStream._buf >= _bitStream._bufCheck)
_bitStream.Prepare2();
UInt64 processed = _bitStream.GetProcessedSize_Round();
if (processed >= _bitStream._blockEnd)
{
if (processed > _bitStream._blockEnd)
break; // return S_FALSE;
{
unsigned bits7 = _bitStream.GetProcessedBits7();
if (bits7 > _bitStream._blockEndBits7)
break; // return S_FALSE;
if (bits7 == _bitStream._blockEndBits7)
{
if (_isLastBlock)
{
_reps[0] = rep0;
if (_bitStream.InputEofError())
break;
/*
// packSize can be 15 bytes larger for encrypted archive
if (_packSize_Defined && _packSize < _bitStream.GetProcessedSize())
break;
*/
return _bitStream._hres;
// break;
}
RINOK(ReadTables(_bitStream));
continue;
}
}
}
}
UInt32 sym = m_MainDecoder.DecodeSymbol(&_bitStream);
if (sym < 256)
{
size_t winPos = _winPos;
_window[winPos] = (Byte)sym;
_winPos = winPos + 1;
_lzSize++;
continue;
}
UInt32 len;
if (sym < kSymbolRep + kNumReps)
{
if (sym >= kSymbolRep)
{
if (sym != kSymbolRep)
{
UInt32 dist;
if (sym == kSymbolRep + 1)
dist = _reps[1];
else
{
if (sym == kSymbolRep + 2)
dist = _reps[2];
else
{
dist = _reps[3];
_reps[3] = _reps[2];
}
_reps[2] = _reps[1];
}
_reps[1] = rep0;
rep0 = dist;
}
UInt32 sym = m_LenDecoder.DecodeSymbol(&_bitStream);
if (sym >= kLenTableSize)
break; // return S_FALSE;
len = SlotToLen(_bitStream, sym);
}
else
{
if (sym == 256)
{
RINOK(AddFilter(_bitStream));
continue;
}
else // if (sym == 257)
{
len = _lastLen;
// if (len = 0), we ignore that symbol, like original unRAR code, but it can mean error in stream.
// if (len == 0) return S_FALSE;
if (len == 0)
continue;
}
}
}
else if (sym >= kMainTableSize)
break; // return S_FALSE;
else
{
_reps[3] = _reps[2];
_reps[2] = _reps[1];
_reps[1] = rep0;
len = SlotToLen(_bitStream, sym - (kSymbolRep + kNumReps));
rep0 = m_DistDecoder.DecodeSymbol(&_bitStream);
if (rep0 >= 4)
{
if (rep0 >= _numCorrectDistSymbols)
break; // return S_FALSE;
unsigned numBits = (rep0 >> 1) - 1;
rep0 = (2 | (rep0 & 1)) << numBits;
if (numBits < kNumAlignBits)
rep0 += _bitStream.ReadBits9(numBits);
else
{
len += (numBits >= 7);
len += (numBits >= 12);
len += (numBits >= 17);
if (_useAlignBits)
{
// if (numBits > kNumAlignBits)
rep0 += (_bitStream.ReadBits32(numBits - kNumAlignBits) << kNumAlignBits);
UInt32 a = m_AlignDecoder.DecodeSymbol(&_bitStream);
if (a >= kAlignTableSize)
break; // return S_FALSE;
rep0 += a;
}
else
rep0 += _bitStream.ReadBits32(numBits);
}
}
}
_lastLen = len;
if (rep0 >= _lzSize)
_lzError = true;
{
UInt32 lenCur = len;
size_t winPos = _winPos;
size_t pos = (winPos - (size_t)rep0 - 1) & _winMask;
{
size_t rem = limit - winPos;
// size_t rem = _winSize - winPos;
if (lenCur > rem)
{
lenCur = (UInt32)rem;
remLen = len - lenCur;
}
}
Byte *win = _window;
_lzSize += lenCur;
_winPos = winPos + lenCur;
if (_winSize - pos >= lenCur)
{
const Byte *src = win + pos;
Byte *dest = win + winPos;
do
*dest++ = *src++;
while (--lenCur != 0);
}
else
{
do
{
win[winPos] = win[pos];
winPos++;
pos = (pos + 1) & _winMask;
}
while (--lenCur != 0);
}
}
}
if (_bitStream._hres != S_OK)
return _bitStream._hres;
return S_FALSE;
}
HRESULT CDecoder::CodeReal()
{
_unsupportedFilter = false;
_lzError = false;
_writeError = false;
if (!_isSolid || !_wasInit)
{
size_t clearSize = _winSize;
if (_lzSize < _winSize)
clearSize = (size_t)_lzSize;
memset(_window, 0, clearSize);
_wasInit = true;
_lzSize = 0;
_lzWritten = 0;
_winPos = 0;
for (unsigned i = 0; i < kNumReps; i++)
_reps[i] = (UInt32)0 - 1;
_lastLen = 0;
_tableWasFilled = false;
}
_isLastBlock = false;
InitFilters();
_filterEnd = 0;
_writtenFileSize = 0;
_lzFileStart = _lzSize;
_lzWritten = _lzSize;
HRESULT res = DecodeLZ();
HRESULT res2 = S_OK;
if (!_writeError && res != E_OUTOFMEMORY)
res2 = WriteBuf();
/*
if (res == S_OK)
if (InputEofError())
res = S_FALSE;
*/
if (res == S_OK)
res = res2;
if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize)
return S_FALSE;
return res;
}
// Original unRAR claims that maximum possible filter block size is (1 << 16) now,
// and (1 << 17) is minimum win size required to support filter.
// Original unRAR uses (1 << 18) for "extra safety and possible filter area size expansion"
// We can use any win size.
static const unsigned kWinSize_Log_Min = 17;
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{
try
{
if (_dictSizeLog >= sizeof(size_t) * 8)
return E_NOTIMPL;
if (!_isSolid)
_lzEnd = 0;
else
{
if (_lzSize < _lzEnd)
{
if (_window)
{
UInt64 rem = _lzEnd - _lzSize;
if (rem >= _winSize)
memset(_window, 0, _winSize);
else
{
size_t pos = (size_t)_lzSize & _winSize;
size_t rem2 = _winSize - pos;
if (rem2 > rem)
rem2 = (size_t)rem;
memset(_window + pos, 0, rem2);
rem -= rem2;
memset(_window, 0, (size_t)rem);
}
}
_lzEnd &= ((((UInt64)1) << 33) - 1);
_lzSize = _lzEnd;
_winPos = (size_t)(_lzSize & _winSize);
}
_lzEnd = _lzSize;
}
size_t newSize;
{
unsigned newSizeLog = _dictSizeLog;
if (newSizeLog < kWinSize_Log_Min)
newSizeLog = kWinSize_Log_Min;
newSize = (size_t)1 << newSizeLog;
_numCorrectDistSymbols = newSizeLog * 2;
}
if (!_window || _winSize != newSize)
{
if (!_isSolid && newSize > _winSizeAllocated)
{
::MidFree(_window);
_window = NULL;
_winSizeAllocated = 0;
}
Byte *win = _window;
if (!_window || newSize > _winSizeAllocated)
{
win = (Byte *)::MidAlloc(newSize);
if (!win)
return E_OUTOFMEMORY;
_winSizeAllocated = newSize;
memset(win, 0, newSize);
}
if (_isSolid && _window)
{
// original unRAR claims:
// "Archiving code guarantees that win size does not grow in the same solid stream",
// but the original unRAR decoder still supports such grow case.
Byte *winOld = _window;
size_t oldSize = _winSize;
size_t newMask = newSize - 1;
size_t oldMask = _winSize - 1;
size_t winPos = _winPos;
for (size_t i = 1; i < oldSize; i++) // i < oldSize) ?
win[(winPos - i) & newMask] = winOld[(winPos - i) & oldMask];
::MidFree(_window);
}
_window = win;
_winSize = newSize;
}
_winMask = _winSize - 1;
if (!_inputBuf)
{
_inputBuf = (Byte *)::MidAlloc(kInputBufSize);
if (!_inputBuf)
return E_OUTOFMEMORY;
}
_inStream = inStream;
_outStream = outStream;
/*
_packSize = 0;
_packSize_Defined = (inSize != NULL);
if (_packSize_Defined)
_packSize = *inSize;
*/
_unpackSize = 0;
_unpackSize_Defined = (outSize != NULL);
if (_unpackSize_Defined)
_unpackSize = *outSize;
if ((Int64)_unpackSize >= 0)
_lzEnd += _unpackSize;
else
_lzEnd = 0;
_progress = progress;
HRESULT res = CodeReal();
if (res != S_OK)
return res;
if (_lzError)
return S_FALSE;
if (_unsupportedFilter)
return E_NOTIMPL;
return S_OK;
}
// catch(const CInBufferException &e) { return e.ErrorCode; }
// catch(...) { return S_FALSE; }
catch(...) { return E_OUTOFMEMORY; }
// CNewException is possible here. But probably CNewException is caused
// by error in data stream.
}
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size != 2)
return E_NOTIMPL;
_dictSizeLog = (Byte)((data[0] & 0xF) + 17);
_isSolid = ((data[1] & 1) != 0);
return S_OK;
}
}}

View File

@@ -0,0 +1,335 @@
// Rar5Decoder.h
// According to unRAR license, this code may not be used to develop
// a program that creates RAR archives
#ifndef __COMPRESS_RAR5_DECODER_H
#define __COMPRESS_RAR5_DECODER_H
#include "../../../C/Alloc.h"
#include "../../../C/CpuArch.h"
#include "../../Common/MyBuffer.h"
#include "../../Common/MyCom.h"
#include "../../Common/MyException.h"
#include "../../Common/MyVector.h"
#include "../ICoder.h"
#include "HuffmanDecoder.h"
namespace NCompress {
namespace NRar5 {
class CMidBuffer
{
Byte *_data;
size_t _size;
CLASS_NO_COPY(CMidBuffer)
public:
CMidBuffer(): _data(NULL), _size(0) {};
~CMidBuffer() { ::MidFree(_data); }
bool IsAllocated() const { return _data != NULL; }
operator Byte *() { return _data; }
operator const Byte *() const { return _data; }
size_t Size() const { return _size; }
void AllocAtLeast(size_t size)
{
if (size > _size)
{
const size_t kMinSize = (1 << 16);
if (size < kMinSize)
size = kMinSize;
::MidFree(_data);
_data = (Byte *)::MidAlloc(size);
_size = size;
}
}
};
/*
struct CInBufferException: public CSystemException
{
CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
};
*/
class CBitDecoder
{
public:
const Byte *_buf;
unsigned _bitPos;
bool _wasFinished;
Byte _blockEndBits7;
const Byte *_bufCheck2;
const Byte *_bufCheck;
Byte *_bufLim;
Byte *_bufBase;
UInt64 _processedSize;
UInt64 _blockEnd;
ISequentialInStream *_stream;
HRESULT _hres;
void SetCheck2()
{
_bufCheck2 = _bufCheck;
if (_bufCheck > _buf)
{
UInt64 processed = GetProcessedSize_Round();
if (_blockEnd < processed)
_bufCheck2 = _buf;
else
{
UInt64 delta = _blockEnd - processed;
if ((size_t)(_bufCheck - _buf) > delta)
_bufCheck2 = _buf + (size_t)delta;
}
}
}
bool IsBlockOverRead() const
{
UInt64 v = GetProcessedSize_Round();
if (v < _blockEnd)
return false;
if (v > _blockEnd)
return true;
return _bitPos > _blockEndBits7;
}
/*
CBitDecoder() throw():
_buf(0),
_bufLim(0),
_bufBase(0),
_stream(0),
_processedSize(0),
_wasFinished(false)
{}
*/
void Init() throw()
{
_blockEnd = 0;
_blockEndBits7 = 0;
_bitPos = 0;
_processedSize = 0;
_buf = _bufBase;
_bufLim = _bufBase;
_bufCheck = _buf;
_bufCheck2 = _buf;
_wasFinished = false;
}
void Prepare2() throw();
void Prepare() throw()
{
if (_buf >= _bufCheck)
Prepare2();
}
bool ExtraBitsWereRead() const
{
return _buf >= _bufLim && (_buf > _bufLim || _bitPos != 0);
}
bool InputEofError() const { return ExtraBitsWereRead(); }
unsigned GetProcessedBits7() const { return _bitPos; }
UInt64 GetProcessedSize_Round() const { return _processedSize + (_buf - _bufBase); }
UInt64 GetProcessedSize() const { return _processedSize + (_buf - _bufBase) + ((_bitPos + 7) >> 3); }
void AlignToByte()
{
_buf += (_bitPos + 7) >> 3;
_bitPos = 0;
}
Byte ReadByteInAligned()
{
return *_buf++;
}
UInt32 GetValue(unsigned numBits)
{
UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];
v >>= (24 - numBits - _bitPos);
return v & ((1 << numBits) - 1);
}
void MovePos(unsigned numBits)
{
_bitPos += numBits;
_buf += (_bitPos >> 3);
_bitPos &= 7;
}
UInt32 ReadBits9(unsigned numBits)
{
const Byte *buf = _buf;
UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
v &= ((UInt32)0xFFFF >> _bitPos);
numBits += _bitPos;
v >>= (16 - numBits);
_buf = buf + (numBits >> 3);
_bitPos = numBits & 7;
return v;
}
UInt32 ReadBits9fix(unsigned numBits)
{
const Byte *buf = _buf;
UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
UInt32 mask = ((1 << numBits) - 1);
numBits += _bitPos;
v >>= (16 - numBits);
_buf = buf + (numBits >> 3);
_bitPos = numBits & 7;
return v & mask;
}
UInt32 ReadBits32(unsigned numBits)
{
UInt32 mask = ((1 << numBits) - 1);
numBits += _bitPos;
const Byte *buf = _buf;
UInt32 v = GetBe32(buf);
if (numBits > 32)
{
v <<= (numBits - 32);
v |= (UInt32)buf[4] >> (40 - numBits);
}
else
v >>= (32 - numBits);
_buf = buf + (numBits >> 3);
_bitPos = numBits & 7;
return v & mask;
}
};
struct CFilter
{
Byte Type;
Byte Channels;
UInt32 Size;
UInt64 Start;
};
const unsigned kNumReps = 4;
const unsigned kLenTableSize = 11 * 4;
const unsigned kMainTableSize = 256 + 1 + 1 + kNumReps + kLenTableSize;
const unsigned kDistTableSize = 64;
const unsigned kNumAlignBits = 4;
const unsigned kAlignTableSize = (1 << kNumAlignBits);
const unsigned kLevelTableSize = 20;
const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
const unsigned kNumHuffmanBits = 15;
class CDecoder:
public ICompressCoder,
public ICompressSetDecoderProperties2,
public CMyUnknownImp
{
bool _useAlignBits;
bool _isLastBlock;
bool _unpackSize_Defined;
// bool _packSize_Defined;
bool _unsupportedFilter;
bool _lzError;
bool _writeError;
// CBitDecoder _bitStream;
Byte *_window;
size_t _winPos;
size_t _winSize;
size_t _winMask;
UInt64 _lzSize;
unsigned _numCorrectDistSymbols;
unsigned _numUnusedFilters;
UInt64 _lzWritten;
UInt64 _lzFileStart;
UInt64 _unpackSize;
// UInt64 _packSize;
UInt64 _lzEnd;
UInt64 _writtenFileSize;
size_t _winSizeAllocated;
Byte _dictSizeLog;
bool _tableWasFilled;
bool _isSolid;
bool _wasInit;
UInt32 _reps[kNumReps];
UInt32 _lastLen;
UInt64 _filterEnd;
CMidBuffer _filterSrc;
CMidBuffer _filterDst;
CRecordVector<CFilter> _filters;
ISequentialInStream *_inStream;
ISequentialOutStream *_outStream;
ICompressProgressInfo *_progress;
Byte *_inputBuf;
NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
void InitFilters()
{
_numUnusedFilters = 0;
_filters.Clear();
}
void DeleteUnusedFilters()
{
if (_numUnusedFilters != 0)
{
_filters.DeleteFrontal(_numUnusedFilters);
_numUnusedFilters = 0;
}
}
HRESULT WriteData(const Byte *data, size_t size);
HRESULT ExecuteFilter(const CFilter &f);
HRESULT WriteBuf();
HRESULT AddFilter(CBitDecoder &_bitStream);
HRESULT ReadTables(CBitDecoder &_bitStream);
HRESULT DecodeLZ();
HRESULT CodeReal();
public:
CDecoder();
~CDecoder();
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
};
}}
#endif

View File

@@ -7,12 +7,14 @@
#include "Rar1Decoder.h"
#include "Rar2Decoder.h"
#include "Rar3Decoder.h"
#include "Rar5Decoder.h"
#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder())
CREATE_CODEC(1)
CREATE_CODEC(2)
CREATE_CODEC(3)
CREATE_CODEC(5)
#define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, "Rar" name, 1, false }
@@ -21,6 +23,7 @@ REGISTER_CODECS_VAR
RAR_CODEC(1, "1"),
RAR_CODEC(2, "2"),
RAR_CODEC(3, "3"),
RAR_CODEC(5, "5"),
};
REGISTER_CODECS(Rar)

View File

@@ -0,0 +1,62 @@
// HmacSha256.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "HmacSha256.h"
namespace NCrypto {
namespace NSha256 {
static const unsigned kBlockSize = 64;
void CHmac::SetKey(const Byte *key, size_t keySize)
{
Byte temp[kBlockSize];
size_t i;
for (i = 0; i < kBlockSize; i++)
temp[i] = 0;
if (keySize > kBlockSize)
{
Sha256_Init(&_sha);
Sha256_Update(&_sha, key, keySize);
Sha256_Final(&_sha, temp);
}
else
for (i = 0; i < keySize; i++)
temp[i] = key[i];
for (i = 0; i < kBlockSize; i++)
temp[i] ^= 0x36;
Sha256_Init(&_sha);
Sha256_Update(&_sha, temp, kBlockSize);
for (i = 0; i < kBlockSize; i++)
temp[i] ^= 0x36 ^ 0x5C;
Sha256_Init(&_sha2);
Sha256_Update(&_sha2, temp, kBlockSize);
}
void CHmac::Final(Byte *mac)
{
Sha256_Final(&_sha, mac);
Sha256_Update(&_sha2, mac, SHA256_DIGEST_SIZE);
Sha256_Final(&_sha2, mac);
}
/*
void CHmac::Final(Byte *mac, size_t macSize)
{
Byte digest[SHA256_DIGEST_SIZE];
Final(digest);
for (size_t i = 0; i < macSize; i++)
mac[i] = digest[i];
}
*/
}}

View File

@@ -0,0 +1,27 @@
// HmacSha256.h
// Implements HMAC-SHA-256 (RFC2104, FIPS-198)
#ifndef __CRYPTO_HMAC_SHA256_H
#define __CRYPTO_HMAC_SHA256_H
#include "../../../C/Sha256.h"
namespace NCrypto {
namespace NSha256 {
const unsigned kDigestSize = SHA256_DIGEST_SIZE;
class CHmac
{
CSha256 _sha;
CSha256 _sha2;
public:
void SetKey(const Byte *key, size_t keySize);
void Update(const Byte *data, size_t dataSize) { Sha256_Update(&_sha, data, dataSize); }
void Final(Byte *mac);
// void Final(Byte *mac, size_t macSize);
};
}}
#endif

View File

@@ -9,7 +9,7 @@
#include "Rar20Crypto.h"
namespace NCrypto {
namespace NRar20 {
namespace NRar2 {
static const unsigned kNumRounds = 32;
@@ -39,44 +39,48 @@ void CData::UpdateKeys(const Byte *data)
Keys[j] ^= g_CrcTable[data[i + j]];
}
static void Swap(Byte *b1, Byte *b2)
static inline void Swap(Byte &b1, Byte &b2)
{
Byte b = *b1;
*b1 = *b2;
*b2 = b;
Byte b = b1;
b1 = b2;
b2 = b;
}
void CData::SetPassword(const Byte *data, UInt32 size)
void CData::SetPassword(const Byte *data, unsigned size)
{
Keys[0] = 0xD3A3B879L;
Keys[1] = 0x3F6D12F7L;
Keys[2] = 0x7515A235L;
Keys[3] = 0xA4E7F123L;
Byte psw[256];
if (size >= sizeof(psw))
size = sizeof(psw) - 1;
Byte psw[128];
memset(psw, 0, sizeof(psw));
if (size != 0)
{
if (size >= sizeof(psw))
size = sizeof(psw) - 1;
memcpy(psw, data, size);
}
memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable));
for (UInt32 j = 0; j < 256; j++)
for (UInt32 i = 0; i < size; i += 2)
for (unsigned j = 0; j < 256; j++)
for (unsigned i = 0; i < size; i += 2)
{
UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++)
Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]);
unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
unsigned n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++)
Swap(SubstTable[n1 & 0xFF], SubstTable[(n1 + i + k) & 0xFF]);
}
for (UInt32 i = 0; i < size; i += 16)
EncryptBlock(&psw[i]);
for (unsigned i = 0; i < size; i += 16)
EncryptBlock(psw + i);
}
void CData::CryptBlock(Byte *buf, bool encrypt)
{
Byte inBuf[16];
UInt32 A, B, C, D, T, TA, TB;
UInt32 A, B, C, D;
A = GetUi32(buf + 0) ^ Keys[0];
B = GetUi32(buf + 4) ^ Keys[1];
@@ -89,14 +93,10 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
for (unsigned i = 0; i < kNumRounds; i++)
{
UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];
T = ((C + rotlFixed(D, 11)) ^ key);
TA = A ^ SubstLong(T);
T = ((D ^ rotlFixed(C, 17)) + key);
TB = B ^ SubstLong(T);
A = C;
B = D;
C = TA;
D = TB;
UInt32 TA = A ^ SubstLong((C + rotlFixed(D, 11)) ^ key);
UInt32 TB = B ^ SubstLong((D ^ rotlFixed(C, 17)) + key);
A = C; C = TA;
B = D; D = TB;
}
SetUi32(buf + 0, C ^ Keys[0]);
@@ -107,12 +107,6 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
UpdateKeys(encrypt ? buf : inBuf);
}
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
_cipher.SetPassword(data, size);
return S_OK;
}
STDMETHODIMP CDecoder::Init()
{
return S_OK;
@@ -126,10 +120,10 @@ STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
return 0;
if (size < kBlockSize)
return kBlockSize;
UInt32 i;
size -= kBlockSize;
UInt32 i;
for (i = 0; i <= size; i += kBlockSize)
_cipher.DecryptBlock(data + i);
DecryptBlock(data + i);
return i;
}

View File

@@ -6,13 +6,12 @@
#include "../../Common/MyCom.h"
#include "../ICoder.h"
#include "../IPassword.h"
namespace NCrypto {
namespace NRar20 {
namespace NRar2 {
/* ICompressFilter::Init() does nothing for this filter.
Call CryptoSetPassword() to initialize filter. */
Call SetPassword() to initialize filter. */
class CData
{
@@ -31,22 +30,17 @@ class CData
public:
void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }
void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }
void SetPassword(const Byte *password, UInt32 passwordLen);
void SetPassword(const Byte *password, unsigned passwordLen);
};
class CDecoder:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp,
public CData
{
CData _cipher;
public:
MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
MY_UNKNOWN_IMP
INTERFACE_ICompressFilter(;)
};
}}

257
CPP/7zip/Crypto/Rar5Aes.cpp Normal file
View File

@@ -0,0 +1,257 @@
// Crypto/Rar5Aes.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#ifndef _7ZIP_ST
#include "../../Windows/Synchronization.h"
#endif
#include "Rar5Aes.h"
namespace NCrypto {
namespace NRar5 {
static const unsigned kNumIterationsLog_Max = 24;
static const unsigned kPswCheckCsumSize = 4;
static const unsigned kCheckSize = kPswCheckSize + kPswCheckCsumSize;
CKey::CKey():
_needCalc(true),
_numIterationsLog(0)
{
for (unsigned i = 0; i < sizeof(_salt); i++)
_salt[i] = 0;
}
CDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {}
static unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val)
{
unsigned i;
*val = 0;
for (i = 0; i < maxSize;)
{
Byte b = p[i];
if (i < 10)
*val |= (UInt64)(b & 0x7F) << (7 * i++);
if ((b & 0x80) == 0)
return i;
}
return 0;
}
HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV, bool isService)
{
UInt64 Version;
unsigned num = ReadVarInt(p, size, &Version);
if (num == 0)
return E_NOTIMPL;
p += num;
size -= num;
if (Version != 0)
return E_NOTIMPL;
num = ReadVarInt(p, size, &Flags);
if (num == 0)
return E_NOTIMPL;
p += num;
size -= num;
bool isCheck = IsThereCheck();
if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize : 0))
return E_NOTIMPL;
if (_numIterationsLog != p[0])
{
_numIterationsLog = p[0];
_needCalc = true;
}
p++;
if (memcmp(_salt, p, kSaltSize) != 0)
{
memcpy(_salt, p, kSaltSize);
_needCalc = true;
}
p += kSaltSize;
if (includeIV)
{
memcpy(_iv, p, AES_BLOCK_SIZE);
p += AES_BLOCK_SIZE;
}
_canCheck = true;
if (isCheck)
{
memcpy(_check, p, kPswCheckSize);
CSha256 sha;
Byte digest[SHA256_DIGEST_SIZE];
Sha256_Init(&sha);
Sha256_Update(&sha, _check, kPswCheckSize);
Sha256_Final(&sha, digest);
_canCheck = (memcmp(digest, p + kPswCheckSize, kPswCheckCsumSize) == 0);
if (_canCheck && isService)
{
// There was bug in RAR 5.21- : PswCheck field in service records ("QO") contained zeros.
// so we disable password checking for such bad records.
_canCheck = false;
for (unsigned i = 0; i < kPswCheckSize; i++)
if (p[i] != 0)
{
_canCheck = true;
break;
}
}
}
return (_numIterationsLog <= kNumIterationsLog_Max ? S_OK : E_NOTIMPL);
}
void CDecoder::SetPassword(const Byte *data, size_t size)
{
if (size != _password.Size() || memcmp(data, _password, size) != 0)
{
_needCalc = true;
_password.CopyFrom(data, size);
}
}
STDMETHODIMP CDecoder::Init()
{
CalcKey_and_CheckPassword();
RINOK(SetKey(_key, kAesKeySize));
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
return CAesCbcCoder::Init();
}
UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const
{
NSha256::CHmac ctx;
ctx.SetKey(_hashKey, NSha256::kDigestSize);
Byte v[4];
SetUi32(v, crc);
ctx.Update(v, 4);
Byte h[NSha256::kDigestSize];
ctx.Final(h);
crc = 0;
for (unsigned i = 0; i < NSha256::kDigestSize; i++)
crc ^= (UInt32)h[i] << ((i & 3) * 8);
return crc;
};
void CDecoder::Hmac_Convert_32Bytes(Byte *data) const
{
NSha256::CHmac ctx;
ctx.SetKey(_hashKey, NSha256::kDigestSize);
ctx.Update(data, NSha256::kDigestSize);
ctx.Final(data);
};
#ifndef _7ZIP_ST
static CKey g_Key;
static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
#define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
#else
#define MT_LOCK
#endif
bool CDecoder::CalcKey_and_CheckPassword()
{
if (_needCalc)
{
{
MT_LOCK
if (!g_Key._needCalc && IsKeyEqualTo(g_Key))
{
CopyCalcedKeysFrom(g_Key);
_needCalc = false;
}
}
if (_needCalc)
{
Byte pswCheck[SHA256_DIGEST_SIZE];
{
// Pbkdf HMAC-SHA-256
NSha256::CHmac baseCtx;
baseCtx.SetKey(_password, _password.Size());
NSha256::CHmac ctx = baseCtx;
ctx.Update(_salt, sizeof(_salt));
Byte u[NSha256::kDigestSize];
Byte key[NSha256::kDigestSize];
u[0] = 0;
u[1] = 0;
u[2] = 0;
u[3] = 1;
ctx.Update(u, 4);
ctx.Final(u);
memcpy(key, u, NSha256::kDigestSize);
UInt32 numIterations = ((UInt32)1 << _numIterationsLog) - 1;
for (unsigned i = 0; i < 3; i++)
{
UInt32 j = numIterations;
for (; j != 0; j--)
{
ctx = baseCtx;
ctx.Update(u, NSha256::kDigestSize);
ctx.Final(u);
for (unsigned s = 0; s < NSha256::kDigestSize; s++)
key[s] ^= u[s];
}
// RAR uses additional iterations for additional keys
memcpy((i == 0 ? _key : (i == 1 ? _hashKey : pswCheck)), key, NSha256::kDigestSize);
numIterations = 16;
}
}
{
unsigned i;
for (i = 0; i < kPswCheckSize; i++)
_check_Calced[i] = pswCheck[i];
for (i = kPswCheckSize; i < SHA256_DIGEST_SIZE; i++)
_check_Calced[i & (kPswCheckSize - 1)] ^= pswCheck[i];
}
_needCalc = false;
{
MT_LOCK
g_Key = *this;
}
}
}
if (IsThereCheck() && _canCheck)
return (memcmp(_check_Calced, _check, kPswCheckSize) == 0);
return true;
}
}}

84
CPP/7zip/Crypto/Rar5Aes.h Normal file
View File

@@ -0,0 +1,84 @@
// Crypto/Rar5Aes.h
#ifndef __CRYPTO_RAR5_AES_H
#define __CRYPTO_RAR5_AES_H
#include "../../../C/Aes.h"
#include "../../Common/MyBuffer.h"
#include "HmacSha256.h"
#include "MyAes.h"
namespace NCrypto {
namespace NRar5 {
const unsigned kSaltSize = 16;
const unsigned kPswCheckSize = 8;
const unsigned kAesKeySize = 32;
namespace NCryptoFlags
{
const unsigned kPswCheck = 1 << 0;
const unsigned kUseMAC = 1 << 1;
}
struct CKey
{
bool _needCalc;
unsigned _numIterationsLog;
Byte _salt[kSaltSize];
CByteBuffer _password;
Byte _key[kAesKeySize];
Byte _check_Calced[kPswCheckSize];
Byte _hashKey[SHA256_DIGEST_SIZE];
void CopyCalcedKeysFrom(const CKey &k)
{
memcpy(_key, k._key, sizeof(_key));
memcpy(_check_Calced, k._check_Calced, sizeof(_check_Calced));
memcpy(_hashKey, k._hashKey, sizeof(_hashKey));
}
bool IsKeyEqualTo(const CKey &key)
{
return (_numIterationsLog == key._numIterationsLog
&& memcmp(_salt, key._salt, sizeof(_salt)) == 0
&& _password == key._password);
}
CKey();
};
class CDecoder:
public CAesCbcDecoder,
public CKey
{
Byte _check[kPswCheckSize];
bool _canCheck;
UInt64 Flags;
bool IsThereCheck() const { return ((Flags & NCryptoFlags::kPswCheck) != 0); }
public:
Byte _iv[AES_BLOCK_SIZE];
CDecoder();
STDMETHOD(Init)();
void SetPassword(const Byte *data, size_t size);
HRESULT SetDecoderProps(const Byte *data, unsigned size, bool includeIV, bool isService);
bool CalcKey_and_CheckPassword();
bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }
UInt32 Hmac_Convert_Crc32(UInt32 crc) const;
void Hmac_Convert_32Bytes(Byte *data) const;
};
}}
#endif

View File

@@ -1,5 +1,4 @@
// Crypto/RarAes.cpp
// Note: you must include MyAes.cpp to project to initialize AES tables
#include "StdAfx.h"
@@ -7,10 +6,10 @@
#include "Sha1Cls.h"
namespace NCrypto {
namespace NRar29 {
namespace NRar3 {
CDecoder::CDecoder():
CAesCbcDecoder(kRarAesKeySize),
CAesCbcDecoder(kAesKeySize),
_thereIsSalt(false),
_needCalc(true),
_rar350Mode(false)
@@ -19,7 +18,7 @@ CDecoder::CDecoder():
_salt[i] = 0;
}
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
HRESULT CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
bool prev = _thereIsSalt;
_thereIsSalt = false;
@@ -53,12 +52,12 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
return S_OK;
}
static const unsigned kPasswordLen_MAX = 127 * 2;
static const unsigned kPasswordLen_Bytes_MAX = 127 * 2;
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
void CDecoder::SetPassword(const Byte *data, unsigned size)
{
if (size > kPasswordLen_MAX)
size = kPasswordLen_MAX;
if (size > kPasswordLen_Bytes_MAX)
size = kPasswordLen_Bytes_MAX;
bool same = false;
if (size == _password.Size())
{
@@ -73,13 +72,12 @@ STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
if (!_needCalc && !same)
_needCalc = true;
_password.CopyFrom(data, (size_t)size);
return S_OK;
}
STDMETHODIMP CDecoder::Init()
{
CalcKey();
RINOK(SetKey(_key, kRarAesKeySize));
RINOK(SetKey(_key, kAesKeySize));
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
return CAesCbcCoder::Init();
}
@@ -91,7 +89,7 @@ void CDecoder::CalcKey()
const unsigned kSaltSize = 8;
Byte buf[kPasswordLen_MAX + kSaltSize];
Byte buf[kPasswordLen_Bytes_MAX + kSaltSize];
if (_password.Size() != 0)
memcpy(buf, _password, _password.Size());
@@ -109,7 +107,7 @@ void CDecoder::CalcKey()
Byte digest[NSha1::kDigestSize];
// rar reverts hash for sha.
const UInt32 kNumRounds = (1 << 18);
const UInt32 kNumRounds = ((UInt32)1 << 18);
UInt32 i;
for (i = 0; i < kNumRounds; i++)
{

View File

@@ -12,14 +12,14 @@
#include "MyAes.h"
namespace NCrypto {
namespace NRar29 {
namespace NRar3 {
const UInt32 kRarAesKeySize = 16;
const unsigned kAesKeySize = 16;
class CDecoder:
public CAesCbcDecoder,
public CAesCbcDecoder
// public ICompressSetDecoderProperties2,
public ICryptoSetPassword
// public ICryptoSetPassword
{
Byte _salt[8];
bool _thereIsSalt;
@@ -28,17 +28,20 @@ class CDecoder:
CByteBuffer _password;
Byte _key[kRarAesKeySize];
Byte _key[kAesKeySize];
Byte _iv[AES_BLOCK_SIZE];
void CalcKey();
public:
/*
MY_UNKNOWN_IMP1(
ICryptoSetPassword)
ICryptoSetPassword
// ICompressSetDecoderProperties2
*/
STDMETHOD(Init)();
STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
void SetPassword(const Byte *data, unsigned size);
HRESULT SetDecoderProperties2(const Byte *data, UInt32 size);
CDecoder();
void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }

View File

@@ -163,6 +163,7 @@ Handler GUIDs:
0C xz
0D ppmd
CC Rar5
CD IHex
CE Hxs
CF TE

View File

@@ -4,7 +4,6 @@
#define __IPROGRESS_H
#include "../Common/MyTypes.h"
#include "../Common/MyUnknown.h"
#include "IDecl.h"

View File

@@ -4,7 +4,7 @@
#define __ISTREAM_H
#include "../Common/MyTypes.h"
#include "../Common/MyUnknown.h"
#include "../Common/MyWindows.h"
#include "IDecl.h"

View File

@@ -102,6 +102,7 @@ enum
kpidStreamId,
kpidReadOnly,
kpidOutName,
kpidCopyLink,
kpid_NUM_DEFINED,

View File

@@ -380,6 +380,21 @@ STDMETHODIMP CAgent::DoOperation(
HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
if (res == S_OK && processedPaths)
{
{
/* OutHandler for 7z archives doesn't report compression operation for empty files.
So we must include these files manually */
FOR_VECTOR(i, updatePairs2)
{
const CUpdatePair2 &up = updatePairs2[i];
if (up.DirIndex >= 0 && up.NewData)
{
const CDirItem &di = dirItems.Items[up.DirIndex];
if (!di.IsDir() && di.Size == 0)
processedItems[up.DirIndex] = 1;
}
}
}
FOR_VECTOR (i, dirItems.Items)
if (processedItems[i] != 0)
processedPaths->Add(dirItems.GetPhyPath(i));

View File

@@ -4,6 +4,8 @@
#include <stdio.h>
#include "../../../Common/MyWindows.h"
#include "../../../Common/Defs.h"
#include "../../../Common/MyInitGuid.h"

View File

@@ -5,6 +5,8 @@
#undef sprintf
#undef printf
#include "../../../../C/Alloc.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
@@ -23,6 +25,7 @@
#endif
#include "../../Common/FilePathAutoRename.h"
// #include "../../Common/StreamUtils.h"
#include "../Common/ExtractingFilePath.h"
#include "../Common/PropIDUtils.h"
@@ -541,11 +544,54 @@ static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)
return s;
}
/*
#ifdef SUPPORT_LINKS
struct CTempMidBuffer
{
void *Buf;
CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); }
~CTempMidBuffer() { ::MidFree(Buf); }
};
HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream)
{
const size_t kBufSize = 1 << 16;
CTempMidBuffer buf(kBufSize);
if (!buf.Buf)
return E_OUTOFMEMORY;
NIO::CInFile inFile;
NIO::COutFile outFile;
if (!inFile.Open(_CopyFile_Path))
return SendMessageError_with_LastError("Open error", _CopyFile_Path);
for (;;)
{
UInt32 num;
if (!inFile.Read(buf.Buf, kBufSize, num))
return SendMessageError_with_LastError("Read error", _CopyFile_Path);
if (num == 0)
return S_OK;
RINOK(WriteStream(outStream, buf.Buf, num));
}
}
#endif
*/
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
{
COM_TRY_BEGIN
*outStream = 0;
*outStream = NULL;
#ifndef _SFX
if (_hashStream)
@@ -563,6 +609,11 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
_curSizeDefined = false;
_index = index;
#ifdef SUPPORT_LINKS
// _CopyFile_Path.Empty();
linkPath.Empty();
#endif
IInArchive *archive = _arc->Archive;
#ifndef _SFX
@@ -596,46 +647,56 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
#ifdef SUPPORT_LINKS
// bool isCopyLink = false;
bool isHardLink = false;
bool isJunction = false;
bool isRelative = false;
UString linkPath;
// RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink));
// if (isHardLink)
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, kpidHardLink, &prop));
if (prop.vt == VT_BSTR)
{
isHardLink = true;
// isCopyLink = false;
isRelative = false; // RAR5, TAR: hard links are from root folder of archive
linkPath.SetFromBstr(prop.bstrVal);
isRelative = false; // TAR: hard links are from root folder of archive
}
else if (prop.vt == VT_EMPTY)
{
// linkPath.Empty();
}
else
else if (prop.vt != VT_EMPTY)
return E_FAIL;
}
/*
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, kpidCopyLink, &prop));
if (prop.vt == VT_BSTR)
{
isHardLink = false;
isCopyLink = true;
isRelative = false; // RAR5: copy links are from root folder of archive
linkPath.SetFromBstr(prop.bstrVal);
}
else if (prop.vt != VT_EMPTY)
return E_FAIL;
}
*/
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, kpidSymLink, &prop));
if (prop.vt == VT_BSTR)
{
isHardLink = false;
// isCopyLink = false;
isRelative = true; // RAR5, TAR: symbolic links can be relative
linkPath.SetFromBstr(prop.bstrVal);
isRelative = true; // TAR: symbolic links are relative
}
else if (prop.vt == VT_EMPTY)
{
// linkPath.Empty();
}
else
else if (prop.vt != VT_EMPTY)
return E_FAIL;
}
bool isOkReparse = false;
if (linkPath.IsEmpty() && _arc->GetRawProps)
@@ -643,7 +704,9 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
const void *data;
UInt32 dataSize;
UInt32 propType;
_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
if (dataSize != 0)
{
if (propType != NPropDataType::kRaw)
@@ -654,6 +717,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
if (isOkReparse)
{
isHardLink = false;
// isCopyLink = false;
linkPath = reparse.GetPath();
isJunction = reparse.IsMountPoint();
isRelative = reparse.IsRelative();
@@ -670,6 +734,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
// rar5 uses "\??\" prefix for absolute links
if (linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR))
{
isRelative = false;
linkPath.DeleteFrontal(4);
}
for (;;)
// while (NName::IsAbsolutePath(linkPath))
{
@@ -1108,7 +1179,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
else
{
FString existPath;
if (isHardLink || !isRelative)
if (isHardLink /* || isCopyLink */ || !isRelative)
{
if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
{
@@ -1122,7 +1193,9 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
if (!existPath.IsEmpty())
{
if (isHardLink)
if (isHardLink /* || isCopyLink */)
{
// if (isHardLink)
{
if (!MyCreateHardLink(fullProcessedPath, existPath))
{
@@ -1130,6 +1203,28 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
// return S_OK;
}
}
/*
else
{
NFind::CFileInfo fi;
if (!fi.Find(existPath))
{
RINOK(SendMessageError2("Can not find the file for copying", existPath, fullProcessedPath));
}
else
{
if (_curSizeDefined && _curSize == fi.Size)
_CopyFile_Path = existPath;
else
{
RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath));
}
// RINOK(MyCopyFile(existPath, fullProcessedPath));
}
}
*/
}
else if (_ntOptions.SymLinks.Val)
{
// bool isSymLink = true; // = false for junction
@@ -1161,7 +1256,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
#endif
}
else
if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */)
#endif // SUPPORT_LINKS
{
bool needWriteFile = true;
@@ -1225,6 +1321,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
}
_outFileStream = outStreamLoc;
}
}
@@ -1250,12 +1347,34 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
#endif
if (outStreamLoc)
*outStream = outStreamLoc.Detach();
{
/*
#ifdef SUPPORT_LINKS
if (!_CopyFile_Path.IsEmpty())
{
RINOK(PrepareOperation(askExtractMode));
RINOK(MyCopyFile(outStreamLoc));
return SetOperationResult(NArchive::NExtract::NOperationResult::kOK);
}
if (isCopyLink && _testMode)
return S_OK;
#endif
*/
*outStream = outStreamLoc.Detach();
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
{
COM_TRY_BEGIN
@@ -1266,6 +1385,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
#endif
_extractMode = false;
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract:
@@ -1282,6 +1402,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
COM_TRY_END
}
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
{
COM_TRY_BEGIN
@@ -1346,6 +1467,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
if (!_curSizeDefined)
GetUnpackSize();
if (_curSizeDefined)
{
#ifdef SUPPORT_ALT_STREAMS
@@ -1367,8 +1489,11 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
if (_extractMode && _fi.AttribDefined)
SetFileAttrib(_diskFilePath, _fi.Attrib);
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
return S_OK;
COM_TRY_END
}

View File

@@ -299,14 +299,23 @@ public:
const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize);
#ifdef SUPPORT_LINKS
private:
CHardLinks _hardLinks;
UString linkPath;
// FString _CopyFile_Path;
// HRESULT MyCopyFile(ISequentialOutStream *outStream);
public:
// call PrepareHardLinks() after Init()
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
#endif
#ifdef SUPPORT_ALT_STREAMS
CObjectVector<CIndexToPathPair> _renamedFiles;
#endif

View File

@@ -48,18 +48,13 @@ class COpenCallbackImp:
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback)
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName)
#ifndef _NO_CRYPTO
MY_UNKNOWN_IMP3(
IArchiveOpenVolumeCallback,
ICryptoGetTextPassword,
IArchiveOpenSetSubArchiveName
)
#else
MY_UNKNOWN_IMP2(
IArchiveOpenVolumeCallback,
IArchiveOpenSetSubArchiveName
)
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IArchiveOpenCallback(;)
INTERFACE_IArchiveOpenVolumeCallback(;)
@@ -93,7 +88,8 @@ public:
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
// UInt64 TotalSize;
COpenCallbackImp(): Callback(NULL) {}
COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {}
void Init(const FString &folderPrefix, const FString &fileName)
{
_folderPrefix = folderPrefix;
@@ -106,6 +102,7 @@ public:
// TotalSize = 0;
PasswordWasAsked = false;
}
bool SetSecondFileInfo(CFSTR newName)
{
return _fileInfo.Find(newName) && !_fileInfo.IsDir();

View File

@@ -1566,7 +1566,8 @@ static const CBenchHash g_Hash[] =
{ 10, 339, 0x8F8FEDAB, "CRC32:8" },
{ 10, 512, 0xDF1C17CC, "CRC64" },
{ 10, 5100, 0x2D79FF2E, "SHA256" },
{ 10, 2340, 0x4C25132B, "SHA1" }
{ 10, 2340, 0x4C25132B, "SHA1" },
{ 2, 5500, 0xE084E913, "BLAKE2sp" }
};
struct CTotalBenchRes

View File

@@ -865,7 +865,7 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
{
const CCodecLib &lib = Libs[ci.LibIndex];
if (lib.CreateDecoder)
return lib.CreateDecoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
}
return S_OK;
@@ -887,7 +887,7 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
{
const CCodecLib &lib = Libs[ci.LibIndex];
if (lib.CreateEncoder)
return lib.CreateEncoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
}
return S_OK;

View File

@@ -1083,6 +1083,7 @@ static bool IsNewStyleSignature(const CArcInfoEx &ai)
class CArchiveOpenCallback_Offset:
public IArchiveOpenCallback,
public IArchiveOpenVolumeCallback,
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
@@ -1090,19 +1091,24 @@ class CArchiveOpenCallback_Offset:
{
public:
CMyComPtr<IArchiveOpenCallback> Callback;
CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback;
UInt64 Files;
UInt64 Offset;
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
MY_UNKNOWN_IMP2(
IArchiveOpenCallback,
ICryptoGetTextPassword)
#else
MY_UNKNOWN_IMP1(IArchiveOpenCallback)
#endif
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
MY_QUERYINTERFACE_BEGIN2(IArchiveOpenCallback)
MY_QUERYINTERFACE_ENTRY(IArchiveOpenVolumeCallback)
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IArchiveOpenCallback(;)
INTERFACE_IArchiveOpenVolumeCallback(;)
#ifndef _NO_CRYPTO
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
@@ -1119,12 +1125,12 @@ STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)
}
#endif
STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *)
{
return S_OK;
}
STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes)
STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes)
{
if (!Callback)
return S_OK;
@@ -1134,8 +1140,25 @@ STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files *
return Callback->SetCompleted(&Files, &value);
}
STDMETHODIMP CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value)
{
if (OpenVolumeCallback)
return OpenVolumeCallback->GetProperty(propID, value);
NCOM::PropVariant_Clear(value);
return S_OK;
// return E_NOTIMPL;
}
STDMETHODIMP CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream)
{
if (OpenVolumeCallback)
return OpenVolumeCallback->GetStream(name, inStream);
return S_FALSE;
}
#endif
UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
{
if (isDefinedProp != NULL)
@@ -2208,9 +2231,6 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
{
CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
CMyComPtr<IArchiveOpenCallback> openCallback_Offset = openCallback_Offset_Spec;
const size_t kBeforeSize = 1 << 16;
const size_t kAfterSize = 1 << 20;
const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize
@@ -2288,14 +2308,18 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
limitedStreamSpec->SetStream(op.stream);
openCallback_Offset_Spec->Callback = op.callback;
#ifndef _NO_CRYPTO
CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL;
CMyComPtr<IArchiveOpenCallback> openCallback_Offset;
if (op.callback)
{
openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
openCallback_Offset = openCallback_Offset_Spec;
openCallback_Offset_Spec->Callback = op.callback;
openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback);
#ifndef _NO_CRYPTO
openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
}
#endif
}
if (op.callback)
RINOK(op.callback->SetTotal(NULL, &fileSize));
@@ -2382,13 +2406,20 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
}
if (pos >= callbackPrev + (1 << 23))
bool useOffsetCallback = false;
if (openCallback_Offset)
{
openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
openCallback_Offset_Spec->Offset = pos;
RINOK(openCallback_Offset->SetCompleted(NULL, NULL));
useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);
if (pos >= callbackPrev + (1 << 23))
{
RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL));
callbackPrev = pos;
}
}
{
UInt64 endPos = bufPhyPos + bytesInBuf;
@@ -2557,13 +2588,20 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
UInt64 maxCheckStartPosition = 0;
if (openCallback_Offset)
{
openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
openCallback_Offset_Spec->Offset = startArcPos;
}
// HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
extractCallback_To_OpenCallback_Spec->Files = 0;
extractCallback_To_OpenCallback_Spec->Offset = startArcPos;
HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, openCallback_Offset, extractCallback_To_OpenCallback);
HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition,
useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback,
extractCallback_To_OpenCallback);
RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result));

View File

@@ -35,7 +35,7 @@ namespace NUpdateArchive {
{
NPairAction::EEnum StateActions[NPairState::kNumValues];
const bool IsEqualTo(const CActionSet &a) const
bool IsEqualTo(const CActionSet &a) const
{
for (unsigned i = 0; i < NPairState::kNumValues; i++)
if (StateActions[i] != a.StateActions[i])

View File

@@ -413,7 +413,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
{
case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
case kpidIsDir: prop = di.IsDir(); break;
case kpidSize: prop = di.Size; break;
case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
case kpidAttrib: prop = di.Attrib; break;
case kpidCTime: prop = di.CTime; break;
case kpidATime: prop = di.ATime; break;

View File

@@ -4,6 +4,10 @@
#include "ConsoleClose.h"
#if !defined(UNDER_CE) && defined(_WIN32)
#include "../../../Common/MyWindows.h"
#endif
namespace NConsoleClose {
unsigned g_BreakCounter = 0;

View File

@@ -123,6 +123,7 @@ static const char * const kPropIdToName[] =
, "Stream ID"
, "Read-only"
, "Out Name"
, "Copy Link"
};
static const char kEmptyAttribChar = '.';

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include <Psapi.h>
#include "../../../../C/CpuArch.h"
@@ -230,21 +232,29 @@ static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
}
static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
const CUpdateErrorInfo &errorInfo, CStdOutStream &so, bool showHeaders)
const CUpdateErrorInfo &errorInfo,
CStdOutStream *so,
CStdOutStream *se,
bool showHeaders)
{
int exitCode = NExitCode::kSuccess;
if (callback.ScanErrors.Paths.Size() != 0)
{
so << endl;
so << "Scan WARNINGS for files and folders:" << endl << endl;
PrintWarningsPaths(callback.ScanErrors, so);
so << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
so << endl;
if (se)
{
*se << endl;
*se << "Scan WARNINGS for files and folders:" << endl << endl;
PrintWarningsPaths(callback.ScanErrors, *se);
*se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
*se << endl;
}
exitCode = NExitCode::kWarning;
}
if (result != S_OK || errorInfo.ThereIsError())
{
if (se)
{
UString message;
if (!errorInfo.Message.IsEmpty())
@@ -265,7 +275,8 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
message.Add_LF();
}
if (!message.IsEmpty())
so << L"\nError:\n" << message;
*se << L"\nError:\n" << message;
}
// we will work with (result) later
// throw CSystemException(result);
@@ -277,17 +288,25 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
{
if (showHeaders)
if (callback.ScanErrors.Paths.Size() == 0)
so << kEverythingIsOk << endl;
if (so)
{
if (se)
se->Flush();
*so << kEverythingIsOk << endl;
}
}
else
{
so << endl;
so << "WARNINGS for files:" << endl << endl;
PrintWarningsPaths(callback.FailedFiles, so);
so << "WARNING: Cannot open " << numErrors << " file";
if (se)
{
*se << endl;
*se << "WARNINGS for files:" << endl << endl;
PrintWarningsPaths(callback.FailedFiles, *se);
*se << "WARNING: Cannot open " << numErrors << " file";
if (numErrors > 1)
so << 's';
so << endl;
*se << 's';
*se << endl;
}
exitCode = NExitCode::kWarning;
}
@@ -474,9 +493,6 @@ int Main2(
if (options.Number_for_Percents != k_OutStream_disabled)
percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
if (options.HelpMode)
{
ShowCopyrightAndHelp(g_StdStream, true);
@@ -589,6 +605,7 @@ int Main2(
if (options.Command.CommandType == NCommandType::kInfo)
{
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
unsigned i;
#ifdef EXTERNAL_CODECS
@@ -754,6 +771,7 @@ int Main2(
}
else if (options.Command.CommandType == NCommandType::kBenchmark)
{
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
options.Properties, options.NumIterations, (FILE *)so);
if (hresultMain == S_FALSE)
@@ -890,73 +908,91 @@ int Main2(
hresultMain = E_FAIL;
}
so << endl;
CStdOutStream *so = g_StdStream;
bool isError = false;
if (so)
{
*so << endl;
if (ecs->NumTryArcs > 1)
{
so << "Archives: " << ecs->NumTryArcs << endl;
so << "OK archives: " << ecs->NumOkArcs << endl;
*so << "Archives: " << ecs->NumTryArcs << endl;
*so << "OK archives: " << ecs->NumOkArcs << endl;
}
bool isError = false;
}
if (ecs->NumCantOpenArcs != 0)
{
isError = true;
so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
if (so)
*so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
}
if (ecs->NumArcsWithError != 0)
{
isError = true;
so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
if (so)
*so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
}
if (so)
{
if (ecs->NumArcsWithWarnings != 0)
so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
*so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
if (ecs->NumOpenArcWarnings != 0)
{
so << endl;
*so << endl;
if (ecs->NumOpenArcWarnings != 0)
so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
*so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
}
}
if (ecs->NumOpenArcErrors != 0)
{
isError = true;
so << endl;
if (so)
{
*so << endl;
if (ecs->NumOpenArcErrors != 0)
so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
*so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
}
}
if (isError)
retCode = NExitCode::kFatalError;
if (so)
if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
{
// if (ecs->NumArchives > 1)
{
so << endl;
*so << endl;
if (ecs->NumFileErrors != 0)
so << "Sub items Errors: " << ecs->NumFileErrors << endl;
*so << "Sub items Errors: " << ecs->NumFileErrors << endl;
}
}
else if (hresultMain == S_OK)
{
if (stat.NumFolders != 0)
so << "Folders: " << stat.NumFolders << endl;
*so << "Folders: " << stat.NumFolders << endl;
if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
so << "Files: " << stat.NumFiles << endl;
*so << "Files: " << stat.NumFiles << endl;
if (stat.NumAltStreams != 0)
{
so << "Alternate Streams: " << stat.NumAltStreams << endl;
so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
*so << "Alternate Streams: " << stat.NumAltStreams << endl;
*so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
}
so
*so
<< "Size: " << stat.UnpackSize << endl
<< "Compressed: " << stat.PackSize << endl;
if (hashCalc)
{
so << endl;
PrintHashStat(so, hb);
*so << endl;
PrintHashStat(*so, hb);
}
}
}
@@ -1047,9 +1083,14 @@ int Main2(
callback.ClosePercents2();
retCode = WarningsCheck(hresultMain, callback, errorInfo, so,
// options.EnableHeaders
true);
CStdOutStream *se = g_StdStream;
if (!se)
se = g_ErrStream;
retCode = WarningsCheck(hresultMain, callback, errorInfo,
g_StdStream, se,
true // options.EnableHeaders
);
}
else if (options.Command.CommandType == NCommandType::kHash)
{
@@ -1068,7 +1109,10 @@ int Main2(
errorInfoString, &callback);
CUpdateErrorInfo errorInfo;
errorInfo.Message = errorInfoString;
retCode = WarningsCheck(hresultMain, callback, errorInfo, so, options.EnableHeaders);
CStdOutStream *se = g_StdStream;
if (!se)
se = g_ErrStream;
retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders);
}
else
ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);

View File

@@ -3,6 +3,10 @@
#ifndef __CONTEXT_MENU_H
#define __CONTEXT_MENU_H
#include "../../../Common/MyWindows.h"
#include <ShlObj.h>
#include "../../../Common/MyString.h"
#include "../FileManager/MyCom2.h"

View File

@@ -8,11 +8,13 @@
#include "StdAfx.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/MyWindows.h"
#include <ShlGuid.h>
#include <OleCtl.h>
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/StringConvert.h"

View File

@@ -3,6 +3,8 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/StringConvert.h"
@@ -96,6 +98,7 @@ EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)
class COpenArchiveCallback:
public IArchiveOpenCallback,
public IArchiveOpenVolumeCallback,
public IArchiveOpenSetSubArchiveName,
public IProgress,
public ICryptoGetTextPassword,
public CMyUnknownImp
@@ -109,6 +112,8 @@ class COpenArchiveCallback:
bool _numBytesTotalDefined;
NFind::CFileInfo _fileInfo;
bool _subArchiveMode;
UString _subArchiveName;
public:
bool PasswordIsDefined;
UString Password;
@@ -116,8 +121,9 @@ public:
FString _folderPrefix;
public:
MY_UNKNOWN_IMP3(
MY_UNKNOWN_IMP4(
IArchiveOpenVolumeCallback,
IArchiveOpenSetSubArchiveName,
IProgress,
ICryptoGetTextPassword
)
@@ -134,13 +140,24 @@ public:
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
STDMETHOD(SetSubArchiveName(const wchar_t *name))
{
_subArchiveMode = true;
_subArchiveName = name;
return S_OK;
}
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
COpenArchiveCallback(): _subArchiveMode(false) {}
void Init()
{
PasswordIsDefined = false;
_subArchiveMode = false;
_numFilesTotalDefined = false;
_numBytesTotalDefined = false;
@@ -220,6 +237,8 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
{
if (WasEscPressed())
return E_ABORT;
if (_subArchiveMode)
return S_FALSE;
*inStream = NULL;
FString fullPath = _folderPrefix + us2fs(name);
if (!_fileInfo.Find(fullPath))
@@ -238,6 +257,14 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
if (_subArchiveMode)
{
switch(propID)
{
case kpidName: prop = _subArchiveName; break;
}
}
else
switch(propID)
{
case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break;

View File

@@ -7,7 +7,7 @@
namespace NMessageID {
const UINT k_Last_PropId_supported_by_plugin = kpidStreamId;
const unsigned k_Last_PropId_supported_by_plugin = kpidStreamId;
enum EEnum
{

View File

@@ -2,6 +2,10 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include <commctrl.h>
#ifndef UNDER_CE
#include "../../../Windows/CommonDialog.h"
#include "../../../Windows/Shell.h"
@@ -106,7 +110,7 @@ class CBrowseDialog: public NControl::CModalDialog
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
virtual void OnOK();
void Post_RefreshPathEdit() { PostMessage(k_Message_RefreshPathEdit); }
void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); }
bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);
// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
@@ -295,7 +299,7 @@ bool CBrowseDialog::OnInit()
#ifndef UNDER_CE
/* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,
even if we use mouse for pressing the button to open this dialog. */
PostMessage(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
PostMsg(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
#endif
return CModalDialog::OnInit();

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../Agent/Agent.h"

View File

@@ -2,6 +2,10 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include <shlwapi.h>
#include "../../../../C/Alloc.h"
#include "../../../Common/IntToString.h"

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include <Winbase.h>
#include "../../../Common/Defs.h"
@@ -585,7 +587,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
CCopyState state;
state.ProgressInfo.TotalSize = stat.Size;
state.ProgressInfo.TotalSize = stat.Size;
state.ProgressInfo.StartPos = 0;
state.ProgressInfo.Progress = callback;
state.ProgressInfo.Init();
@@ -593,7 +594,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
state.MoveMode = IntToBool(moveMode);
state.UseReadWriteMode = isAltDest;
state.Prepare();
state.TotalSize = stat.Size;
for (UInt32 i = 0; i < numItems; i++)
{

View File

@@ -42,7 +42,7 @@ static const UInt32 kLangIDs[] =
static bool GetSymLink(CFSTR path, CReparseAttr &attr)
{
NFile::NIO::CInFile file;
NIO::CInFile file;
if (!file.Open(path,
FILE_SHARE_READ,
OPEN_EXISTING,
@@ -88,12 +88,13 @@ bool CLinkDialog::OnInit()
LangSetWindowText(*this, IDD_LINK);
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
#endif
_pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
_pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
if (!FilePath.IsEmpty())
{
NFile::NFind::CFileInfo fi;
NFind::CFileInfo fi;
int linkType = 0;
if (!fi.Find(us2fs(FilePath)))
linkType = IDR_LINK_TYPE_SYM_FILE;
@@ -219,7 +220,7 @@ void CLinkDialog::OnButton_SetPath(bool to)
UString resultPath;
if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
return;
NFile::NName::NormalizeDirPathPrefix(resultPath);
NName::NormalizeDirPathPrefix(resultPath);
combo.SetCurSel(-1);
combo.SetText(resultPath);
}
@@ -239,16 +240,23 @@ void CLinkDialog::OnButton_Link()
UString from, to;
_pathFromCombo.GetText(from);
_pathToCombo.GetText(to);
int i;
for (i = 0; i < ARRAY_SIZE(k_LinkType_Buttons); i++)
if (IsButtonCheckedBool(k_LinkType_Buttons[i]))
break;
if (from.IsEmpty())
return;
if (!NName::IsAbsolutePath(from))
from.Insert(0, CurDirPrefix);
int idb = -1;
for (unsigned i = 0;; i++)
{
if (i >= ARRAY_SIZE(k_LinkType_Buttons))
return;
idb = k_LinkType_Buttons[i];
if (IsButtonCheckedBool(idb))
break;
}
int idb = k_LinkType_Buttons[i];
NFile::NFind::CFileInfo info1, info2;
NFind::CFileInfo info1, info2;
bool finded1 = info1.Find(us2fs(from));
bool finded2 = info2.Find(us2fs(to));
@@ -259,14 +267,13 @@ void CLinkDialog::OnButton_Link()
if (finded1 && info1.IsDir() != isDirLink ||
finded2 && info2.IsDir() != isDirLink)
{
ShowError(L"Incorrect linkType");
ShowError(L"Incorrect link type");
return;
}
if (idb == IDR_LINK_TYPE_HARD)
{
bool res = NFile::NDir::MyCreateHardLink(us2fs(from), us2fs(to));
if (!res)
if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to)))
{
ShowLastErrorMessage();
return;
@@ -291,9 +298,10 @@ void CLinkDialog::OnButton_Link()
}
if (!NFile::NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
{
ShowLastErrorMessage();
return;
}
}
@@ -321,7 +329,8 @@ void CApp::Link()
int index = indices[0];
const UString itemName = srcPanel.GetItemName(index);
UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
const UString fsPrefix = srcPanel.GetFsPath();
const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
UString path = srcPath;
{
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
@@ -332,6 +341,7 @@ void CApp::Link()
}
CLinkDialog dlg;
dlg.CurDirPrefix = fsPrefix;
dlg.FilePath = srcPath + itemName;
dlg.AnotherPath = path;

View File

@@ -23,6 +23,7 @@ class CLinkDialog: public NWindows::NControl::CModalDialog
void ShowError(const wchar_t *s);
void Set_LinkType_Radio(int idb);
public:
UString CurDirPrefix;
UString FilePath;
UString AnotherPath;

View File

@@ -795,7 +795,7 @@ void CPanel::Change_ShowNtfsStrems_Mode()
void CPanel::Post_Refresh_StatusBar()
{
if (_processStatusBar)
PostMessage(kRefresh_StatusBar);
PostMsg(kRefresh_StatusBar);
}
void CPanel::AddToArchive()

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