mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-18 14:11:54 -06:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cba375916f |
16
C/7zDec.c
16
C/7zDec.c
@@ -1,5 +1,5 @@
|
|||||||
/* 7zDec.c -- Decoding from 7z folder
|
/* 7zDec.c -- Decoding from 7z folder
|
||||||
2015-06-13 : Igor Pavlov : Public domain */
|
2015-08-01 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Precomp.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
@@ -144,11 +144,11 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte *inBuf = NULL;
|
const void *inBuf = NULL;
|
||||||
size_t lookahead = (1 << 18);
|
size_t lookahead = (1 << 18);
|
||||||
if (lookahead > inSize)
|
if (lookahead > inSize)
|
||||||
lookahead = (size_t)inSize;
|
lookahead = (size_t)inSize;
|
||||||
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
res = inStream->Look(inStream, &inBuf, &lookahead);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -197,11 +197,11 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte *inBuf = NULL;
|
const void *inBuf = NULL;
|
||||||
size_t lookahead = (1 << 18);
|
size_t lookahead = (1 << 18);
|
||||||
if (lookahead > inSize)
|
if (lookahead > inSize)
|
||||||
lookahead = (size_t)inSize;
|
lookahead = (size_t)inSize;
|
||||||
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
res = inStream->Look(inStream, &inBuf, &lookahead);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -237,11 +237,11 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
|
|||||||
{
|
{
|
||||||
while (inSize > 0)
|
while (inSize > 0)
|
||||||
{
|
{
|
||||||
void *inBuf;
|
const void *inBuf;
|
||||||
size_t curSize = (1 << 18);
|
size_t curSize = (1 << 18);
|
||||||
if (curSize > inSize)
|
if (curSize > inSize)
|
||||||
curSize = (size_t)inSize;
|
curSize = (size_t)inSize;
|
||||||
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
|
RINOK(inStream->Look(inStream, &inBuf, &curSize));
|
||||||
if (curSize == 0)
|
if (curSize == 0)
|
||||||
return SZ_ERROR_INPUT_EOF;
|
return SZ_ERROR_INPUT_EOF;
|
||||||
memcpy(outBuffer, inBuf, curSize);
|
memcpy(outBuffer, inBuf, curSize);
|
||||||
@@ -429,7 +429,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
|
|||||||
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
else if (coder->MethodID == k_BCJ2)
|
else if (coder->MethodID == k_BCJ2)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#define MY_VER_MAJOR 15
|
#define MY_VER_MAJOR 15
|
||||||
#define MY_VER_MINOR 05
|
#define MY_VER_MINOR 06
|
||||||
#define MY_VER_BUILD 00
|
#define MY_VER_BUILD 00
|
||||||
#define MY_VERSION "15.05 beta"
|
#define MY_VERSION_NUMBERS "15.06"
|
||||||
#define MY_DATE "2015-06-14"
|
#define MY_VERSION "15.06 beta"
|
||||||
|
#define MY_DATE "2015-08-09"
|
||||||
#undef MY_COPYRIGHT
|
#undef MY_COPYRIGHT
|
||||||
#undef MY_VERSION_COPYRIGHT_DATE
|
#undef MY_VERSION_COPYRIGHT_DATE
|
||||||
|
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"
|
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"
|
||||||
|
|
||||||
|
|||||||
6
C/Bcj2.c
6
C/Bcj2.c
@@ -1,5 +1,5 @@
|
|||||||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
/* 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"
|
#include "Precomp.h"
|
||||||
|
|
||||||
@@ -178,8 +178,8 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
|||||||
p->state =
|
p->state =
|
||||||
p->bufs[BCJ2_STREAM_MAIN] ==
|
p->bufs[BCJ2_STREAM_MAIN] ==
|
||||||
p->lims[BCJ2_STREAM_MAIN] ?
|
p->lims[BCJ2_STREAM_MAIN] ?
|
||||||
BCJ2_STREAM_MAIN :
|
(unsigned)BCJ2_STREAM_MAIN :
|
||||||
BCJ2_DEC_STATE_ORIG;
|
(unsigned)BCJ2_DEC_STATE_ORIG;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
C/Blake2.h
Normal file
48
C/Blake2.h
Normal 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
244
C/Blake2s.c
Normal 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);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Compiler.h
|
/* Compiler.h
|
||||||
2015-03-25 : Igor Pavlov : Public domain */
|
2015-08-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_COMPILER_H
|
#ifndef __7Z_COMPILER_H
|
||||||
#define __7Z_COMPILER_H
|
#define __7Z_COMPILER_H
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#else
|
#else
|
||||||
#pragma warning(disable : 4511) // copy constructor could not be generated
|
#pragma warning(disable : 4511) // copy constructor could not be generated
|
||||||
#pragma warning(disable : 4512) // assignment operator 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 : 4702) // unreachable code
|
||||||
#pragma warning(disable : 4710) // not inlined
|
#pragma warning(disable : 4710) // not inlined
|
||||||
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* CpuArch.h -- CPU specific code
|
/* CpuArch.h -- CPU specific code
|
||||||
2015-03-25: Igor Pavlov : Public domain */
|
2015-08-02: Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __CPU_ARCH_H
|
#ifndef __CPU_ARCH_H
|
||||||
#define __CPU_ARCH_H
|
#define __CPU_ARCH_H
|
||||||
@@ -90,9 +90,10 @@ Stop_Compiling_Bad_Endian
|
|||||||
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||||
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||||
#define GetUi64(p) (*(const UInt64 *)(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 SetUi16(p, v) { *(UInt16 *)(p) = (v); }
|
||||||
#define SetUi64(p, v) *(UInt64 *)(p) = (v);
|
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
|
||||||
|
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|||||||
11
C/LzmaDec.c
11
C/LzmaDec.c
@@ -1,5 +1,5 @@
|
|||||||
/* LzmaDec.c -- LZMA Decoder
|
/* LzmaDec.c -- LZMA Decoder
|
||||||
2015-05-14 : Igor Pavlov : Public domain */
|
2015-06-23 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Precomp.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
@@ -438,10 +438,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||||||
if (checkDicSize == 0)
|
if (checkDicSize == 0)
|
||||||
{
|
{
|
||||||
if (distance >= processedPos)
|
if (distance >= processedPos)
|
||||||
|
{
|
||||||
|
p->dicPos = dicPos;
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (distance >= checkDicSize)
|
else if (distance >= checkDicSize)
|
||||||
|
{
|
||||||
|
p->dicPos = dicPos;
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
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;
|
SizeT pos;
|
||||||
|
|
||||||
if ((rem = limit - dicPos) == 0)
|
if ((rem = limit - dicPos) == 0)
|
||||||
|
{
|
||||||
|
p->dicPos = dicPos;
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
curLen = ((rem < len) ? (unsigned)rem : len);
|
curLen = ((rem < len) ? (unsigned)rem : len);
|
||||||
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
|
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* 7zMain.c - Test application for 7z Decoder
|
/* 7zMain.c - Test application for 7z Decoder
|
||||||
2015-05-11 : Igor Pavlov : Public domain */
|
2015-08-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Precomp.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
@@ -328,22 +328,20 @@ void PrintError(char *sz)
|
|||||||
printf("\nERROR: %s\n", sz);
|
printf("\nERROR: %s\n", sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FILE
|
|
||||||
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
|
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');
|
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');
|
||||||
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');
|
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');
|
||||||
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.');
|
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.');
|
||||||
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.');
|
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.');
|
||||||
s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.');
|
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
|
// #define NUM_PARENTS_MAX 128
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
PROG = 7zDec
|
PROG = 7zDec
|
||||||
CXX = g++
|
CXX = gcc
|
||||||
LIB =
|
LIB =
|
||||||
RM = rm -f
|
RM = rm -f
|
||||||
CFLAGS = -c -O2 -Wall
|
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)
|
all: $(PROG)
|
||||||
|
|
||||||
@@ -38,6 +38,9 @@ $(PROG): $(OBJS)
|
|||||||
CpuArch.o: ../../CpuArch.c
|
CpuArch.o: ../../CpuArch.c
|
||||||
$(CXX) $(CFLAGS) ../../CpuArch.c
|
$(CXX) $(CFLAGS) ../../CpuArch.c
|
||||||
|
|
||||||
|
Delta.o: ../../Delta.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Delta.c
|
||||||
|
|
||||||
LzmaDec.o: ../../LzmaDec.c
|
LzmaDec.o: ../../LzmaDec.c
|
||||||
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
||||||
|
|
||||||
@@ -50,6 +53,9 @@ Bra.o: ../../Bra.c
|
|||||||
Bra86.o: ../../Bra86.c
|
Bra86.o: ../../Bra86.c
|
||||||
$(CXX) $(CFLAGS) ../../Bra86.c
|
$(CXX) $(CFLAGS) ../../Bra86.c
|
||||||
|
|
||||||
|
BraIA64.o: ../../BraIA64.c
|
||||||
|
$(CXX) $(CFLAGS) ../../BraIA64.c
|
||||||
|
|
||||||
Bcj2.o: ../../Bcj2.c
|
Bcj2.o: ../../Bcj2.c
|
||||||
$(CXX) $(CFLAGS) ../../Bcj2.c
|
$(CXX) $(CFLAGS) ../../Bcj2.c
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* 7zipInnstall.c - 7-Zip Installer
|
/* 7zipInstall.c - 7-Zip Installer
|
||||||
2015-06-13 : Igor Pavlov : Public domain */
|
2015-08-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Precomp.h"
|
#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)
|
#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
|
||||||
|
|
||||||
#ifdef _64BIT_INSTALLER
|
#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
|
#else
|
||||||
#define k_7zip_with_Ver k_7zip_with_Ver_base
|
#define k_7zip_with_Ver k_7zip_with_Ver_base
|
||||||
#endif
|
#endif
|
||||||
@@ -84,6 +84,8 @@ static HWND g_Path_HWND;
|
|||||||
static HWND g_InfoLine_HWND;
|
static HWND g_InfoLine_HWND;
|
||||||
static HWND g_Progress_HWND;
|
static HWND g_Progress_HWND;
|
||||||
|
|
||||||
|
static DWORD g_TotalSize;
|
||||||
|
|
||||||
static WCHAR path[MAX_PATH * 2 + 40];
|
static WCHAR path[MAX_PATH * 2 + 40];
|
||||||
|
|
||||||
|
|
||||||
@@ -143,7 +145,7 @@ static WRes CreateComplexDir()
|
|||||||
|
|
||||||
if (IS_DRIVE_PATH(s))
|
if (IS_DRIVE_PATH(s))
|
||||||
prefixSize = 3;
|
prefixSize = 3;
|
||||||
else if (IS_SEPAR(s[1]) && IS_SEPAR(s[1]))
|
else if (IS_SEPAR(s[0]) && IS_SEPAR(s[1]))
|
||||||
prefixSize = 2;
|
prefixSize = 2;
|
||||||
else
|
else
|
||||||
return ERROR_INVALID_NAME;
|
return ERROR_INVALID_NAME;
|
||||||
@@ -796,16 +798,30 @@ static void WriteShellEx()
|
|||||||
// wcscpy(destPath, path);
|
// wcscpy(destPath, path);
|
||||||
// wcscat(destPath, L"7zFM.exe");
|
// wcscat(destPath, L"7zFM.exe");
|
||||||
MyRegistry_SetString(destKey, L"DisplayName", k_7zip_with_Ver_str);
|
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);
|
MyRegistry_SetString(destKey, L"DisplayIcon", destPath);
|
||||||
|
|
||||||
wcscpy(destPath, path);
|
wcscpy(destPath, path);
|
||||||
// MyRegistry_SetString(destKey, L"InstallLocation", destPath);
|
MyRegistry_SetString(destKey, L"InstallLocation", destPath);
|
||||||
wcscat(destPath, L"Uninstall.exe");
|
wcscat(destPath, L"Uninstall.exe");
|
||||||
// wcscat(destPath, L"\"");
|
// wcscat(destPath, L"\"");
|
||||||
MyRegistry_SetString(destKey, L"UninstallString", destPath);
|
MyRegistry_SetString(destKey, L"UninstallString", destPath);
|
||||||
|
|
||||||
MyRegistry_SetDWORD(destKey, L"NoModify", 1);
|
MyRegistry_SetDWORD(destKey, L"NoModify", 1);
|
||||||
MyRegistry_SetDWORD(destKey, L"NoRepair", 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);
|
RegCloseKey(destKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1124,23 @@ if (res == SZ_OK)
|
|||||||
FileInStream_CreateVTable(&archiveStream);
|
FileInStream_CreateVTable(&archiveStream);
|
||||||
LookToRead_CreateVTable(&lookStream, False);
|
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);
|
NormalizePrefix(path);
|
||||||
winRes = CreateComplexDir();
|
winRes = CreateComplexDir();
|
||||||
|
|
||||||
@@ -1131,6 +1164,8 @@ if (res == SZ_OK)
|
|||||||
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call, if(!outBuf) */
|
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call, if(!outBuf) */
|
||||||
Byte *outBuf = NULL; /* it must be NULL before first call for each new archive. */
|
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) */
|
size_t outBufSize = 0; /* it can have any value before first call, if(!outBuf) */
|
||||||
|
|
||||||
|
g_TotalSize = 0;
|
||||||
|
|
||||||
if (!g_SilentMode)
|
if (!g_SilentMode)
|
||||||
{
|
{
|
||||||
@@ -1309,6 +1344,8 @@ if (res == SZ_OK)
|
|||||||
res = SZ_ERROR_FAIL;
|
res = SZ_ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_TotalSize += (DWORD)outSizeProcessed;
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FILE
|
#ifdef USE_WINDOWS_FILE
|
||||||
if (SzBitWithVals_Check(&db.MTime, i))
|
if (SzBitWithVals_Check(&db.MTime, i))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* 7zipUninstall.c - 7-Zip Uninstaller
|
/* 7zipUninstall.c - 7-Zip Uninstaller
|
||||||
2015-06-13 : Igor Pavlov : Public domain */
|
2015-08-09 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Precomp.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
|
#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
|
||||||
|
|
||||||
#ifdef _64BIT_INSTALLER
|
#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
|
#else
|
||||||
#define k_7zip_with_Ver k_7zip_with_Ver_base
|
#define k_7zip_with_Ver k_7zip_with_Ver_base
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -301,6 +301,12 @@ HRESULT CDecoder::Decode(
|
|||||||
{
|
{
|
||||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
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;
|
CCreatedCoder cod;
|
||||||
RINOK(CreateCoder(
|
RINOK(CreateCoder(
|
||||||
EXTERNAL_CODECS_LOC_VARS
|
EXTERNAL_CODECS_LOC_VARS
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public:
|
|||||||
UInt64 _numSolidBytes;
|
UInt64 _numSolidBytes;
|
||||||
bool _numSolidBytesDefined;
|
bool _numSolidBytesDefined;
|
||||||
bool _solidExtension;
|
bool _solidExtension;
|
||||||
|
bool _useTypeSorting;
|
||||||
|
|
||||||
bool _compressHeaders;
|
bool _compressHeaders;
|
||||||
bool _encryptHeadersSpecified;
|
bool _encryptHeadersSpecified;
|
||||||
|
|||||||
@@ -508,14 +508,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
|
|
||||||
if (ui.NewData)
|
if (ui.NewData)
|
||||||
{
|
{
|
||||||
NCOM::CPropVariant prop;
|
ui.Size = 0;
|
||||||
RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
|
if (!ui.IsDir)
|
||||||
if (prop.vt != VT_UI8)
|
{
|
||||||
return E_INVALIDARG;
|
NCOM::CPropVariant prop;
|
||||||
ui.Size = (UInt64)prop.uhVal.QuadPart;
|
RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
|
||||||
if (ui.Size != 0 && ui.IsAnti)
|
if (prop.vt != VT_UI8)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
ui.Size = (UInt64)prop.uhVal.QuadPart;
|
||||||
|
if (ui.Size != 0 && ui.IsAnti)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateItems.Add(ui);
|
updateItems.Add(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,6 +618,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
options.NumSolidFiles = _numSolidFiles;
|
options.NumSolidFiles = _numSolidFiles;
|
||||||
options.NumSolidBytes = _numSolidBytes;
|
options.NumSolidBytes = _numSolidBytes;
|
||||||
options.SolidExtension = _solidExtension;
|
options.SolidExtension = _solidExtension;
|
||||||
|
options.UseTypeSorting = _useTypeSorting;
|
||||||
|
|
||||||
options.RemoveSfxBlock = _removeSfxBlock;
|
options.RemoveSfxBlock = _removeSfxBlock;
|
||||||
// options.VolumeMode = _volumeMode;
|
// options.VolumeMode = _volumeMode;
|
||||||
|
|
||||||
@@ -701,6 +708,7 @@ void COutHandler::InitProps()
|
|||||||
// _volumeMode = false;
|
// _volumeMode = false;
|
||||||
|
|
||||||
InitSolid();
|
InitSolid();
|
||||||
|
_useTypeSorting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT COutHandler::SetSolidFromString(const UString &s)
|
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("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);
|
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
|
||||||
}
|
}
|
||||||
return CMultiMethodProps::SetProperty(name, value);
|
return CMultiMethodProps::SetProperty(name, value);
|
||||||
|
|||||||
@@ -554,11 +554,11 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *g_Exts =
|
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"
|
" zip jar ear war msi"
|
||||||
" 3gp avi mov mpeg mpg mpe wmv"
|
" 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"
|
" 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"
|
" chm hxi hxs"
|
||||||
" gif jpeg jpg jp2 png tiff bmp ico psd psp"
|
" gif jpeg jpg jp2 png tiff bmp ico psd psp"
|
||||||
" awg ps eps cgm dxf svg vrml wmf emf ai md"
|
" 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"
|
" 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"
|
" 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"
|
" f77 f f90 f95"
|
||||||
" asm sql manifest dep "
|
" asm sql manifest dep"
|
||||||
" mak clw csproj vcproj sln dsp dsw "
|
" mak clw csproj vcproj sln dsp dsw"
|
||||||
" class "
|
" class"
|
||||||
" bat cmd"
|
" bat cmd"
|
||||||
" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
|
" 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"
|
" 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"
|
" abw afp cwk lwp wpd wps wpt wrf wri"
|
||||||
" abf afm bdf fon mgf otf pcf pfa snf ttf"
|
" abf afm bdf fon mgf otf pcf pfa snf ttf"
|
||||||
" dbf mdb nsf ntf wdb db fdb gdb"
|
" 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";
|
" pdb pch idb ncb opt";
|
||||||
|
|
||||||
static unsigned GetExtIndex(const char *ext)
|
static unsigned GetExtIndex(const char *ext)
|
||||||
@@ -2251,7 +2251,7 @@ HRESULT Update(
|
|||||||
continue;
|
continue;
|
||||||
CRecordVector<CRefItem> refItems;
|
CRecordVector<CRefItem> refItems;
|
||||||
refItems.ClearAndSetSize(numFiles);
|
refItems.ClearAndSetSize(numFiles);
|
||||||
bool sortByType = (numSolidFiles > 1);
|
bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
|
||||||
for (i = 0; i < numFiles; i++)
|
for (i = 0; i < numFiles; i++)
|
||||||
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
|
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
|
||||||
CSortParam sortParam;
|
CSortParam sortParam;
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ struct CUpdateOptions
|
|||||||
UInt64 NumSolidFiles;
|
UInt64 NumSolidFiles;
|
||||||
UInt64 NumSolidBytes;
|
UInt64 NumSolidBytes;
|
||||||
bool SolidExtension;
|
bool SolidExtension;
|
||||||
|
|
||||||
|
bool UseTypeSorting;
|
||||||
|
|
||||||
bool RemoveSfxBlock;
|
bool RemoveSfxBlock;
|
||||||
bool MultiThreadMixer;
|
bool MultiThreadMixer;
|
||||||
|
|
||||||
@@ -109,6 +112,7 @@ struct CUpdateOptions
|
|||||||
NumSolidFiles((UInt64)(Int64)(-1)),
|
NumSolidFiles((UInt64)(Int64)(-1)),
|
||||||
NumSolidBytes((UInt64)(Int64)(-1)),
|
NumSolidBytes((UInt64)(Int64)(-1)),
|
||||||
SolidExtension(false),
|
SolidExtension(false),
|
||||||
|
UseTypeSorting(true),
|
||||||
RemoveSfxBlock(false),
|
RemoveSfxBlock(false),
|
||||||
MultiThreadMixer(true)
|
MultiThreadMixer(true)
|
||||||
{}
|
{}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
PROG = 7z.dll
|
PROG = 7z.dll
|
||||||
DEF_FILE = ../../Archive/Archive2.def
|
DEF_FILE = ../Archive.def
|
||||||
CFLAGS = $(CFLAGS) \
|
CFLAGS = $(CFLAGS) \
|
||||||
-DEXTERNAL_CODECS \
|
-DEXTERNAL_CODECS \
|
||||||
|
|
||||||
@@ -60,9 +60,11 @@ WIN_OBJS = \
|
|||||||
$O\StreamUtils.obj \
|
$O\StreamUtils.obj \
|
||||||
$O\VirtThread.obj \
|
$O\VirtThread.obj \
|
||||||
|
|
||||||
|
COMPRESS_OBJS = \
|
||||||
|
$O\CopyCoder.obj \
|
||||||
|
|
||||||
AR_COMMON_OBJS = \
|
AR_COMMON_OBJS = \
|
||||||
$O\CoderMixer2.obj \
|
$O\CoderMixer2.obj \
|
||||||
$O\CoderMixer2MT.obj \
|
|
||||||
$O\CrossThreadProgress.obj \
|
$O\CrossThreadProgress.obj \
|
||||||
$O\HandlerOut.obj \
|
$O\HandlerOut.obj \
|
||||||
$O\InStreamWithCRC.obj \
|
$O\InStreamWithCRC.obj \
|
||||||
@@ -76,4 +78,6 @@ C_OBJS = \
|
|||||||
$O\CpuArch.obj \
|
$O\CpuArch.obj \
|
||||||
$O\Threads.obj \
|
$O\Threads.obj \
|
||||||
|
|
||||||
|
!include "../../Crc.mak"
|
||||||
|
|
||||||
!include "../../7zip.mak"
|
!include "../../7zip.mak"
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "../../../Common/MyBuffer.h"
|
#include "../../../Common/MyBuffer.h"
|
||||||
|
|
||||||
#include "../../Common/StreamUtils.h"
|
#include "../../Common/StreamUtils.h"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// FindSignature.h
|
// FindSignature.h
|
||||||
|
|
||||||
#ifndef __FINDSIGNATURE_H
|
#ifndef __FIND_SIGNATURE_H
|
||||||
#define __FINDSIGNATURE_H
|
#define __FIND_SIGNATURE_H
|
||||||
|
|
||||||
#include "../../IStream.h"
|
#include "../../IStream.h"
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "../../Common/MyInitGuid.h"
|
#include "../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
#if defined(_7ZIP_LARGE_PAGES)
|
#if defined(_7ZIP_LARGE_PAGES)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.
|
/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.
|
||||||
The code is much larger in that case. */
|
The code is much larger in that case. */
|
||||||
|
|
||||||
#define NSIS_SCRIPT
|
// #define NSIS_SCRIPT
|
||||||
|
|
||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
namespace NNsis {
|
namespace NNsis {
|
||||||
|
|||||||
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal file
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal 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
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "../Common/ItemNameUtils.h"
|
#include "../Common/ItemNameUtils.h"
|
||||||
#include "../Common/OutStreamWithCRC.h"
|
#include "../Common/OutStreamWithCRC.h"
|
||||||
|
|
||||||
|
#include "RarVol.h"
|
||||||
#include "RarHandler.h"
|
#include "RarHandler.h"
|
||||||
|
|
||||||
using namespace NWindows;
|
using namespace NWindows;
|
||||||
@@ -44,6 +45,8 @@ namespace NRar {
|
|||||||
|
|
||||||
static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE;
|
static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE;
|
||||||
|
|
||||||
|
const unsigned kPasswordLen_MAX = 127;
|
||||||
|
|
||||||
bool CItem::IgnoreItem() const
|
bool CItem::IgnoreItem() const
|
||||||
{
|
{
|
||||||
switch (HostOS)
|
switch (HostOS)
|
||||||
@@ -131,7 +134,7 @@ class CInArchive
|
|||||||
CByteBuffer _comment;
|
CByteBuffer _comment;
|
||||||
CByteBuffer m_FileHeaderData;
|
CByteBuffer m_FileHeaderData;
|
||||||
NHeader::NBlock::CBlock m_BlockHeader;
|
NHeader::NBlock::CBlock m_BlockHeader;
|
||||||
NCrypto::NRar29::CDecoder *m_RarAESSpec;
|
NCrypto::NRar3::CDecoder *m_RarAESSpec;
|
||||||
CMyComPtr<ICompressFilter> m_RarAES;
|
CMyComPtr<ICompressFilter> m_RarAES;
|
||||||
CBuffer<Byte> m_DecryptedData;
|
CBuffer<Byte> m_DecryptedData;
|
||||||
Byte *m_DecryptedDataAligned;
|
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; \
|
_ttt_ .DosTime = Get32(p); p += 4; size -= 4; \
|
||||||
READ_TIME(_mask_, _ttt_); } \
|
READ_TIME(_mask_, _ttt_); } \
|
||||||
|
|
||||||
|
|
||||||
bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
|
bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
|
||||||
{
|
{
|
||||||
const Byte *pStart = p;
|
const Byte *pStart = p;
|
||||||
@@ -500,7 +504,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
|||||||
}
|
}
|
||||||
if (!m_RarAES)
|
if (!m_RarAES)
|
||||||
{
|
{
|
||||||
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
|
m_RarAESSpec = new NCrypto::NRar3::CDecoder;
|
||||||
m_RarAES = m_RarAESSpec;
|
m_RarAES = m_RarAESSpec;
|
||||||
}
|
}
|
||||||
m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
|
m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
|
||||||
@@ -518,7 +522,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
|||||||
unsigned len = 0;
|
unsigned len = 0;
|
||||||
if (password)
|
if (password)
|
||||||
len = MyStringLen(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++)
|
for (unsigned i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
wchar_t c = password[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);
|
((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);
|
const UInt32 kDecryptedBufferSize = (1 << 12);
|
||||||
if (m_DecryptedData.Size() == 0)
|
if (m_DecryptedData.Size() == 0)
|
||||||
@@ -990,121 +997,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
|||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsDigit(wchar_t c)
|
|
||||||
{
|
|
||||||
return c >= L'0' && c <= L'9';
|
|
||||||
}
|
|
||||||
|
|
||||||
class CVolumeName
|
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
areThereNonZeros = false;
|
areThereNonZeros = false;
|
||||||
numZeros = 0;
|
numZeros = 0;
|
||||||
@@ -1136,7 +1030,6 @@ HRESULT CHandler::Open2(IInStream *stream,
|
|||||||
{
|
{
|
||||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
|
|
||||||
|
|
||||||
CVolumeName seqName;
|
CVolumeName seqName;
|
||||||
|
|
||||||
@@ -1145,8 +1038,8 @@ HRESULT CHandler::Open2(IInStream *stream,
|
|||||||
|
|
||||||
if (openCallback)
|
if (openCallback)
|
||||||
{
|
{
|
||||||
openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
|
openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||||
openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInArchive archive;
|
CInArchive archive;
|
||||||
@@ -1363,108 +1256,91 @@ struct CMethodItem
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CFolderInStream:
|
class CVolsInStream:
|
||||||
public ISequentialInStream,
|
public ISequentialInStream,
|
||||||
public CMyUnknownImp
|
public CMyUnknownImp
|
||||||
{
|
{
|
||||||
public:
|
UInt64 _rem;
|
||||||
MY_UNKNOWN_IMP
|
ISequentialInStream *_stream;
|
||||||
|
const CObjectVector<CArc> *_arcs;
|
||||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const CObjectVector<CArc> *_archives;
|
|
||||||
const CObjectVector<CItem> *_items;
|
const CObjectVector<CItem> *_items;
|
||||||
CRefItem _refItem;
|
CRefItem _refItem;
|
||||||
unsigned _curIndex;
|
unsigned _curIndex;
|
||||||
UInt32 _crc;
|
UInt32 _crc;
|
||||||
bool _fileIsOpen;
|
bool _calcCrc;
|
||||||
CMyComPtr<ISequentialInStream> _stream;
|
|
||||||
|
|
||||||
HRESULT OpenStream();
|
|
||||||
HRESULT CloseStream();
|
|
||||||
public:
|
public:
|
||||||
void Init(const CObjectVector<CArc> *archives,
|
MY_UNKNOWN_IMP
|
||||||
const CObjectVector<CItem> *items,
|
|
||||||
const CRefItem &refItem);
|
|
||||||
|
|
||||||
CRecordVector<UInt32> CRCs;
|
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||||
|
|
||||||
|
void Init(const CObjectVector<CArc> *arcs,
|
||||||
|
const CObjectVector<CItem> *items,
|
||||||
|
const CRefItem &refItem)
|
||||||
|
{
|
||||||
|
_arcs = arcs;
|
||||||
|
_items = items;
|
||||||
|
_refItem = refItem;
|
||||||
|
_curIndex = 0;
|
||||||
|
_stream = NULL;
|
||||||
|
CrcIsOK = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CrcIsOK;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const
|
STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||||
{
|
|
||||||
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,
|
|
||||||
const CObjectVector<CItem> *items,
|
|
||||||
const CRefItem &refItem)
|
|
||||||
{
|
|
||||||
_archives = archives;
|
|
||||||
_items = items;
|
|
||||||
_refItem = refItem;
|
|
||||||
_curIndex = 0;
|
|
||||||
CRCs.Clear();
|
|
||||||
_fileIsOpen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT CFolderInStream::OpenStream()
|
|
||||||
{
|
|
||||||
while (_curIndex < _refItem.NumItems)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
if (processedSize)
|
||||||
|
*processedSize = 0;
|
||||||
UInt32 realProcessedSize = 0;
|
UInt32 realProcessedSize = 0;
|
||||||
while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
|
|
||||||
|
while (size != 0)
|
||||||
{
|
{
|
||||||
if (_fileIsOpen)
|
if (!_stream)
|
||||||
{
|
{
|
||||||
UInt32 localProcessedSize;
|
if (_curIndex >= _refItem.NumItems)
|
||||||
RINOK(_stream->Read(
|
break;
|
||||||
((Byte *)data) + realProcessedSize, size, &localProcessedSize));
|
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
|
||||||
_crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize);
|
IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream;
|
||||||
if (localProcessedSize == 0)
|
RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||||
{
|
_stream = s;
|
||||||
RINOK(CloseStream());
|
_calcCrc = (CrcIsOK && item.IsSplitAfter());
|
||||||
continue;
|
_crc = CRC_INIT_VAL;
|
||||||
}
|
_rem = item.PackSize;
|
||||||
realProcessedSize += localProcessedSize;
|
|
||||||
size -= localProcessedSize;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
{
|
||||||
RINOK(OpenStream());
|
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];
|
||||||
|
_curIndex++;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (processedSize != 0)
|
|
||||||
*processedSize = realProcessedSize;
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1526,13 +1402,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
|
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
|
||||||
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
|
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
|
||||||
|
|
||||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
|
NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||||
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
|
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
|
||||||
NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
|
NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL;
|
||||||
CMyComPtr<ICompressFilter> rar29CryptoDecoder;
|
CMyComPtr<ICompressFilter> rar3CryptoDecoder;
|
||||||
|
|
||||||
CFolderInStream *folderInStreamSpec = NULL;
|
CVolsInStream *volsInStreamSpec = NULL;
|
||||||
CMyComPtr<ISequentialInStream> folderInStream;
|
CMyComPtr<ISequentialInStream> volsInStream;
|
||||||
|
|
||||||
CLocalProgress *lps = new CLocalProgress;
|
CLocalProgress *lps = new CLocalProgress;
|
||||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||||
@@ -1602,26 +1478,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
outStreamSpec->Init();
|
outStreamSpec->Init();
|
||||||
realOutStream.Release();
|
realOutStream.Release();
|
||||||
|
|
||||||
/*
|
if (!volsInStream)
|
||||||
for (unsigned partIndex = 0; partIndex < 1; partIndex++)
|
|
||||||
{
|
{
|
||||||
CMyComPtr<ISequentialInStream> inStream;
|
volsInStreamSpec = new CVolsInStream;
|
||||||
|
volsInStream = volsInStreamSpec;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
folderInStreamSpec->Init(&_arcs, &_items, refItem);
|
volsInStreamSpec->Init(&_arcs, &_items, refItem);
|
||||||
|
|
||||||
UInt64 packSize = currentPackSize;
|
UInt64 packSize = currentPackSize;
|
||||||
|
|
||||||
@@ -1632,29 +1495,29 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
|
|
||||||
if (item.IsEncrypted())
|
if (item.IsEncrypted())
|
||||||
{
|
{
|
||||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
// CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||||
|
|
||||||
if (item.UnPackVersion >= 29)
|
if (item.UnPackVersion >= 29)
|
||||||
{
|
{
|
||||||
if (!rar29CryptoDecoder)
|
if (!rar3CryptoDecoder)
|
||||||
{
|
{
|
||||||
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
|
rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder;
|
||||||
rar29CryptoDecoder = rar29CryptoDecoderSpec;
|
rar3CryptoDecoder = rar3CryptoDecoderSpec;
|
||||||
}
|
}
|
||||||
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||||
/*
|
/*
|
||||||
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
|
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
|
||||||
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||||
&cryptoProperties));
|
&cryptoProperties));
|
||||||
*/
|
*/
|
||||||
RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||||
filterStreamSpec->Filter = rar29CryptoDecoder;
|
filterStreamSpec->Filter = rar3CryptoDecoder;
|
||||||
}
|
}
|
||||||
else if (item.UnPackVersion >= 20)
|
else if (item.UnPackVersion >= 20)
|
||||||
{
|
{
|
||||||
if (!rar20CryptoDecoder)
|
if (!rar20CryptoDecoder)
|
||||||
{
|
{
|
||||||
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
|
rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder;
|
||||||
rar20CryptoDecoder = rar20CryptoDecoderSpec;
|
rar20CryptoDecoder = rar20CryptoDecoderSpec;
|
||||||
}
|
}
|
||||||
filterStreamSpec->Filter = rar20CryptoDecoder;
|
filterStreamSpec->Filter = rar20CryptoDecoder;
|
||||||
@@ -1666,49 +1529,66 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
// RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||||
|
|
||||||
if (!getTextPassword)
|
if (!getTextPassword)
|
||||||
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||||
if (getTextPassword)
|
|
||||||
|
if (!getTextPassword)
|
||||||
|
{
|
||||||
|
outStream.Release();
|
||||||
|
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (getTextPassword)
|
||||||
{
|
{
|
||||||
CMyComBSTR password;
|
CMyComBSTR password;
|
||||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||||
|
|
||||||
if (item.UnPackVersion >= 29)
|
if (item.UnPackVersion >= 29)
|
||||||
{
|
{
|
||||||
UString unicodePassword;
|
|
||||||
unsigned len = 0;
|
unsigned len = 0;
|
||||||
if (password)
|
if (password)
|
||||||
len = MyStringLen(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++)
|
for (unsigned i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
wchar_t c = password[i];
|
wchar_t c = password[i];
|
||||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
((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
|
else
|
||||||
{
|
{
|
||||||
AString oemPassword;
|
AString oemPassword;
|
||||||
if (password)
|
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
|
else
|
||||||
{
|
{
|
||||||
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
|
RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
filterStreamSpec->SetInStream(folderInStream);
|
filterStreamSpec->SetInStream(volsInStream);
|
||||||
filterStreamSpec->SetOutStreamSize(NULL);
|
filterStreamSpec->SetOutStreamSize(NULL);
|
||||||
inStream = filterStream;
|
inStream = filterStream;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inStream = folderInStream;
|
inStream = volsInStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMyComPtr<ICompressCoder> commonCoder;
|
CMyComPtr<ICompressCoder> commonCoder;
|
||||||
@@ -1766,7 +1646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
|
Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
|
||||||
if (solidStart)
|
if (solidStart)
|
||||||
{
|
{
|
||||||
isSolid = false;
|
isSolid = 0;
|
||||||
solidStart = false;
|
solidStart = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1786,46 +1666,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
|
|
||||||
if (item.IsEncrypted())
|
if (item.IsEncrypted())
|
||||||
filterStreamSpec->ReleaseInStream();
|
filterStreamSpec->ReleaseInStream();
|
||||||
if (result == S_FALSE)
|
|
||||||
{
|
const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
|
||||||
outStream.Release();
|
int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
|
||||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
|
NExtract::NOperationResult::kOK:
|
||||||
continue;
|
NExtract::NOperationResult::kCRCError;
|
||||||
}
|
outStream.Release();
|
||||||
if (result != S_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
/*
|
if (result != S_OK)
|
||||||
if (refItem.NumItems == 1 &&
|
|
||||||
!item.IsSplitBefore() && !item.IsSplitAfter())
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
|
if (result == S_FALSE)
|
||||||
bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
|
opRes = NExtract::NOperationResult::kDataError;
|
||||||
outStream.Release();
|
else if (result == E_NOTIMPL)
|
||||||
RINOK(extractCallback->SetOperationResult(crcOK ?
|
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||||
NExtract::NOperationResult::kOK:
|
else
|
||||||
NExtract::NOperationResult::kCRCError));
|
return result;
|
||||||
}
|
}
|
||||||
/*
|
RINOK(extractCallback->SetOperationResult(opRes));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RINOK(extractCallback->SetOperationResult(crcOK ?
|
|
||||||
NExtract::NOperationResult::kOK:
|
|
||||||
NExtract::NOperationResult::kCRCError));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|||||||
129
CPP/7zip/Archive/Rar/RarVol.h
Normal file
129
CPP/7zip/Archive/Rar/RarVol.h
Normal 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
|
||||||
@@ -29,11 +29,13 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
|
|||||||
{
|
{
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
RINOK(callback->GetProperty(index, propId, &prop));
|
RINOK(callback->GetProperty(index, propId, &prop));
|
||||||
|
|
||||||
if (prop.vt == VT_BSTR)
|
if (prop.vt == VT_BSTR)
|
||||||
{
|
{
|
||||||
UString s = prop.bstrVal;
|
UString s = prop.bstrVal;
|
||||||
if (convertSlash)
|
if (convertSlash)
|
||||||
s = NItemName::MakeLegalName(s);
|
s = NItemName::MakeLegalName(s);
|
||||||
|
|
||||||
if (codePage == CP_UTF8)
|
if (codePage == CP_UTF8)
|
||||||
{
|
{
|
||||||
ConvertUnicodeToUTF8(s, res);
|
ConvertUnicodeToUTF8(s, res);
|
||||||
@@ -44,9 +46,11 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
|
|||||||
}
|
}
|
||||||
else if (prop.vt != VT_EMPTY)
|
else if (prop.vt != VT_EMPTY)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// sort old files with original order.
|
// sort old files with original order.
|
||||||
|
|
||||||
static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
|
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)
|
if (u2.NewProps)
|
||||||
return -1;
|
return -1;
|
||||||
return MyCompare(u1.IndexInArchive, u2.IndexInArchive);
|
return MyCompare(u1.IndexInArc, u2.IndexInArc);
|
||||||
}
|
}
|
||||||
if (!u2.NewProps)
|
if (!u2.NewProps)
|
||||||
return 1;
|
return 1;
|
||||||
return MyCompare(u1.IndexInClient, u2.IndexInClient);
|
return MyCompare(u1.IndexInClient, u2.IndexInClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||||
IArchiveUpdateCallback *callback)
|
IArchiveUpdateCallback *callback)
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
|
|
||||||
if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream)
|
if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream)
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
CObjectVector<CUpdateItem> updateItems;
|
CObjectVector<CUpdateItem> updateItems;
|
||||||
UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
|
UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
|
||||||
|
|
||||||
for (UInt32 i = 0; i < numItems; i++)
|
for (UInt32 i = 0; i < numItems; i++)
|
||||||
{
|
{
|
||||||
CUpdateItem ui;
|
CUpdateItem ui;
|
||||||
Int32 newData;
|
Int32 newData;
|
||||||
Int32 newProps;
|
Int32 newProps;
|
||||||
UInt32 indexInArchive;
|
UInt32 indexInArc;
|
||||||
|
|
||||||
if (!callback)
|
if (!callback)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
|
|
||||||
|
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc));
|
||||||
|
|
||||||
ui.NewProps = IntToBool(newProps);
|
ui.NewProps = IntToBool(newProps);
|
||||||
ui.NewData = IntToBool(newData);
|
ui.NewData = IntToBool(newData);
|
||||||
ui.IndexInArchive = indexInArchive;
|
ui.IndexInArc = indexInArc;
|
||||||
ui.IndexInClient = i;
|
ui.IndexInClient = i;
|
||||||
|
|
||||||
if (IntToBool(newProps))
|
if (IntToBool(newProps))
|
||||||
@@ -109,6 +119,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
else
|
else
|
||||||
ui.Mode = prop.ulVal;
|
ui.Mode = prop.ulVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
RINOK(callback->GetProperty(i, kpidMTime, &prop));
|
RINOK(callback->GetProperty(i, kpidMTime, &prop));
|
||||||
@@ -119,6 +130,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
else
|
else
|
||||||
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
|
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true));
|
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true));
|
||||||
if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
|
if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
|
||||||
ui.Name += '/';
|
ui.Name += '/';
|
||||||
@@ -139,14 +151,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
updateItems.Add(ui);
|
updateItems.Add(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_thereIsPaxExtendedHeader)
|
if (_thereIsPaxExtendedHeader)
|
||||||
{
|
{
|
||||||
// we restore original order of files, if there is pax header block
|
// we restore original order of files, if there is pax header block
|
||||||
updateItems.Sort(CompareUpdateItems, NULL);
|
updateItems.Sort(CompareUpdateItems, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback);
|
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback);
|
||||||
|
|
||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
if (ui.NewData)
|
if (ui.NewData)
|
||||||
complexity += ui.Size;
|
complexity += ui.Size;
|
||||||
else
|
else
|
||||||
complexity += inputItems[ui.IndexInArchive].GetFullSize();
|
complexity += inputItems[ui.IndexInArc].GetFullSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
RINOK(updateCallback->SetTotal(complexity));
|
RINOK(updateCallback->SetTotal(complexity));
|
||||||
@@ -68,12 +68,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
|
|
||||||
const CUpdateItem &ui = updateItems[i];
|
const CUpdateItem &ui = updateItems[i];
|
||||||
CItem item;
|
CItem item;
|
||||||
|
|
||||||
if (ui.NewProps)
|
if (ui.NewProps)
|
||||||
{
|
{
|
||||||
item.Mode = ui.Mode;
|
item.Mode = ui.Mode;
|
||||||
item.Name = ui.Name;
|
item.Name = ui.Name;
|
||||||
item.User = ui.User;
|
item.User = ui.User;
|
||||||
item.Group = ui.Group;
|
item.Group = ui.Group;
|
||||||
|
|
||||||
if (ui.IsDir)
|
if (ui.IsDir)
|
||||||
{
|
{
|
||||||
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
|
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
|
||||||
@@ -84,6 +86,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
|
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
|
||||||
item.PackSize = ui.Size;
|
item.PackSize = ui.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.MTime = ui.MTime;
|
item.MTime = ui.MTime;
|
||||||
item.DeviceMajorDefined = false;
|
item.DeviceMajorDefined = false;
|
||||||
item.DeviceMinorDefined = false;
|
item.DeviceMinorDefined = false;
|
||||||
@@ -92,7 +95,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8);
|
memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
item = inputItems[ui.IndexInArchive];
|
item = inputItems[ui.IndexInArc];
|
||||||
|
|
||||||
AString symLink;
|
AString symLink;
|
||||||
if (ui.NewData || ui.NewProps)
|
if (ui.NewData || ui.NewProps)
|
||||||
@@ -116,6 +119,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
CMyComPtr<ISequentialInStream> fileInStream;
|
CMyComPtr<ISequentialInStream> fileInStream;
|
||||||
|
|
||||||
bool needWrite = true;
|
bool needWrite = true;
|
||||||
|
|
||||||
if (!symLink.IsEmpty())
|
if (!symLink.IsEmpty())
|
||||||
{
|
{
|
||||||
item.PackSize = 0;
|
item.PackSize = 0;
|
||||||
@@ -124,6 +128,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
|
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
|
||||||
|
|
||||||
if (res == S_FALSE)
|
if (res == S_FALSE)
|
||||||
needWrite = false;
|
needWrite = false;
|
||||||
else
|
else
|
||||||
@@ -141,10 +146,17 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
|
if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
|
||||||
{
|
{
|
||||||
item.PackSize = size2;
|
item.PackSize = size2;
|
||||||
|
item.Size = size2;
|
||||||
item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
|
item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.PackSize = 0;
|
||||||
|
item.Size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
AString hardLink;
|
AString hardLink;
|
||||||
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true));
|
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true));
|
||||||
@@ -183,13 +195,15 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
RINOK(outArchive.FillDataResidual(item.PackSize));
|
RINOK(outArchive.FillDataResidual(item.PackSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
complexity += item.PackSize;
|
complexity += item.PackSize;
|
||||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const CItemEx &existItem = inputItems[ui.IndexInArchive];
|
const CItemEx &existItem = inputItems[ui.IndexInArc];
|
||||||
UInt64 size;
|
UInt64 size;
|
||||||
|
|
||||||
if (ui.NewProps)
|
if (ui.NewProps)
|
||||||
{
|
{
|
||||||
// memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8);
|
// 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));
|
RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
|
||||||
size = existItem.GetFullSize();
|
size = existItem.GetFullSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
streamSpec->Init(size);
|
streamSpec->Init(size);
|
||||||
|
|
||||||
if (opCallback)
|
if (opCallback)
|
||||||
{
|
{
|
||||||
RINOK(opCallback->ReportOperation(
|
RINOK(opCallback->ReportOperation(
|
||||||
NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive,
|
NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,
|
||||||
NUpdateNotifyOp::kReplicate))
|
NUpdateNotifyOp::kReplicate))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +257,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
|||||||
complexity += size;
|
complexity += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lps->InSize = lps->OutSize = complexity;
|
lps->InSize = lps->OutSize = complexity;
|
||||||
RINOK(lps->SetCur());
|
RINOK(lps->SetCur());
|
||||||
return outArchive.WriteFinishHeader();
|
return outArchive.WriteFinishHeader();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#define __TAR_UPDATE_H
|
#define __TAR_UPDATE_H
|
||||||
|
|
||||||
#include "../IArchive.h"
|
#include "../IArchive.h"
|
||||||
|
|
||||||
#include "TarItem.h"
|
#include "TarItem.h"
|
||||||
|
|
||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
@@ -11,10 +12,10 @@ namespace NTar {
|
|||||||
|
|
||||||
struct CUpdateItem
|
struct CUpdateItem
|
||||||
{
|
{
|
||||||
int IndexInArchive;
|
int IndexInArc;
|
||||||
int IndexInClient;
|
int IndexInClient;
|
||||||
Int64 MTime;
|
|
||||||
UInt64 Size;
|
UInt64 Size;
|
||||||
|
Int64 MTime;
|
||||||
UInt32 Mode;
|
UInt32 Mode;
|
||||||
bool NewData;
|
bool NewData;
|
||||||
bool NewProps;
|
bool NewProps;
|
||||||
@@ -22,6 +23,8 @@ struct CUpdateItem
|
|||||||
AString Name;
|
AString Name;
|
||||||
AString User;
|
AString User;
|
||||||
AString Group;
|
AString Group;
|
||||||
|
|
||||||
|
CUpdateItem(): Size(0), IsDir(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||||
|
|||||||
@@ -358,15 +358,24 @@ HRESULT CHandler::Open2(IInStream *stream)
|
|||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
UInt64 totalPackSize = 0;
|
UInt64 totalPackSize = 0;
|
||||||
|
unsigned numMainFiles = 0;
|
||||||
|
|
||||||
FOR_VECTOR(i, _files)
|
FOR_VECTOR(i, _files)
|
||||||
{
|
{
|
||||||
const CFile &file = _files[i];
|
const CFile &file = _files[i];
|
||||||
file.UpdateTotalPackSize(totalPackSize);
|
file.UpdateTotalPackSize(totalPackSize);
|
||||||
if (file.Name == "Payload")
|
if (file.Name == "Payload")
|
||||||
|
{
|
||||||
_mainSubfile = i;
|
_mainSubfile = i;
|
||||||
|
numMainFiles++;
|
||||||
|
}
|
||||||
if (file.Name == "PackageInfo")
|
if (file.Name == "PackageInfo")
|
||||||
_is_pkg = true;
|
_is_pkg = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (numMainFiles > 1)
|
||||||
|
_mainSubfile = -1;
|
||||||
|
|
||||||
_phySize = _dataStartPos + totalPackSize;
|
_phySize = _dataStartPos + totalPackSize;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
}
|
}
|
||||||
if (IntToBool(newData))
|
if (IntToBool(newData))
|
||||||
{
|
{
|
||||||
UInt64 size;
|
UInt64 size = 0;
|
||||||
|
if (!ui.IsDir)
|
||||||
{
|
{
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
RINOK(callback->GetProperty(i, kpidSize, &prop));
|
RINOK(callback->GetProperty(i, kpidSize, &prop));
|
||||||
@@ -219,6 +220,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
largestSizeDefined = true;
|
largestSizeDefined = true;
|
||||||
}
|
}
|
||||||
ui.Size = size;
|
ui.Size = size;
|
||||||
|
|
||||||
// ui.Size -= ui.Size / 2;
|
// ui.Size -= ui.Size / 2;
|
||||||
}
|
}
|
||||||
updateItems.Add(ui);
|
updateItems.Add(ui);
|
||||||
|
|||||||
@@ -591,6 +591,29 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2)
|
|||||||
return ((i1.Flags & mask) == (i2.Flags & mask));
|
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)
|
static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
|
||||||
{
|
{
|
||||||
if (!FlagsAreSame(cdItem, localItem))
|
if (!FlagsAreSame(cdItem, localItem))
|
||||||
@@ -611,7 +634,30 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
|
|||||||
return false;
|
return false;
|
||||||
*/
|
*/
|
||||||
if (cdItem.Name != localItem.Name)
|
if (cdItem.Name != localItem.Name)
|
||||||
return false;
|
{
|
||||||
|
// #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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ static void SetFileHeader(
|
|||||||
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
|
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
|
||||||
item.Method = kMethodForDirectory;
|
item.Method = kMethodForDirectory;
|
||||||
item.PackSize = 0;
|
item.PackSize = 0;
|
||||||
item.Crc = 0; // test it
|
item.Size = 0;
|
||||||
|
item.Crc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -332,14 +332,6 @@ SOURCE=..\..\Archive\7z\7zUpdate.h
|
|||||||
# PROP Default_Filter ""
|
# PROP Default_Filter ""
|
||||||
# Begin Source File
|
# 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
|
SOURCE=..\..\Archive\Common\CoderMixer2.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ NSIS_OBJS = \
|
|||||||
|
|
||||||
RAR_OBJS = \
|
RAR_OBJS = \
|
||||||
$O\RarHandler.obj \
|
$O\RarHandler.obj \
|
||||||
|
$O\Rar5Handler.obj \
|
||||||
|
|
||||||
TAR_OBJS = \
|
TAR_OBJS = \
|
||||||
$O\TarHandler.obj \
|
$O\TarHandler.obj \
|
||||||
@@ -212,6 +213,7 @@ COMPRESS_OBJS = \
|
|||||||
$O\Rar2Decoder.obj \
|
$O\Rar2Decoder.obj \
|
||||||
$O\Rar3Decoder.obj \
|
$O\Rar3Decoder.obj \
|
||||||
$O\Rar3Vm.obj \
|
$O\Rar3Vm.obj \
|
||||||
|
$O\Rar5Decoder.obj \
|
||||||
$O\RarCodecsRegister.obj \
|
$O\RarCodecsRegister.obj \
|
||||||
$O\ShrinkDecoder.obj \
|
$O\ShrinkDecoder.obj \
|
||||||
$O\ZlibDecoder.obj \
|
$O\ZlibDecoder.obj \
|
||||||
@@ -222,11 +224,13 @@ CRYPTO_OBJS = \
|
|||||||
$O\7zAes.obj \
|
$O\7zAes.obj \
|
||||||
$O\7zAesRegister.obj \
|
$O\7zAesRegister.obj \
|
||||||
$O\HmacSha1.obj \
|
$O\HmacSha1.obj \
|
||||||
|
$O\HmacSha256.obj \
|
||||||
$O\MyAes.obj \
|
$O\MyAes.obj \
|
||||||
$O\MyAesReg.obj \
|
$O\MyAesReg.obj \
|
||||||
$O\Pbkdf2HmacSha1.obj \
|
$O\Pbkdf2HmacSha1.obj \
|
||||||
$O\RandGen.obj \
|
$O\RandGen.obj \
|
||||||
$O\Rar20Crypto.obj \
|
$O\Rar20Crypto.obj \
|
||||||
|
$O\Rar5Aes.obj \
|
||||||
$O\RarAes.obj \
|
$O\RarAes.obj \
|
||||||
$O\WzAes.obj \
|
$O\WzAes.obj \
|
||||||
$O\ZipCrypto.obj \
|
$O\ZipCrypto.obj \
|
||||||
@@ -239,6 +243,7 @@ C_OBJS = \
|
|||||||
$O\Alloc.obj \
|
$O\Alloc.obj \
|
||||||
$O\Bcj2.obj \
|
$O\Bcj2.obj \
|
||||||
$O\Bcj2Enc.obj \
|
$O\Bcj2Enc.obj \
|
||||||
|
$O\Blake2s.obj \
|
||||||
$O\Bra.obj \
|
$O\Bra.obj \
|
||||||
$O\Bra86.obj \
|
$O\Bra86.obj \
|
||||||
$O\BraIA64.obj \
|
$O\BraIA64.obj \
|
||||||
|
|||||||
@@ -243,6 +243,10 @@ SOURCE=..\..\..\Common\CrcReg.cpp
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\Common\Defs.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\Common\DynamicBuffer.h
|
SOURCE=..\..\..\Common\DynamicBuffer.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -452,6 +456,24 @@ SOURCE=..\..\Compress\Rar3Vm.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=..\..\Compress\RarCodecsRegister.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
@@ -821,6 +843,14 @@ SOURCE=..\..\Crypto\HmacSha1.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=..\..\Crypto\MyAes.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -887,6 +917,14 @@ SOURCE=..\..\Crypto\Rar20Crypto.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=..\..\Crypto\RarAes.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -1319,6 +1357,26 @@ SOURCE=..\..\..\..\C\Bcj2Enc.c
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=..\..\..\..\C\Bra.c
|
||||||
|
|
||||||
!IF "$(CFG)" == "7z - Win32 Release"
|
!IF "$(CFG)" == "7z - Win32 Release"
|
||||||
@@ -1874,6 +1932,14 @@ SOURCE=..\..\Archive\7z\7zUpdateItem.h
|
|||||||
# PROP Default_Filter ""
|
# PROP Default_Filter ""
|
||||||
# Begin Source File
|
# 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
|
SOURCE=..\..\Archive\Rar\RarHandler.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -1888,6 +1954,10 @@ SOURCE=..\..\Archive\Rar\RarHeader.h
|
|||||||
|
|
||||||
SOURCE=..\..\Archive\Rar\RarItem.h
|
SOURCE=..\..\Archive\Rar\RarItem.h
|
||||||
# End Source File
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Rar\RarVol.h
|
||||||
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "Cab"
|
# Begin Group "Cab"
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#define MY_SET_BINARY_MODE(file)
|
#define MY_SET_BINARY_MODE(file)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// #include "../../../Common/MyWindows.h"
|
#include "../../../Common/MyWindows.h"
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
#include "../../../../C/7zVersion.h"
|
#include "../../../../C/7zVersion.h"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
#include "../../../Common/CommandLineParser.h"
|
#include "../../../Common/CommandLineParser.h"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
#include "../../../Common/CommandLineParser.h"
|
#include "../../../Common/CommandLineParser.h"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include <Shlwapi.h>
|
#include <Shlwapi.h>
|
||||||
|
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
struct CAlignedMidBuffer
|
struct CAlignedMidBuffer
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
Byte *_buf;
|
Byte *_buf;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "LimitedStreams.h"
|
#include "LimitedStreams.h"
|
||||||
#include "../../Common/Defs.h"
|
#include "../../Common/Defs.h"
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "../PropID.h"
|
#include "../PropID.h"
|
||||||
|
|
||||||
// VARTYPE
|
// VARTYPE
|
||||||
@@ -101,5 +103,6 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
|
|||||||
VT_UI8,
|
VT_UI8,
|
||||||
VT_UI8,
|
VT_UI8,
|
||||||
VT_BOOL,
|
VT_BOOL,
|
||||||
VT_BSTR // kpidOutName
|
VT_BSTR,
|
||||||
|
VT_BSTR
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "UniqBlocks.h"
|
#include "UniqBlocks.h"
|
||||||
|
|
||||||
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
|
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
|
||||||
|
|||||||
@@ -2,3 +2,5 @@ EXPORTS
|
|||||||
CreateObject PRIVATE
|
CreateObject PRIVATE
|
||||||
GetNumberOfMethods PRIVATE
|
GetNumberOfMethods PRIVATE
|
||||||
GetMethodProperty PRIVATE
|
GetMethodProperty PRIVATE
|
||||||
|
CreateDecoder PRIVATE
|
||||||
|
CreateEncoder PRIVATE
|
||||||
|
|||||||
@@ -130,14 +130,14 @@ CCoder::CCoder(bool deflate64Mode):
|
|||||||
m_Values(0),
|
m_Values(0),
|
||||||
m_Tables(0)
|
m_Tables(0)
|
||||||
{
|
{
|
||||||
{
|
|
||||||
CEncProps props;
|
|
||||||
SetProps(&props);
|
|
||||||
}
|
|
||||||
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
|
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
|
||||||
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
|
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
|
||||||
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
|
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
|
||||||
m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
|
m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
|
||||||
|
{
|
||||||
|
CEncProps props;
|
||||||
|
SetProps(&props);
|
||||||
|
}
|
||||||
MatchFinder_Construct(&_lzInWindow);
|
MatchFinder_Construct(&_lzInWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ public:
|
|||||||
|
|
||||||
bool SetCodeLengths(const Byte *lens)
|
bool SetCodeLengths(const Byte *lens)
|
||||||
{
|
{
|
||||||
unsigned lenCounts[kNumBitsMax + 1];
|
UInt32 lenCounts[kNumBitsMax + 1];
|
||||||
UInt32 tmpPositions[kNumBitsMax + 1];
|
UInt32 tmpPositions[kNumBitsMax + 1];
|
||||||
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 1; i <= kNumBitsMax; i++)
|
for (i = 1; i <= kNumBitsMax; i++)
|
||||||
lenCounts[i] = 0;
|
lenCounts[i] = 0;
|
||||||
|
|
||||||
UInt32 symbol;
|
UInt32 symbol;
|
||||||
|
|
||||||
for (symbol = 0; symbol < m_NumSymbols; symbol++)
|
for (symbol = 0; symbol < m_NumSymbols; symbol++)
|
||||||
@@ -42,7 +44,7 @@ public:
|
|||||||
m_Positions[0] = m_Limits[0] = 0;
|
m_Positions[0] = m_Limits[0] = 0;
|
||||||
UInt32 startPos = 0;
|
UInt32 startPos = 0;
|
||||||
UInt32 index = 0;
|
UInt32 index = 0;
|
||||||
const UInt32 kMaxValue = (1 << kNumBitsMax);
|
const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
|
||||||
|
|
||||||
for (i = 1; i <= kNumBitsMax; i++)
|
for (i = 1; i <= kNumBitsMax; i++)
|
||||||
{
|
{
|
||||||
@@ -74,14 +76,15 @@ public:
|
|||||||
UInt32 DecodeSymbol(TBitDecoder *bitStream)
|
UInt32 DecodeSymbol(TBitDecoder *bitStream)
|
||||||
{
|
{
|
||||||
unsigned numBits;
|
unsigned numBits;
|
||||||
UInt32 value = bitStream->GetValue(kNumBitsMax);
|
UInt32 val = bitStream->GetValue(kNumBitsMax);
|
||||||
if (value < m_Limits[kNumTableBits])
|
|
||||||
numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
|
if (val < m_Limits[kNumTableBits])
|
||||||
|
numBits = m_Lengths[val >> (kNumBitsMax - kNumTableBits)];
|
||||||
else
|
else
|
||||||
for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
|
for (numBits = kNumTableBits + 1; val >= m_Limits[numBits]; numBits++);
|
||||||
|
|
||||||
bitStream->MovePos(numBits);
|
bitStream->MovePos(numBits);
|
||||||
UInt32 index = m_Positions[numBits] +
|
UInt32 index = m_Positions[numBits] + ((val - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
|
||||||
((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
|
|
||||||
if (index >= m_NumSymbols)
|
if (index >= m_NumSymbols)
|
||||||
// throw CDecoderException(); // test it
|
// throw CDecoderException(); // test it
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
|||||||
{
|
{
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
m_IsSolid = (data[0] != 0);
|
m_IsSolid = ((data[0] & 1) != 0);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
|||||||
{
|
{
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
m_IsSolid = (data[0] != 0);
|
m_IsSolid = ((data[0] & 1) != 0);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)
|
|||||||
NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
|
NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
|
||||||
NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
|
NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
|
||||||
CFilter *filter = _filters[tempFilter->FilterIndex];
|
CFilter *filter = _filters[tempFilter->FilterIndex];
|
||||||
|
if (!filter->IsSupported)
|
||||||
|
_unsupportedFilter = true;
|
||||||
_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);
|
_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);
|
||||||
delete tempFilter;
|
delete tempFilter;
|
||||||
_tempFilters[tempFilterIndex] = 0;
|
_tempFilters[tempFilterIndex] = 0;
|
||||||
@@ -226,12 +228,15 @@ void CDecoder::InitFilters()
|
|||||||
_filters.Clear();
|
_filters.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const unsigned MAX_UNPACK_FILTERS = 8192;
|
||||||
|
|
||||||
bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
||||||
{
|
{
|
||||||
CMemBitDecoder inp;
|
CMemBitDecoder inp;
|
||||||
inp.Init(_vmData, codeSize);
|
inp.Init(_vmData, codeSize);
|
||||||
|
|
||||||
UInt32 filterIndex;
|
UInt32 filterIndex;
|
||||||
|
|
||||||
if (firstByte & 0x80)
|
if (firstByte & 0x80)
|
||||||
{
|
{
|
||||||
filterIndex = inp.ReadEncodedUInt32();
|
filterIndex = inp.ReadEncodedUInt32();
|
||||||
@@ -242,6 +247,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
filterIndex = _lastFilter;
|
filterIndex = _lastFilter;
|
||||||
|
|
||||||
if (filterIndex > (UInt32)_filters.Size())
|
if (filterIndex > (UInt32)_filters.Size())
|
||||||
return false;
|
return false;
|
||||||
_lastFilter = filterIndex;
|
_lastFilter = filterIndex;
|
||||||
@@ -251,7 +257,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
|||||||
if (newFilter)
|
if (newFilter)
|
||||||
{
|
{
|
||||||
// check if too many filters
|
// check if too many filters
|
||||||
if (filterIndex > 1024)
|
if (filterIndex > MAX_UNPACK_FILTERS)
|
||||||
return false;
|
return false;
|
||||||
filter = new CFilter;
|
filter = new CFilter;
|
||||||
_filters.Add(filter);
|
_filters.Add(filter);
|
||||||
@@ -301,6 +307,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
|||||||
if (initMask & (1 << i))
|
if (initMask & (1 << i))
|
||||||
tempFilter->InitR[i] = inp.ReadEncodedUInt32();
|
tempFilter->InitR[i] = inp.ReadEncodedUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isOK = true;
|
||||||
if (newFilter)
|
if (newFilter)
|
||||||
{
|
{
|
||||||
UInt32 vmCodeSize = inp.ReadEncodedUInt32();
|
UInt32 vmCodeSize = inp.ReadEncodedUInt32();
|
||||||
@@ -308,7 +316,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
|||||||
return false;
|
return false;
|
||||||
for (UInt32 i = 0; i < vmCodeSize; i++)
|
for (UInt32 i = 0; i < vmCodeSize; i++)
|
||||||
_vmCode[i] = (Byte)inp.ReadBits(8);
|
_vmCode[i] = (Byte)inp.ReadBits(8);
|
||||||
filter->PrepareProgram(_vmCode, vmCodeSize);
|
isOK = filter->PrepareProgram(_vmCode, vmCodeSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Byte *globalData = &tempFilter->GlobalData[0];
|
Byte *globalData = &tempFilter->GlobalData[0];
|
||||||
@@ -331,7 +339,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
|||||||
for (UInt32 i = 0; i < dataSize; i++)
|
for (UInt32 i = 0; i < dataSize; i++)
|
||||||
dest[i] = (Byte)inp.ReadBits(8);
|
dest[i] = (Byte)inp.ReadBits(8);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
return isOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDecoder::ReadVmCodeLZ()
|
bool CDecoder::ReadVmCodeLZ()
|
||||||
@@ -796,6 +805,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
|
|||||||
HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
||||||
{
|
{
|
||||||
_writtenFileSize = 0;
|
_writtenFileSize = 0;
|
||||||
|
_unsupportedFilter = false;
|
||||||
if (!m_IsSolid)
|
if (!m_IsSolid)
|
||||||
{
|
{
|
||||||
_lzSize = 0;
|
_lzSize = 0;
|
||||||
@@ -843,6 +853,10 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
|||||||
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
|
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
|
||||||
if (_writtenFileSize < _unpackSize)
|
if (_writtenFileSize < _unpackSize)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
|
if (_unsupportedFilter)
|
||||||
|
return E_NOTIMPL;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -892,7 +906,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
|||||||
{
|
{
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
m_IsSolid = (data[0] != 0);
|
m_IsSolid = ((data[0] & 1) != 0);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ class CDecoder:
|
|||||||
bool m_IsSolid;
|
bool m_IsSolid;
|
||||||
|
|
||||||
bool _lzMode;
|
bool _lzMode;
|
||||||
|
bool _unsupportedFilter;
|
||||||
|
|
||||||
UInt32 PrevAlignBits;
|
UInt32 PrevAlignBits;
|
||||||
UInt32 PrevAlignCount;
|
UInt32 PrevAlignCount;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ Note:
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "../../../C/7zCrc.h"
|
#include "../../../C/7zCrc.h"
|
||||||
#include "../../../C/Alloc.h"
|
#include "../../../C/Alloc.h"
|
||||||
|
|
||||||
@@ -55,6 +57,8 @@ namespace NVm {
|
|||||||
|
|
||||||
static const UInt32 kStackRegIndex = kNumRegs - 1;
|
static const UInt32 kStackRegIndex = kNumRegs - 1;
|
||||||
|
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
|
|
||||||
static const UInt32 FLAG_C = 1;
|
static const UInt32 FLAG_C = 1;
|
||||||
static const UInt32 FLAG_Z = 2;
|
static const UInt32 FLAG_Z = 2;
|
||||||
static const UInt32 FLAG_S = 0x80000000;
|
static const UInt32 FLAG_S = 0x80000000;
|
||||||
@@ -113,11 +117,14 @@ static const Byte kCmdFlags[]=
|
|||||||
/* CMD_PRINT */ CF_OP0
|
/* CMD_PRINT */ CF_OP0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
CVm::CVm(): Mem(NULL) {}
|
CVm::CVm(): Mem(NULL) {}
|
||||||
|
|
||||||
bool CVm::Create()
|
bool CVm::Create()
|
||||||
{
|
{
|
||||||
if (Mem == NULL)
|
if (!Mem)
|
||||||
Mem = (Byte *)::MyAlloc(kSpaceSize + 4);
|
Mem = (Byte *)::MyAlloc(kSpaceSize + 4);
|
||||||
return (Mem != NULL);
|
return (Mem != NULL);
|
||||||
}
|
}
|
||||||
@@ -145,12 +152,14 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
|||||||
memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);
|
memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);
|
||||||
|
|
||||||
bool res = true;
|
bool res = true;
|
||||||
|
|
||||||
#ifdef RARVM_STANDARD_FILTERS
|
#ifdef RARVM_STANDARD_FILTERS
|
||||||
if (prg->StandardFilterIndex >= 0)
|
if (prg->StandardFilterIndex >= 0)
|
||||||
ExecuteStandardFilter(prg->StandardFilterIndex);
|
ExecuteStandardFilter(prg->StandardFilterIndex);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
res = ExecuteCode(prg);
|
res = ExecuteCode(prg);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
@@ -158,7 +167,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
|||||||
prg->Commands.Add(CCommand());
|
prg->Commands.Add(CCommand());
|
||||||
prg->Commands.Back().OpCode = CMD_RET;
|
prg->Commands.Back().OpCode = CMD_RET;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
res = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;
|
UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;
|
||||||
UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;
|
UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;
|
||||||
if (newBlockPos + newBlockSize >= kSpaceSize)
|
if (newBlockPos + newBlockSize >= kSpaceSize)
|
||||||
@@ -175,9 +188,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
|||||||
outGlobalData.ClearAndSetSize(dataSize);
|
outGlobalData.ClearAndSetSize(dataSize);
|
||||||
memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize);
|
memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
|
|
||||||
#define SET_IP(IP) \
|
#define SET_IP(IP) \
|
||||||
if ((IP) >= numCommands) return true; \
|
if ((IP) >= numCommands) return true; \
|
||||||
@@ -191,7 +206,7 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
|||||||
|
|
||||||
UInt32 CVm::GetOperand32(const COperand *op) const
|
UInt32 CVm::GetOperand32(const COperand *op) const
|
||||||
{
|
{
|
||||||
switch(op->Type)
|
switch (op->Type)
|
||||||
{
|
{
|
||||||
case OP_TYPE_REG: return R[op->Data];
|
case OP_TYPE_REG: return R[op->Data];
|
||||||
case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);
|
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)
|
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_REG: R[op->Data] = val; return;
|
||||||
case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], 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
|
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_REG: return (Byte)R[op->Data];
|
||||||
case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];;
|
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)
|
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_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;
|
||||||
case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = 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 (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
switch(cmd->OpCode)
|
switch (cmd->OpCode)
|
||||||
{
|
{
|
||||||
#ifndef RARVM_NO_VM
|
|
||||||
|
|
||||||
case CMD_MOV:
|
case CMD_MOV:
|
||||||
SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));
|
SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));
|
||||||
break;
|
break;
|
||||||
@@ -619,8 +632,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case CMD_RET:
|
case CMD_RET:
|
||||||
{
|
{
|
||||||
if (R[kStackRegIndex] >= kSpaceSize)
|
if (R[kStackRegIndex] >= kSpaceSize)
|
||||||
@@ -638,7 +649,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// Read program
|
// Read program
|
||||||
|
|
||||||
@@ -682,25 +692,31 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
|
|||||||
inp.Init(code, codeSize);
|
inp.Init(code, codeSize);
|
||||||
|
|
||||||
StaticData.Clear();
|
StaticData.Clear();
|
||||||
|
|
||||||
if (inp.ReadBit())
|
if (inp.ReadBit())
|
||||||
{
|
{
|
||||||
UInt32 dataSize = inp.ReadEncodedUInt32() + 1;
|
UInt32 dataSize = inp.ReadEncodedUInt32() + 1;
|
||||||
for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)
|
for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)
|
||||||
StaticData.Add((Byte)inp.ReadBits(8));
|
StaticData.Add((Byte)inp.ReadBits(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (inp.Avail())
|
while (inp.Avail())
|
||||||
{
|
{
|
||||||
Commands.Add(CCommand());
|
Commands.Add(CCommand());
|
||||||
CCommand *cmd = &Commands.Back();
|
CCommand *cmd = &Commands.Back();
|
||||||
|
|
||||||
if (inp.ReadBit() == 0)
|
if (inp.ReadBit() == 0)
|
||||||
cmd->OpCode = (ECommand)inp.ReadBits(3);
|
cmd->OpCode = (ECommand)inp.ReadBits(3);
|
||||||
else
|
else
|
||||||
cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));
|
cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));
|
||||||
|
|
||||||
if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE)
|
if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE)
|
||||||
cmd->ByteMode = (inp.ReadBit()) ? true : false;
|
cmd->ByteMode = (inp.ReadBit()) ? true : false;
|
||||||
else
|
else
|
||||||
cmd->ByteMode = 0;
|
cmd->ByteMode = 0;
|
||||||
|
|
||||||
int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK);
|
int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK);
|
||||||
|
|
||||||
if (opNum > 0)
|
if (opNum > 0)
|
||||||
{
|
{
|
||||||
DecodeArg(inp, cmd->Op1, cmd->ByteMode);
|
DecodeArg(inp, cmd->Op1, cmd->ByteMode);
|
||||||
@@ -727,6 +743,7 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd->ByteMode)
|
if (cmd->ByteMode)
|
||||||
{
|
{
|
||||||
switch (cmd->OpCode)
|
switch (cmd->OpCode)
|
||||||
@@ -751,6 +768,9 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef RARVM_STANDARD_FILTERS
|
#ifdef RARVM_STANDARD_FILTERS
|
||||||
|
|
||||||
enum EStandardFilter
|
enum EStandardFilter
|
||||||
@@ -760,8 +780,8 @@ enum EStandardFilter
|
|||||||
SF_ITANIUM,
|
SF_ITANIUM,
|
||||||
SF_RGB,
|
SF_RGB,
|
||||||
SF_AUDIO,
|
SF_AUDIO,
|
||||||
SF_DELTA,
|
SF_DELTA
|
||||||
SF_UPCASE
|
// SF_UPCASE
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct CStandardFilterSignature
|
static const struct CStandardFilterSignature
|
||||||
@@ -777,8 +797,8 @@ kStdFilters[]=
|
|||||||
{ 120, 0x3769893f, SF_ITANIUM },
|
{ 120, 0x3769893f, SF_ITANIUM },
|
||||||
{ 29, 0x0e06077d, SF_DELTA },
|
{ 29, 0x0e06077d, SF_DELTA },
|
||||||
{ 149, 0x1c2c5dc8, SF_RGB },
|
{ 149, 0x1c2c5dc8, SF_RGB },
|
||||||
{ 216, 0xbc85e701, SF_AUDIO },
|
{ 216, 0xbc85e701, SF_AUDIO }
|
||||||
{ 40, 0x46b9c560, SF_UPCASE }
|
// { 40, 0x46b9c560, SF_UPCASE }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int FindStandardFilter(const Byte *code, UInt32 codeSize)
|
static int FindStandardFilter(const Byte *code, UInt32 codeSize)
|
||||||
@@ -795,28 +815,48 @@ static int FindStandardFilter(const Byte *code, UInt32 codeSize)
|
|||||||
|
|
||||||
#endif
|
#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();
|
Commands.Clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef RARVM_STANDARD_FILTERS
|
#ifdef RARVM_STANDARD_FILTERS
|
||||||
StandardFilterIndex = -1;
|
StandardFilterIndex = -1;
|
||||||
#endif
|
#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
|
#ifdef RARVM_STANDARD_FILTERS
|
||||||
StandardFilterIndex = FindStandardFilter(code, codeSize);
|
StandardFilterIndex = FindStandardFilter(code, codeSize);
|
||||||
if (StandardFilterIndex >= 0)
|
if (StandardFilterIndex >= 0)
|
||||||
return;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
ReadProgram(code + 1, codeSize - 1);
|
ReadProgram(code + 1, codeSize - 1);
|
||||||
|
#else
|
||||||
|
IsSupported = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
Commands.Add(CCommand());
|
Commands.Add(CCommand());
|
||||||
Commands.Back().OpCode = CMD_RET;
|
Commands.Back().OpCode = CMD_RET;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return isOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)
|
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;
|
return;
|
||||||
dataSize -= 4;
|
dataSize -= 4;
|
||||||
const UInt32 kFileSize = 0x1000000;
|
const UInt32 kFileSize = 0x1000000;
|
||||||
Byte cmpByte2 = (Byte)(e9 ? 0xE9 : 0xE8);
|
Byte cmpMask = (Byte)(e9 ? 0xFE : 0xFF);
|
||||||
for (UInt32 curPos = 0; curPos < dataSize;)
|
for (UInt32 curPos = 0; curPos < dataSize;)
|
||||||
{
|
{
|
||||||
Byte curByte = *(data++);
|
|
||||||
curPos++;
|
curPos++;
|
||||||
if (curByte == 0xE8 || curByte == cmpByte2)
|
if (((*data++) & cmpMask) == 0xE8)
|
||||||
{
|
{
|
||||||
UInt32 offset = curPos + fileOffset;
|
UInt32 offset = curPos + fileOffset;
|
||||||
UInt32 addr = (Int32)GetValue32(data);
|
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};
|
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];
|
Byte cmdMask = kCmdMasks[b];
|
||||||
if (cmdMask != 0)
|
if (cmdMask != 0)
|
||||||
for (int i = 0; i < 3; i++)
|
for (unsigned i = 0; i < 3; i++)
|
||||||
if (cmdMask & (1 << i))
|
if (cmdMask & (1 << i))
|
||||||
{
|
{
|
||||||
int startPos = i * 41 + 18;
|
unsigned startPos = i * 41 + 18;
|
||||||
if (ItaniumGetOpType(data, startPos + 24) == 5)
|
if (ItaniumGetOpType(data, startPos + 24) == 5)
|
||||||
{
|
{
|
||||||
const UInt32 kMask = 0xFFFFF;
|
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);
|
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 offset = (bitField >> inBit) & kMask;
|
||||||
UInt32 andMask = ~(kMask << inBit);
|
UInt32 andMask = ~(kMask << inBit);
|
||||||
bitField = ((offset - fileOffset) & 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] &= andMask;
|
||||||
p[j] |= bitField;
|
p[j] |= bitField;
|
||||||
@@ -1016,6 +1055,7 @@ static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
|
static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
|
||||||
{
|
{
|
||||||
UInt32 srcPos = 0, destPos = dataSize;
|
UInt32 srcPos = 0, destPos = dataSize;
|
||||||
@@ -1028,6 +1068,7 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
|
|||||||
}
|
}
|
||||||
return destPos - dataSize;
|
return destPos - dataSize;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
||||||
{
|
{
|
||||||
@@ -1068,6 +1109,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
|||||||
SetBlockPos(dataSize);
|
SetBlockPos(dataSize);
|
||||||
AudioDecode(Mem, dataSize, R[0]);
|
AudioDecode(Mem, dataSize, R[0]);
|
||||||
break;
|
break;
|
||||||
|
/*
|
||||||
case SF_UPCASE:
|
case SF_UPCASE:
|
||||||
if (dataSize >= kGlobalOffset / 2)
|
if (dataSize >= kGlobalOffset / 2)
|
||||||
break;
|
break;
|
||||||
@@ -1075,6 +1117,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
|||||||
SetBlockSize(destSize);
|
SetBlockSize(destSize);
|
||||||
SetBlockPos(dataSize);
|
SetBlockPos(dataSize);
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
#include "../../../C/CpuArch.h"
|
#include "../../../C/CpuArch.h"
|
||||||
|
|
||||||
#include "../../Common/MyTypes.h"
|
|
||||||
#include "../../Common/MyVector.h"
|
#include "../../Common/MyVector.h"
|
||||||
|
|
||||||
#define RARVM_STANDARD_FILTERS
|
#define RARVM_STANDARD_FILTERS
|
||||||
|
// #define RARVM_VM_ENABLE
|
||||||
|
|
||||||
namespace NCompress {
|
namespace NCompress {
|
||||||
namespace NRar3 {
|
namespace NRar3 {
|
||||||
@@ -39,12 +39,12 @@ namespace NVm {
|
|||||||
inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }
|
inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }
|
||||||
inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); }
|
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 kNumRegs = 1 << kNumRegBits;
|
||||||
const UInt32 kNumGpRegs = kNumRegs - 1;
|
const UInt32 kNumGpRegs = kNumRegs - 1;
|
||||||
|
|
||||||
const UInt32 kSpaceSize = 0x40000;
|
const UInt32 kSpaceSize = 0x40000;
|
||||||
const UInt32 kSpaceMask = kSpaceSize -1;
|
const UInt32 kSpaceMask = kSpaceSize - 1;
|
||||||
const UInt32 kGlobalOffset = 0x3C000;
|
const UInt32 kGlobalOffset = 0x3C000;
|
||||||
const UInt32 kGlobalSize = 0x2000;
|
const UInt32 kGlobalSize = 0x2000;
|
||||||
const UInt32 kFixedGlobalSize = 64;
|
const UInt32 kFixedGlobalSize = 64;
|
||||||
@@ -57,6 +57,9 @@ namespace NGlobalOffset
|
|||||||
const UInt32 kGlobalMemOutSize = 0x30;
|
const UInt32 kGlobalMemOutSize = 0x30;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
|
|
||||||
enum ECommand
|
enum ECommand
|
||||||
{
|
{
|
||||||
CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC,
|
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;
|
COperand Op1, Op2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct CBlockRef
|
struct CBlockRef
|
||||||
{
|
{
|
||||||
UInt32 Offset;
|
UInt32 Offset;
|
||||||
UInt32 Size;
|
UInt32 Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CProgram
|
class CProgram
|
||||||
{
|
{
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
|
void ReadProgram(const Byte *code, UInt32 codeSize);
|
||||||
public:
|
public:
|
||||||
CRecordVector<CCommand> Commands;
|
CRecordVector<CCommand> Commands;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
#ifdef RARVM_STANDARD_FILTERS
|
#ifdef RARVM_STANDARD_FILTERS
|
||||||
int StandardFilterIndex;
|
int StandardFilterIndex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool IsSupported;
|
||||||
CRecordVector<Byte> StaticData;
|
CRecordVector<Byte> StaticData;
|
||||||
|
|
||||||
private:
|
bool PrepareProgram(const Byte *code, UInt32 codeSize);
|
||||||
void ReadProgram(const Byte *code, UInt32 codeSize);
|
|
||||||
public:
|
|
||||||
void PrepareProgram(const Byte *code, UInt32 codeSize);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct CProgramInitState
|
struct CProgramInitState
|
||||||
{
|
{
|
||||||
UInt32 InitR[kNumGpRegs];
|
UInt32 InitR[kNumGpRegs];
|
||||||
@@ -122,6 +134,7 @@ struct CProgramInitState
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CVm
|
class CVm
|
||||||
{
|
{
|
||||||
static UInt32 GetValue(bool byteMode, const void *addr)
|
static UInt32 GetValue(bool byteMode, const void *addr)
|
||||||
@@ -146,15 +159,18 @@ class CVm
|
|||||||
void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }
|
void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }
|
||||||
public:
|
public:
|
||||||
static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }
|
static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
#ifdef RARVM_VM_ENABLE
|
||||||
UInt32 GetOperand32(const COperand *op) const;
|
UInt32 GetOperand32(const COperand *op) const;
|
||||||
void SetOperand32(const COperand *op, UInt32 val);
|
void SetOperand32(const COperand *op, UInt32 val);
|
||||||
Byte GetOperand8(const COperand *op) const;
|
Byte GetOperand8(const COperand *op) const;
|
||||||
void SetOperand8(const COperand *op, Byte val);
|
void SetOperand8(const COperand *op, Byte val);
|
||||||
UInt32 GetOperand(bool byteMode, const COperand *op) const;
|
UInt32 GetOperand(bool byteMode, const COperand *op) const;
|
||||||
void SetOperand(bool byteMode, const COperand *op, UInt32 val);
|
void SetOperand(bool byteMode, const COperand *op, UInt32 val);
|
||||||
|
|
||||||
bool ExecuteCode(const CProgram *prg);
|
bool ExecuteCode(const CProgram *prg);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef RARVM_STANDARD_FILTERS
|
#ifdef RARVM_STANDARD_FILTERS
|
||||||
void ExecuteStandardFilter(unsigned filterIndex);
|
void ExecuteStandardFilter(unsigned filterIndex);
|
||||||
@@ -163,6 +179,7 @@ private:
|
|||||||
Byte *Mem;
|
Byte *Mem;
|
||||||
UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)
|
UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)
|
||||||
UInt32 Flags;
|
UInt32 Flags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CVm();
|
CVm();
|
||||||
~CVm();
|
~CVm();
|
||||||
@@ -171,7 +188,6 @@ public:
|
|||||||
bool Execute(CProgram *prg, const CProgramInitState *initState,
|
bool Execute(CProgram *prg, const CProgramInitState *initState,
|
||||||
CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);
|
CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);
|
||||||
const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }
|
const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
960
CPP/7zip/Compress/Rar5Decoder.cpp
Normal file
960
CPP/7zip/Compress/Rar5Decoder.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
335
CPP/7zip/Compress/Rar5Decoder.h
Normal file
335
CPP/7zip/Compress/Rar5Decoder.h
Normal 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
|
||||||
@@ -7,12 +7,14 @@
|
|||||||
#include "Rar1Decoder.h"
|
#include "Rar1Decoder.h"
|
||||||
#include "Rar2Decoder.h"
|
#include "Rar2Decoder.h"
|
||||||
#include "Rar3Decoder.h"
|
#include "Rar3Decoder.h"
|
||||||
|
#include "Rar5Decoder.h"
|
||||||
|
|
||||||
#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder())
|
#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder())
|
||||||
|
|
||||||
CREATE_CODEC(1)
|
CREATE_CODEC(1)
|
||||||
CREATE_CODEC(2)
|
CREATE_CODEC(2)
|
||||||
CREATE_CODEC(3)
|
CREATE_CODEC(3)
|
||||||
|
CREATE_CODEC(5)
|
||||||
|
|
||||||
#define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, "Rar" name, 1, false }
|
#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(1, "1"),
|
||||||
RAR_CODEC(2, "2"),
|
RAR_CODEC(2, "2"),
|
||||||
RAR_CODEC(3, "3"),
|
RAR_CODEC(3, "3"),
|
||||||
|
RAR_CODEC(5, "5"),
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_CODECS(Rar)
|
REGISTER_CODECS(Rar)
|
||||||
|
|||||||
62
CPP/7zip/Crypto/HmacSha256.cpp
Normal file
62
CPP/7zip/Crypto/HmacSha256.cpp
Normal 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];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}}
|
||||||
27
CPP/7zip/Crypto/HmacSha256.h
Normal file
27
CPP/7zip/Crypto/HmacSha256.h
Normal 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
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "Rar20Crypto.h"
|
#include "Rar20Crypto.h"
|
||||||
|
|
||||||
namespace NCrypto {
|
namespace NCrypto {
|
||||||
namespace NRar20 {
|
namespace NRar2 {
|
||||||
|
|
||||||
static const unsigned kNumRounds = 32;
|
static const unsigned kNumRounds = 32;
|
||||||
|
|
||||||
@@ -39,44 +39,48 @@ void CData::UpdateKeys(const Byte *data)
|
|||||||
Keys[j] ^= g_CrcTable[data[i + j]];
|
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;
|
Byte b = b1;
|
||||||
*b1 = *b2;
|
b1 = b2;
|
||||||
*b2 = b;
|
b2 = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CData::SetPassword(const Byte *data, UInt32 size)
|
void CData::SetPassword(const Byte *data, unsigned size)
|
||||||
{
|
{
|
||||||
Keys[0] = 0xD3A3B879L;
|
Keys[0] = 0xD3A3B879L;
|
||||||
Keys[1] = 0x3F6D12F7L;
|
Keys[1] = 0x3F6D12F7L;
|
||||||
Keys[2] = 0x7515A235L;
|
Keys[2] = 0x7515A235L;
|
||||||
Keys[3] = 0xA4E7F123L;
|
Keys[3] = 0xA4E7F123L;
|
||||||
|
|
||||||
Byte psw[256];
|
Byte psw[128];
|
||||||
if (size >= sizeof(psw))
|
|
||||||
size = sizeof(psw) - 1;
|
|
||||||
memset(psw, 0, sizeof(psw));
|
memset(psw, 0, sizeof(psw));
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
|
{
|
||||||
|
if (size >= sizeof(psw))
|
||||||
|
size = sizeof(psw) - 1;
|
||||||
memcpy(psw, data, size);
|
memcpy(psw, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable));
|
memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable));
|
||||||
|
|
||||||
for (UInt32 j = 0; j < 256; j++)
|
for (unsigned j = 0; j < 256; j++)
|
||||||
for (UInt32 i = 0; i < size; i += 2)
|
for (unsigned i = 0; i < size; i += 2)
|
||||||
{
|
{
|
||||||
UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
|
unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
|
||||||
UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
|
unsigned n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
|
||||||
for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++)
|
for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++)
|
||||||
Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]);
|
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)
|
void CData::CryptBlock(Byte *buf, bool encrypt)
|
||||||
{
|
{
|
||||||
Byte inBuf[16];
|
Byte inBuf[16];
|
||||||
UInt32 A, B, C, D, T, TA, TB;
|
UInt32 A, B, C, D;
|
||||||
|
|
||||||
A = GetUi32(buf + 0) ^ Keys[0];
|
A = GetUi32(buf + 0) ^ Keys[0];
|
||||||
B = GetUi32(buf + 4) ^ Keys[1];
|
B = GetUi32(buf + 4) ^ Keys[1];
|
||||||
@@ -89,14 +93,10 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
|
|||||||
for (unsigned i = 0; i < kNumRounds; i++)
|
for (unsigned i = 0; i < kNumRounds; i++)
|
||||||
{
|
{
|
||||||
UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];
|
UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];
|
||||||
T = ((C + rotlFixed(D, 11)) ^ key);
|
UInt32 TA = A ^ SubstLong((C + rotlFixed(D, 11)) ^ key);
|
||||||
TA = A ^ SubstLong(T);
|
UInt32 TB = B ^ SubstLong((D ^ rotlFixed(C, 17)) + key);
|
||||||
T = ((D ^ rotlFixed(C, 17)) + key);
|
A = C; C = TA;
|
||||||
TB = B ^ SubstLong(T);
|
B = D; D = TB;
|
||||||
A = C;
|
|
||||||
B = D;
|
|
||||||
C = TA;
|
|
||||||
D = TB;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetUi32(buf + 0, C ^ Keys[0]);
|
SetUi32(buf + 0, C ^ Keys[0]);
|
||||||
@@ -107,12 +107,6 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
|
|||||||
UpdateKeys(encrypt ? buf : inBuf);
|
UpdateKeys(encrypt ? buf : inBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
|
||||||
{
|
|
||||||
_cipher.SetPassword(data, size);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CDecoder::Init()
|
STDMETHODIMP CDecoder::Init()
|
||||||
{
|
{
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -126,10 +120,10 @@ STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
|
|||||||
return 0;
|
return 0;
|
||||||
if (size < kBlockSize)
|
if (size < kBlockSize)
|
||||||
return kBlockSize;
|
return kBlockSize;
|
||||||
UInt32 i;
|
|
||||||
size -= kBlockSize;
|
size -= kBlockSize;
|
||||||
|
UInt32 i;
|
||||||
for (i = 0; i <= size; i += kBlockSize)
|
for (i = 0; i <= size; i += kBlockSize)
|
||||||
_cipher.DecryptBlock(data + i);
|
DecryptBlock(data + i);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
#include "../../Common/MyCom.h"
|
#include "../../Common/MyCom.h"
|
||||||
|
|
||||||
#include "../ICoder.h"
|
#include "../ICoder.h"
|
||||||
#include "../IPassword.h"
|
|
||||||
|
|
||||||
namespace NCrypto {
|
namespace NCrypto {
|
||||||
namespace NRar20 {
|
namespace NRar2 {
|
||||||
|
|
||||||
/* ICompressFilter::Init() does nothing for this filter.
|
/* ICompressFilter::Init() does nothing for this filter.
|
||||||
Call CryptoSetPassword() to initialize filter. */
|
Call SetPassword() to initialize filter. */
|
||||||
|
|
||||||
class CData
|
class CData
|
||||||
{
|
{
|
||||||
@@ -31,22 +30,17 @@ class CData
|
|||||||
public:
|
public:
|
||||||
void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }
|
void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }
|
||||||
void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }
|
void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }
|
||||||
void SetPassword(const Byte *password, UInt32 passwordLen);
|
void SetPassword(const Byte *password, unsigned passwordLen);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDecoder:
|
class CDecoder:
|
||||||
public ICompressFilter,
|
public ICompressFilter,
|
||||||
public ICryptoSetPassword,
|
|
||||||
public CMyUnknownImp,
|
public CMyUnknownImp,
|
||||||
public CData
|
public CData
|
||||||
{
|
{
|
||||||
CData _cipher;
|
|
||||||
public:
|
public:
|
||||||
MY_UNKNOWN_IMP1(ICryptoSetPassword)
|
MY_UNKNOWN_IMP
|
||||||
|
INTERFACE_ICompressFilter(;)
|
||||||
STDMETHOD(Init)();
|
|
||||||
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
|
|
||||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
257
CPP/7zip/Crypto/Rar5Aes.cpp
Normal file
257
CPP/7zip/Crypto/Rar5Aes.cpp
Normal 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
84
CPP/7zip/Crypto/Rar5Aes.h
Normal 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
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// Crypto/RarAes.cpp
|
// Crypto/RarAes.cpp
|
||||||
// Note: you must include MyAes.cpp to project to initialize AES tables
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
@@ -7,10 +6,10 @@
|
|||||||
#include "Sha1Cls.h"
|
#include "Sha1Cls.h"
|
||||||
|
|
||||||
namespace NCrypto {
|
namespace NCrypto {
|
||||||
namespace NRar29 {
|
namespace NRar3 {
|
||||||
|
|
||||||
CDecoder::CDecoder():
|
CDecoder::CDecoder():
|
||||||
CAesCbcDecoder(kRarAesKeySize),
|
CAesCbcDecoder(kAesKeySize),
|
||||||
_thereIsSalt(false),
|
_thereIsSalt(false),
|
||||||
_needCalc(true),
|
_needCalc(true),
|
||||||
_rar350Mode(false)
|
_rar350Mode(false)
|
||||||
@@ -19,7 +18,7 @@ CDecoder::CDecoder():
|
|||||||
_salt[i] = 0;
|
_salt[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
HRESULT CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||||
{
|
{
|
||||||
bool prev = _thereIsSalt;
|
bool prev = _thereIsSalt;
|
||||||
_thereIsSalt = false;
|
_thereIsSalt = false;
|
||||||
@@ -53,12 +52,12 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
|||||||
return S_OK;
|
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)
|
if (size > kPasswordLen_Bytes_MAX)
|
||||||
size = kPasswordLen_MAX;
|
size = kPasswordLen_Bytes_MAX;
|
||||||
bool same = false;
|
bool same = false;
|
||||||
if (size == _password.Size())
|
if (size == _password.Size())
|
||||||
{
|
{
|
||||||
@@ -73,13 +72,12 @@ STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
|||||||
if (!_needCalc && !same)
|
if (!_needCalc && !same)
|
||||||
_needCalc = true;
|
_needCalc = true;
|
||||||
_password.CopyFrom(data, (size_t)size);
|
_password.CopyFrom(data, (size_t)size);
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP CDecoder::Init()
|
STDMETHODIMP CDecoder::Init()
|
||||||
{
|
{
|
||||||
CalcKey();
|
CalcKey();
|
||||||
RINOK(SetKey(_key, kRarAesKeySize));
|
RINOK(SetKey(_key, kAesKeySize));
|
||||||
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
|
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
|
||||||
return CAesCbcCoder::Init();
|
return CAesCbcCoder::Init();
|
||||||
}
|
}
|
||||||
@@ -91,7 +89,7 @@ void CDecoder::CalcKey()
|
|||||||
|
|
||||||
const unsigned kSaltSize = 8;
|
const unsigned kSaltSize = 8;
|
||||||
|
|
||||||
Byte buf[kPasswordLen_MAX + kSaltSize];
|
Byte buf[kPasswordLen_Bytes_MAX + kSaltSize];
|
||||||
|
|
||||||
if (_password.Size() != 0)
|
if (_password.Size() != 0)
|
||||||
memcpy(buf, _password, _password.Size());
|
memcpy(buf, _password, _password.Size());
|
||||||
@@ -109,7 +107,7 @@ void CDecoder::CalcKey()
|
|||||||
|
|
||||||
Byte digest[NSha1::kDigestSize];
|
Byte digest[NSha1::kDigestSize];
|
||||||
// rar reverts hash for sha.
|
// rar reverts hash for sha.
|
||||||
const UInt32 kNumRounds = (1 << 18);
|
const UInt32 kNumRounds = ((UInt32)1 << 18);
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < kNumRounds; i++)
|
for (i = 0; i < kNumRounds; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,14 +12,14 @@
|
|||||||
#include "MyAes.h"
|
#include "MyAes.h"
|
||||||
|
|
||||||
namespace NCrypto {
|
namespace NCrypto {
|
||||||
namespace NRar29 {
|
namespace NRar3 {
|
||||||
|
|
||||||
const UInt32 kRarAesKeySize = 16;
|
const unsigned kAesKeySize = 16;
|
||||||
|
|
||||||
class CDecoder:
|
class CDecoder:
|
||||||
public CAesCbcDecoder,
|
public CAesCbcDecoder
|
||||||
// public ICompressSetDecoderProperties2,
|
// public ICompressSetDecoderProperties2,
|
||||||
public ICryptoSetPassword
|
// public ICryptoSetPassword
|
||||||
{
|
{
|
||||||
Byte _salt[8];
|
Byte _salt[8];
|
||||||
bool _thereIsSalt;
|
bool _thereIsSalt;
|
||||||
@@ -28,17 +28,20 @@ class CDecoder:
|
|||||||
|
|
||||||
CByteBuffer _password;
|
CByteBuffer _password;
|
||||||
|
|
||||||
Byte _key[kRarAesKeySize];
|
Byte _key[kAesKeySize];
|
||||||
Byte _iv[AES_BLOCK_SIZE];
|
Byte _iv[AES_BLOCK_SIZE];
|
||||||
|
|
||||||
void CalcKey();
|
void CalcKey();
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
MY_UNKNOWN_IMP1(
|
MY_UNKNOWN_IMP1(
|
||||||
ICryptoSetPassword)
|
ICryptoSetPassword
|
||||||
// ICompressSetDecoderProperties2
|
// ICompressSetDecoderProperties2
|
||||||
|
*/
|
||||||
STDMETHOD(Init)();
|
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();
|
CDecoder();
|
||||||
void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }
|
void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ Handler GUIDs:
|
|||||||
0C xz
|
0C xz
|
||||||
0D ppmd
|
0D ppmd
|
||||||
|
|
||||||
|
CC Rar5
|
||||||
CD IHex
|
CD IHex
|
||||||
CE Hxs
|
CE Hxs
|
||||||
CF TE
|
CF TE
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#define __IPROGRESS_H
|
#define __IPROGRESS_H
|
||||||
|
|
||||||
#include "../Common/MyTypes.h"
|
#include "../Common/MyTypes.h"
|
||||||
#include "../Common/MyUnknown.h"
|
|
||||||
|
|
||||||
#include "IDecl.h"
|
#include "IDecl.h"
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#define __ISTREAM_H
|
#define __ISTREAM_H
|
||||||
|
|
||||||
#include "../Common/MyTypes.h"
|
#include "../Common/MyTypes.h"
|
||||||
#include "../Common/MyUnknown.h"
|
#include "../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "IDecl.h"
|
#include "IDecl.h"
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ enum
|
|||||||
kpidStreamId,
|
kpidStreamId,
|
||||||
kpidReadOnly,
|
kpidReadOnly,
|
||||||
kpidOutName,
|
kpidOutName,
|
||||||
|
kpidCopyLink,
|
||||||
|
|
||||||
kpid_NUM_DEFINED,
|
kpid_NUM_DEFINED,
|
||||||
|
|
||||||
|
|||||||
@@ -380,6 +380,21 @@ STDMETHODIMP CAgent::DoOperation(
|
|||||||
HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
|
HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
|
||||||
if (res == S_OK && processedPaths)
|
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)
|
FOR_VECTOR (i, dirItems.Items)
|
||||||
if (processedItems[i] != 0)
|
if (processedItems[i] != 0)
|
||||||
processedPaths->Add(dirItems.GetPhyPath(i));
|
processedPaths->Add(dirItems.GetPhyPath(i));
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "../../../Common/Defs.h"
|
#include "../../../Common/Defs.h"
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#undef sprintf
|
#undef sprintf
|
||||||
#undef printf
|
#undef printf
|
||||||
|
|
||||||
|
#include "../../../../C/Alloc.h"
|
||||||
|
|
||||||
#include "../../../Common/ComTry.h"
|
#include "../../../Common/ComTry.h"
|
||||||
#include "../../../Common/IntToString.h"
|
#include "../../../Common/IntToString.h"
|
||||||
#include "../../../Common/StringConvert.h"
|
#include "../../../Common/StringConvert.h"
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../Common/FilePathAutoRename.h"
|
#include "../../Common/FilePathAutoRename.h"
|
||||||
|
// #include "../../Common/StreamUtils.h"
|
||||||
|
|
||||||
#include "../Common/ExtractingFilePath.h"
|
#include "../Common/ExtractingFilePath.h"
|
||||||
#include "../Common/PropIDUtils.h"
|
#include "../Common/PropIDUtils.h"
|
||||||
@@ -541,11 +544,54 @@ static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)
|
|||||||
return s;
|
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)
|
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
|
|
||||||
*outStream = 0;
|
*outStream = NULL;
|
||||||
|
|
||||||
#ifndef _SFX
|
#ifndef _SFX
|
||||||
if (_hashStream)
|
if (_hashStream)
|
||||||
@@ -563,6 +609,11 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
|||||||
_curSizeDefined = false;
|
_curSizeDefined = false;
|
||||||
_index = index;
|
_index = index;
|
||||||
|
|
||||||
|
#ifdef SUPPORT_LINKS
|
||||||
|
// _CopyFile_Path.Empty();
|
||||||
|
linkPath.Empty();
|
||||||
|
#endif
|
||||||
|
|
||||||
IInArchive *archive = _arc->Archive;
|
IInArchive *archive = _arc->Archive;
|
||||||
|
|
||||||
#ifndef _SFX
|
#ifndef _SFX
|
||||||
@@ -596,46 +647,56 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
|||||||
|
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
|
|
||||||
|
// bool isCopyLink = false;
|
||||||
bool isHardLink = false;
|
bool isHardLink = false;
|
||||||
bool isJunction = false;
|
bool isJunction = false;
|
||||||
bool isRelative = false;
|
bool isRelative = false;
|
||||||
|
|
||||||
UString linkPath;
|
|
||||||
// RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink));
|
|
||||||
// if (isHardLink)
|
|
||||||
{
|
{
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
RINOK(archive->GetProperty(index, kpidHardLink, &prop));
|
RINOK(archive->GetProperty(index, kpidHardLink, &prop));
|
||||||
if (prop.vt == VT_BSTR)
|
if (prop.vt == VT_BSTR)
|
||||||
{
|
{
|
||||||
isHardLink = true;
|
isHardLink = true;
|
||||||
|
// isCopyLink = false;
|
||||||
|
isRelative = false; // RAR5, TAR: hard links are from root folder of archive
|
||||||
linkPath.SetFromBstr(prop.bstrVal);
|
linkPath.SetFromBstr(prop.bstrVal);
|
||||||
isRelative = false; // TAR: hard links are from root folder of archive
|
|
||||||
}
|
}
|
||||||
else if (prop.vt == VT_EMPTY)
|
else if (prop.vt != VT_EMPTY)
|
||||||
{
|
|
||||||
// linkPath.Empty();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return E_FAIL;
|
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;
|
NCOM::CPropVariant prop;
|
||||||
RINOK(archive->GetProperty(index, kpidSymLink, &prop));
|
RINOK(archive->GetProperty(index, kpidSymLink, &prop));
|
||||||
if (prop.vt == VT_BSTR)
|
if (prop.vt == VT_BSTR)
|
||||||
{
|
{
|
||||||
isHardLink = false;
|
isHardLink = false;
|
||||||
|
// isCopyLink = false;
|
||||||
|
isRelative = true; // RAR5, TAR: symbolic links can be relative
|
||||||
linkPath.SetFromBstr(prop.bstrVal);
|
linkPath.SetFromBstr(prop.bstrVal);
|
||||||
isRelative = true; // TAR: symbolic links are relative
|
|
||||||
}
|
}
|
||||||
else if (prop.vt == VT_EMPTY)
|
else if (prop.vt != VT_EMPTY)
|
||||||
{
|
|
||||||
// linkPath.Empty();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool isOkReparse = false;
|
bool isOkReparse = false;
|
||||||
|
|
||||||
if (linkPath.IsEmpty() && _arc->GetRawProps)
|
if (linkPath.IsEmpty() && _arc->GetRawProps)
|
||||||
@@ -643,7 +704,9 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
|||||||
const void *data;
|
const void *data;
|
||||||
UInt32 dataSize;
|
UInt32 dataSize;
|
||||||
UInt32 propType;
|
UInt32 propType;
|
||||||
|
|
||||||
_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
|
_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
|
||||||
|
|
||||||
if (dataSize != 0)
|
if (dataSize != 0)
|
||||||
{
|
{
|
||||||
if (propType != NPropDataType::kRaw)
|
if (propType != NPropDataType::kRaw)
|
||||||
@@ -654,6 +717,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
|||||||
if (isOkReparse)
|
if (isOkReparse)
|
||||||
{
|
{
|
||||||
isHardLink = false;
|
isHardLink = false;
|
||||||
|
// isCopyLink = false;
|
||||||
linkPath = reparse.GetPath();
|
linkPath = reparse.GetPath();
|
||||||
isJunction = reparse.IsMountPoint();
|
isJunction = reparse.IsMountPoint();
|
||||||
isRelative = reparse.IsRelative();
|
isRelative = reparse.IsRelative();
|
||||||
@@ -669,6 +733,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// rar5 uses "\??\" prefix for absolute links
|
||||||
|
if (linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR))
|
||||||
|
{
|
||||||
|
isRelative = false;
|
||||||
|
linkPath.DeleteFrontal(4);
|
||||||
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
// while (NName::IsAbsolutePath(linkPath))
|
// while (NName::IsAbsolutePath(linkPath))
|
||||||
@@ -1108,7 +1179,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
FString existPath;
|
FString existPath;
|
||||||
if (isHardLink || !isRelative)
|
if (isHardLink /* || isCopyLink */ || !isRelative)
|
||||||
{
|
{
|
||||||
if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
|
if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
|
||||||
{
|
{
|
||||||
@@ -1122,13 +1193,37 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
|||||||
|
|
||||||
if (!existPath.IsEmpty())
|
if (!existPath.IsEmpty())
|
||||||
{
|
{
|
||||||
if (isHardLink)
|
if (isHardLink /* || isCopyLink */)
|
||||||
{
|
{
|
||||||
if (!MyCreateHardLink(fullProcessedPath, existPath))
|
// if (isHardLink)
|
||||||
{
|
{
|
||||||
RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
|
if (!MyCreateHardLink(fullProcessedPath, existPath))
|
||||||
// return S_OK;
|
{
|
||||||
|
RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
|
||||||
|
// 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)
|
else if (_ntOptions.SymLinks.Val)
|
||||||
{
|
{
|
||||||
@@ -1161,7 +1256,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */)
|
||||||
#endif // SUPPORT_LINKS
|
#endif // SUPPORT_LINKS
|
||||||
{
|
{
|
||||||
bool needWriteFile = true;
|
bool needWriteFile = true;
|
||||||
@@ -1225,6 +1321,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
|||||||
{
|
{
|
||||||
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
|
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
_outFileStream = outStreamLoc;
|
_outFileStream = outStreamLoc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1250,12 +1347,34 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (outStreamLoc)
|
if (outStreamLoc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
#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();
|
*outStream = outStreamLoc.Detach();
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
@@ -1266,6 +1385,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
_extractMode = false;
|
_extractMode = false;
|
||||||
|
|
||||||
switch (askExtractMode)
|
switch (askExtractMode)
|
||||||
{
|
{
|
||||||
case NArchive::NExtract::NAskMode::kExtract:
|
case NArchive::NExtract::NAskMode::kExtract:
|
||||||
@@ -1282,6 +1402,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
|||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
@@ -1346,6 +1467,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
|||||||
|
|
||||||
if (!_curSizeDefined)
|
if (!_curSizeDefined)
|
||||||
GetUnpackSize();
|
GetUnpackSize();
|
||||||
|
|
||||||
if (_curSizeDefined)
|
if (_curSizeDefined)
|
||||||
{
|
{
|
||||||
#ifdef SUPPORT_ALT_STREAMS
|
#ifdef SUPPORT_ALT_STREAMS
|
||||||
@@ -1367,8 +1489,11 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
|||||||
|
|
||||||
if (_extractMode && _fi.AttribDefined)
|
if (_extractMode && _fi.AttribDefined)
|
||||||
SetFileAttrib(_diskFilePath, _fi.Attrib);
|
SetFileAttrib(_diskFilePath, _fi.Attrib);
|
||||||
|
|
||||||
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
|
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -299,14 +299,23 @@ public:
|
|||||||
const UStringVector &removePathParts, bool removePartsForAltStreams,
|
const UStringVector &removePathParts, bool removePartsForAltStreams,
|
||||||
UInt64 packSize);
|
UInt64 packSize);
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CHardLinks _hardLinks;
|
CHardLinks _hardLinks;
|
||||||
|
UString linkPath;
|
||||||
|
|
||||||
|
// FString _CopyFile_Path;
|
||||||
|
// HRESULT MyCopyFile(ISequentialOutStream *outStream);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// call PrepareHardLinks() after Init()
|
// call PrepareHardLinks() after Init()
|
||||||
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
|
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPPORT_ALT_STREAMS
|
#ifdef SUPPORT_ALT_STREAMS
|
||||||
CObjectVector<CIndexToPathPair> _renamedFiles;
|
CObjectVector<CIndexToPathPair> _renamedFiles;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -48,18 +48,13 @@ class COpenCallbackImp:
|
|||||||
public CMyUnknownImp
|
public CMyUnknownImp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback)
|
||||||
|
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName)
|
||||||
#ifndef _NO_CRYPTO
|
#ifndef _NO_CRYPTO
|
||||||
MY_UNKNOWN_IMP3(
|
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
|
||||||
IArchiveOpenVolumeCallback,
|
|
||||||
ICryptoGetTextPassword,
|
|
||||||
IArchiveOpenSetSubArchiveName
|
|
||||||
)
|
|
||||||
#else
|
|
||||||
MY_UNKNOWN_IMP2(
|
|
||||||
IArchiveOpenVolumeCallback,
|
|
||||||
IArchiveOpenSetSubArchiveName
|
|
||||||
)
|
|
||||||
#endif
|
#endif
|
||||||
|
MY_QUERYINTERFACE_END
|
||||||
|
MY_ADDREF_RELEASE
|
||||||
|
|
||||||
INTERFACE_IArchiveOpenCallback(;)
|
INTERFACE_IArchiveOpenCallback(;)
|
||||||
INTERFACE_IArchiveOpenVolumeCallback(;)
|
INTERFACE_IArchiveOpenVolumeCallback(;)
|
||||||
@@ -93,7 +88,8 @@ public:
|
|||||||
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
|
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
|
||||||
// UInt64 TotalSize;
|
// UInt64 TotalSize;
|
||||||
|
|
||||||
COpenCallbackImp(): Callback(NULL) {}
|
COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {}
|
||||||
|
|
||||||
void Init(const FString &folderPrefix, const FString &fileName)
|
void Init(const FString &folderPrefix, const FString &fileName)
|
||||||
{
|
{
|
||||||
_folderPrefix = folderPrefix;
|
_folderPrefix = folderPrefix;
|
||||||
@@ -106,6 +102,7 @@ public:
|
|||||||
// TotalSize = 0;
|
// TotalSize = 0;
|
||||||
PasswordWasAsked = false;
|
PasswordWasAsked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetSecondFileInfo(CFSTR newName)
|
bool SetSecondFileInfo(CFSTR newName)
|
||||||
{
|
{
|
||||||
return _fileInfo.Find(newName) && !_fileInfo.IsDir();
|
return _fileInfo.Find(newName) && !_fileInfo.IsDir();
|
||||||
|
|||||||
@@ -1566,7 +1566,8 @@ static const CBenchHash g_Hash[] =
|
|||||||
{ 10, 339, 0x8F8FEDAB, "CRC32:8" },
|
{ 10, 339, 0x8F8FEDAB, "CRC32:8" },
|
||||||
{ 10, 512, 0xDF1C17CC, "CRC64" },
|
{ 10, 512, 0xDF1C17CC, "CRC64" },
|
||||||
{ 10, 5100, 0x2D79FF2E, "SHA256" },
|
{ 10, 5100, 0x2D79FF2E, "SHA256" },
|
||||||
{ 10, 2340, 0x4C25132B, "SHA1" }
|
{ 10, 2340, 0x4C25132B, "SHA1" },
|
||||||
|
{ 2, 5500, 0xE084E913, "BLAKE2sp" }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CTotalBenchRes
|
struct CTotalBenchRes
|
||||||
|
|||||||
@@ -865,7 +865,7 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
|
|||||||
{
|
{
|
||||||
const CCodecLib &lib = Libs[ci.LibIndex];
|
const CCodecLib &lib = Libs[ci.LibIndex];
|
||||||
if (lib.CreateDecoder)
|
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 lib.CreateObject(&ci.Decoder, iid, (void **)coder);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -887,7 +887,7 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
|
|||||||
{
|
{
|
||||||
const CCodecLib &lib = Libs[ci.LibIndex];
|
const CCodecLib &lib = Libs[ci.LibIndex];
|
||||||
if (lib.CreateEncoder)
|
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 lib.CreateObject(&ci.Encoder, iid, (void **)coder);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|||||||
@@ -1083,6 +1083,7 @@ static bool IsNewStyleSignature(const CArcInfoEx &ai)
|
|||||||
|
|
||||||
class CArchiveOpenCallback_Offset:
|
class CArchiveOpenCallback_Offset:
|
||||||
public IArchiveOpenCallback,
|
public IArchiveOpenCallback,
|
||||||
|
public IArchiveOpenVolumeCallback,
|
||||||
#ifndef _NO_CRYPTO
|
#ifndef _NO_CRYPTO
|
||||||
public ICryptoGetTextPassword,
|
public ICryptoGetTextPassword,
|
||||||
#endif
|
#endif
|
||||||
@@ -1090,19 +1091,24 @@ class CArchiveOpenCallback_Offset:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CMyComPtr<IArchiveOpenCallback> Callback;
|
CMyComPtr<IArchiveOpenCallback> Callback;
|
||||||
|
CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback;
|
||||||
UInt64 Files;
|
UInt64 Files;
|
||||||
UInt64 Offset;
|
UInt64 Offset;
|
||||||
|
|
||||||
#ifndef _NO_CRYPTO
|
#ifndef _NO_CRYPTO
|
||||||
CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
|
CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
|
||||||
MY_UNKNOWN_IMP2(
|
|
||||||
IArchiveOpenCallback,
|
|
||||||
ICryptoGetTextPassword)
|
|
||||||
#else
|
|
||||||
MY_UNKNOWN_IMP1(IArchiveOpenCallback)
|
|
||||||
#endif
|
#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
|
#ifndef _NO_CRYPTO
|
||||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||||
#endif
|
#endif
|
||||||
@@ -1119,12 +1125,12 @@ STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
|
STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *)
|
||||||
{
|
{
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes)
|
STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes)
|
||||||
{
|
{
|
||||||
if (!Callback)
|
if (!Callback)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -1134,8 +1140,25 @@ STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files *
|
|||||||
return Callback->SetCompleted(&Files, &value);
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
|
UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
|
||||||
{
|
{
|
||||||
if (isDefinedProp != NULL)
|
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 kBeforeSize = 1 << 16;
|
||||||
const size_t kAfterSize = 1 << 20;
|
const size_t kAfterSize = 1 << 20;
|
||||||
const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize
|
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;
|
CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
|
||||||
limitedStreamSpec->SetStream(op.stream);
|
limitedStreamSpec->SetStream(op.stream);
|
||||||
|
|
||||||
openCallback_Offset_Spec->Callback = op.callback;
|
CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL;
|
||||||
|
CMyComPtr<IArchiveOpenCallback> openCallback_Offset;
|
||||||
#ifndef _NO_CRYPTO
|
|
||||||
if (op.callback)
|
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);
|
openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (op.callback)
|
if (op.callback)
|
||||||
RINOK(op.callback->SetTotal(NULL, &fileSize));
|
RINOK(op.callback->SetTotal(NULL, &fileSize));
|
||||||
@@ -2382,12 +2406,19 @@ 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->Files = handlerSpec->_items.Size();
|
||||||
openCallback_Offset_Spec->Offset = pos;
|
openCallback_Offset_Spec->Offset = pos;
|
||||||
RINOK(openCallback_Offset->SetCompleted(NULL, NULL));
|
|
||||||
callbackPrev = pos;
|
useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);
|
||||||
|
|
||||||
|
if (pos >= callbackPrev + (1 << 23))
|
||||||
|
{
|
||||||
|
RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL));
|
||||||
|
callbackPrev = pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -2557,14 +2588,21 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
UInt64 maxCheckStartPosition = 0;
|
UInt64 maxCheckStartPosition = 0;
|
||||||
openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
|
|
||||||
openCallback_Offset_Spec->Offset = startArcPos;
|
if (openCallback_Offset)
|
||||||
|
{
|
||||||
|
openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
|
||||||
|
openCallback_Offset_Spec->Offset = startArcPos;
|
||||||
|
}
|
||||||
|
|
||||||
// HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
|
// HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
|
||||||
extractCallback_To_OpenCallback_Spec->Files = 0;
|
extractCallback_To_OpenCallback_Spec->Files = 0;
|
||||||
extractCallback_To_OpenCallback_Spec->Offset = startArcPos;
|
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));
|
RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result));
|
||||||
|
|
||||||
bool isOpen = false;
|
bool isOpen = false;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace NUpdateArchive {
|
|||||||
{
|
{
|
||||||
NPairAction::EEnum StateActions[NPairState::kNumValues];
|
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++)
|
for (unsigned i = 0; i < NPairState::kNumValues; i++)
|
||||||
if (StateActions[i] != a.StateActions[i])
|
if (StateActions[i] != a.StateActions[i])
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
|
|||||||
{
|
{
|
||||||
case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
|
case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
|
||||||
case kpidIsDir: prop = di.IsDir(); 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 kpidAttrib: prop = di.Attrib; break;
|
||||||
case kpidCTime: prop = di.CTime; break;
|
case kpidCTime: prop = di.CTime; break;
|
||||||
case kpidATime: prop = di.ATime; break;
|
case kpidATime: prop = di.ATime; break;
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
#include "ConsoleClose.h"
|
#include "ConsoleClose.h"
|
||||||
|
|
||||||
|
#if !defined(UNDER_CE) && defined(_WIN32)
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace NConsoleClose {
|
namespace NConsoleClose {
|
||||||
|
|
||||||
unsigned g_BreakCounter = 0;
|
unsigned g_BreakCounter = 0;
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ static const char * const kPropIdToName[] =
|
|||||||
, "Stream ID"
|
, "Stream ID"
|
||||||
, "Read-only"
|
, "Read-only"
|
||||||
, "Out Name"
|
, "Out Name"
|
||||||
|
, "Copy Link"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char kEmptyAttribChar = '.';
|
static const char kEmptyAttribChar = '.';
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
|
||||||
#include "../../../../C/CpuArch.h"
|
#include "../../../../C/CpuArch.h"
|
||||||
@@ -230,42 +232,51 @@ static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
|
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;
|
int exitCode = NExitCode::kSuccess;
|
||||||
|
|
||||||
if (callback.ScanErrors.Paths.Size() != 0)
|
if (callback.ScanErrors.Paths.Size() != 0)
|
||||||
{
|
{
|
||||||
so << endl;
|
if (se)
|
||||||
so << "Scan WARNINGS for files and folders:" << endl << endl;
|
{
|
||||||
PrintWarningsPaths(callback.ScanErrors, so);
|
*se << endl;
|
||||||
so << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
|
*se << "Scan WARNINGS for files and folders:" << endl << endl;
|
||||||
so << endl;
|
PrintWarningsPaths(callback.ScanErrors, *se);
|
||||||
|
*se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
|
||||||
|
*se << endl;
|
||||||
|
}
|
||||||
exitCode = NExitCode::kWarning;
|
exitCode = NExitCode::kWarning;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != S_OK || errorInfo.ThereIsError())
|
if (result != S_OK || errorInfo.ThereIsError())
|
||||||
{
|
{
|
||||||
UString message;
|
if (se)
|
||||||
if (!errorInfo.Message.IsEmpty())
|
|
||||||
{
|
{
|
||||||
message.AddAscii(errorInfo.Message);
|
UString message;
|
||||||
message.Add_LF();
|
if (!errorInfo.Message.IsEmpty())
|
||||||
}
|
|
||||||
{
|
|
||||||
FOR_VECTOR(i, errorInfo.FileNames)
|
|
||||||
{
|
{
|
||||||
message += fs2us(errorInfo.FileNames[i]);
|
message.AddAscii(errorInfo.Message);
|
||||||
message.Add_LF();
|
message.Add_LF();
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
FOR_VECTOR(i, errorInfo.FileNames)
|
||||||
|
{
|
||||||
|
message += fs2us(errorInfo.FileNames[i]);
|
||||||
|
message.Add_LF();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorInfo.SystemError != 0)
|
||||||
|
{
|
||||||
|
message += NError::MyFormatMessage(errorInfo.SystemError);
|
||||||
|
message.Add_LF();
|
||||||
|
}
|
||||||
|
if (!message.IsEmpty())
|
||||||
|
*se << L"\nError:\n" << message;
|
||||||
}
|
}
|
||||||
if (errorInfo.SystemError != 0)
|
|
||||||
{
|
|
||||||
message += NError::MyFormatMessage(errorInfo.SystemError);
|
|
||||||
message.Add_LF();
|
|
||||||
}
|
|
||||||
if (!message.IsEmpty())
|
|
||||||
so << L"\nError:\n" << message;
|
|
||||||
|
|
||||||
// we will work with (result) later
|
// we will work with (result) later
|
||||||
// throw CSystemException(result);
|
// throw CSystemException(result);
|
||||||
@@ -277,17 +288,25 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
|
|||||||
{
|
{
|
||||||
if (showHeaders)
|
if (showHeaders)
|
||||||
if (callback.ScanErrors.Paths.Size() == 0)
|
if (callback.ScanErrors.Paths.Size() == 0)
|
||||||
so << kEverythingIsOk << endl;
|
if (so)
|
||||||
|
{
|
||||||
|
if (se)
|
||||||
|
se->Flush();
|
||||||
|
*so << kEverythingIsOk << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
so << endl;
|
if (se)
|
||||||
so << "WARNINGS for files:" << endl << endl;
|
{
|
||||||
PrintWarningsPaths(callback.FailedFiles, so);
|
*se << endl;
|
||||||
so << "WARNING: Cannot open " << numErrors << " file";
|
*se << "WARNINGS for files:" << endl << endl;
|
||||||
if (numErrors > 1)
|
PrintWarningsPaths(callback.FailedFiles, *se);
|
||||||
so << 's';
|
*se << "WARNING: Cannot open " << numErrors << " file";
|
||||||
so << endl;
|
if (numErrors > 1)
|
||||||
|
*se << 's';
|
||||||
|
*se << endl;
|
||||||
|
}
|
||||||
exitCode = NExitCode::kWarning;
|
exitCode = NExitCode::kWarning;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,10 +492,7 @@ int Main2(
|
|||||||
CStdOutStream *percentsStream = NULL;
|
CStdOutStream *percentsStream = NULL;
|
||||||
if (options.Number_for_Percents != k_OutStream_disabled)
|
if (options.Number_for_Percents != k_OutStream_disabled)
|
||||||
percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;
|
percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;
|
||||||
|
|
||||||
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
|
|
||||||
|
|
||||||
|
|
||||||
if (options.HelpMode)
|
if (options.HelpMode)
|
||||||
{
|
{
|
||||||
ShowCopyrightAndHelp(g_StdStream, true);
|
ShowCopyrightAndHelp(g_StdStream, true);
|
||||||
@@ -589,6 +605,7 @@ int Main2(
|
|||||||
|
|
||||||
if (options.Command.CommandType == NCommandType::kInfo)
|
if (options.Command.CommandType == NCommandType::kInfo)
|
||||||
{
|
{
|
||||||
|
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
#ifdef EXTERNAL_CODECS
|
#ifdef EXTERNAL_CODECS
|
||||||
@@ -754,6 +771,7 @@ int Main2(
|
|||||||
}
|
}
|
||||||
else if (options.Command.CommandType == NCommandType::kBenchmark)
|
else if (options.Command.CommandType == NCommandType::kBenchmark)
|
||||||
{
|
{
|
||||||
|
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
|
||||||
hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
|
hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
|
||||||
options.Properties, options.NumIterations, (FILE *)so);
|
options.Properties, options.NumIterations, (FILE *)so);
|
||||||
if (hresultMain == S_FALSE)
|
if (hresultMain == S_FALSE)
|
||||||
@@ -890,73 +908,91 @@ int Main2(
|
|||||||
hresultMain = E_FAIL;
|
hresultMain = E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
so << endl;
|
CStdOutStream *so = g_StdStream;
|
||||||
|
|
||||||
if (ecs->NumTryArcs > 1)
|
|
||||||
{
|
|
||||||
so << "Archives: " << ecs->NumTryArcs << endl;
|
|
||||||
so << "OK archives: " << ecs->NumOkArcs << endl;
|
|
||||||
}
|
|
||||||
bool isError = false;
|
bool isError = false;
|
||||||
|
|
||||||
|
if (so)
|
||||||
|
{
|
||||||
|
*so << endl;
|
||||||
|
|
||||||
|
if (ecs->NumTryArcs > 1)
|
||||||
|
{
|
||||||
|
*so << "Archives: " << ecs->NumTryArcs << endl;
|
||||||
|
*so << "OK archives: " << ecs->NumOkArcs << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ecs->NumCantOpenArcs != 0)
|
if (ecs->NumCantOpenArcs != 0)
|
||||||
{
|
{
|
||||||
isError = true;
|
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)
|
if (ecs->NumArcsWithError != 0)
|
||||||
{
|
{
|
||||||
isError = true;
|
isError = true;
|
||||||
so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
|
if (so)
|
||||||
|
*so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
|
||||||
}
|
}
|
||||||
if (ecs->NumArcsWithWarnings != 0)
|
|
||||||
so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
|
|
||||||
|
|
||||||
if (ecs->NumOpenArcWarnings != 0)
|
if (so)
|
||||||
{
|
{
|
||||||
so << endl;
|
if (ecs->NumArcsWithWarnings != 0)
|
||||||
|
*so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
|
||||||
|
|
||||||
if (ecs->NumOpenArcWarnings != 0)
|
if (ecs->NumOpenArcWarnings != 0)
|
||||||
so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
|
{
|
||||||
|
*so << endl;
|
||||||
|
if (ecs->NumOpenArcWarnings != 0)
|
||||||
|
*so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ecs->NumOpenArcErrors != 0)
|
if (ecs->NumOpenArcErrors != 0)
|
||||||
{
|
{
|
||||||
isError = true;
|
isError = true;
|
||||||
so << endl;
|
if (so)
|
||||||
if (ecs->NumOpenArcErrors != 0)
|
{
|
||||||
so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
|
*so << endl;
|
||||||
|
if (ecs->NumOpenArcErrors != 0)
|
||||||
|
*so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError)
|
if (isError)
|
||||||
retCode = NExitCode::kFatalError;
|
retCode = NExitCode::kFatalError;
|
||||||
|
|
||||||
|
if (so)
|
||||||
if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
|
if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
|
||||||
{
|
{
|
||||||
// if (ecs->NumArchives > 1)
|
// if (ecs->NumArchives > 1)
|
||||||
{
|
{
|
||||||
so << endl;
|
*so << endl;
|
||||||
if (ecs->NumFileErrors != 0)
|
if (ecs->NumFileErrors != 0)
|
||||||
so << "Sub items Errors: " << ecs->NumFileErrors << endl;
|
*so << "Sub items Errors: " << ecs->NumFileErrors << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hresultMain == S_OK)
|
else if (hresultMain == S_OK)
|
||||||
{
|
{
|
||||||
if (stat.NumFolders != 0)
|
if (stat.NumFolders != 0)
|
||||||
so << "Folders: " << stat.NumFolders << endl;
|
*so << "Folders: " << stat.NumFolders << endl;
|
||||||
if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
|
if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
|
||||||
so << "Files: " << stat.NumFiles << endl;
|
*so << "Files: " << stat.NumFiles << endl;
|
||||||
if (stat.NumAltStreams != 0)
|
if (stat.NumAltStreams != 0)
|
||||||
{
|
{
|
||||||
so << "Alternate Streams: " << stat.NumAltStreams << endl;
|
*so << "Alternate Streams: " << stat.NumAltStreams << endl;
|
||||||
so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
|
*so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
so
|
*so
|
||||||
<< "Size: " << stat.UnpackSize << endl
|
<< "Size: " << stat.UnpackSize << endl
|
||||||
<< "Compressed: " << stat.PackSize << endl;
|
<< "Compressed: " << stat.PackSize << endl;
|
||||||
if (hashCalc)
|
if (hashCalc)
|
||||||
{
|
{
|
||||||
so << endl;
|
*so << endl;
|
||||||
PrintHashStat(so, hb);
|
PrintHashStat(*so, hb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1047,9 +1083,14 @@ int Main2(
|
|||||||
|
|
||||||
callback.ClosePercents2();
|
callback.ClosePercents2();
|
||||||
|
|
||||||
retCode = WarningsCheck(hresultMain, callback, errorInfo, so,
|
CStdOutStream *se = g_StdStream;
|
||||||
// options.EnableHeaders
|
if (!se)
|
||||||
true);
|
se = g_ErrStream;
|
||||||
|
|
||||||
|
retCode = WarningsCheck(hresultMain, callback, errorInfo,
|
||||||
|
g_StdStream, se,
|
||||||
|
true // options.EnableHeaders
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (options.Command.CommandType == NCommandType::kHash)
|
else if (options.Command.CommandType == NCommandType::kHash)
|
||||||
{
|
{
|
||||||
@@ -1068,7 +1109,10 @@ int Main2(
|
|||||||
errorInfoString, &callback);
|
errorInfoString, &callback);
|
||||||
CUpdateErrorInfo errorInfo;
|
CUpdateErrorInfo errorInfo;
|
||||||
errorInfo.Message = errorInfoString;
|
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
|
else
|
||||||
ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
|
ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
#ifndef __CONTEXT_MENU_H
|
#ifndef __CONTEXT_MENU_H
|
||||||
#define __CONTEXT_MENU_H
|
#define __CONTEXT_MENU_H
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
|
#include <ShlObj.h>
|
||||||
|
|
||||||
#include "../../../Common/MyString.h"
|
#include "../../../Common/MyString.h"
|
||||||
|
|
||||||
#include "../FileManager/MyCom2.h"
|
#include "../FileManager/MyCom2.h"
|
||||||
|
|||||||
@@ -8,11 +8,13 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include <ShlGuid.h>
|
#include <ShlGuid.h>
|
||||||
#include <OleCtl.h>
|
#include <OleCtl.h>
|
||||||
|
|
||||||
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
#include "../../../Common/ComTry.h"
|
#include "../../../Common/ComTry.h"
|
||||||
#include "../../../Common/StringConvert.h"
|
#include "../../../Common/StringConvert.h"
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
#include "../../../Common/StringConvert.h"
|
#include "../../../Common/StringConvert.h"
|
||||||
@@ -96,6 +98,7 @@ EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)
|
|||||||
class COpenArchiveCallback:
|
class COpenArchiveCallback:
|
||||||
public IArchiveOpenCallback,
|
public IArchiveOpenCallback,
|
||||||
public IArchiveOpenVolumeCallback,
|
public IArchiveOpenVolumeCallback,
|
||||||
|
public IArchiveOpenSetSubArchiveName,
|
||||||
public IProgress,
|
public IProgress,
|
||||||
public ICryptoGetTextPassword,
|
public ICryptoGetTextPassword,
|
||||||
public CMyUnknownImp
|
public CMyUnknownImp
|
||||||
@@ -109,6 +112,8 @@ class COpenArchiveCallback:
|
|||||||
bool _numBytesTotalDefined;
|
bool _numBytesTotalDefined;
|
||||||
|
|
||||||
NFind::CFileInfo _fileInfo;
|
NFind::CFileInfo _fileInfo;
|
||||||
|
bool _subArchiveMode;
|
||||||
|
UString _subArchiveName;
|
||||||
public:
|
public:
|
||||||
bool PasswordIsDefined;
|
bool PasswordIsDefined;
|
||||||
UString Password;
|
UString Password;
|
||||||
@@ -116,8 +121,9 @@ public:
|
|||||||
FString _folderPrefix;
|
FString _folderPrefix;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MY_UNKNOWN_IMP3(
|
MY_UNKNOWN_IMP4(
|
||||||
IArchiveOpenVolumeCallback,
|
IArchiveOpenVolumeCallback,
|
||||||
|
IArchiveOpenSetSubArchiveName,
|
||||||
IProgress,
|
IProgress,
|
||||||
ICryptoGetTextPassword
|
ICryptoGetTextPassword
|
||||||
)
|
)
|
||||||
@@ -134,13 +140,24 @@ public:
|
|||||||
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
|
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
|
||||||
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
|
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
|
||||||
|
|
||||||
|
STDMETHOD(SetSubArchiveName(const wchar_t *name))
|
||||||
|
{
|
||||||
|
_subArchiveMode = true;
|
||||||
|
_subArchiveName = name;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// ICryptoGetTextPassword
|
// ICryptoGetTextPassword
|
||||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||||
|
|
||||||
|
COpenArchiveCallback(): _subArchiveMode(false) {}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
PasswordIsDefined = false;
|
PasswordIsDefined = false;
|
||||||
|
|
||||||
|
_subArchiveMode = false;
|
||||||
|
|
||||||
_numFilesTotalDefined = false;
|
_numFilesTotalDefined = false;
|
||||||
_numBytesTotalDefined = false;
|
_numBytesTotalDefined = false;
|
||||||
|
|
||||||
@@ -220,6 +237,8 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
|
|||||||
{
|
{
|
||||||
if (WasEscPressed())
|
if (WasEscPressed())
|
||||||
return E_ABORT;
|
return E_ABORT;
|
||||||
|
if (_subArchiveMode)
|
||||||
|
return S_FALSE;
|
||||||
*inStream = NULL;
|
*inStream = NULL;
|
||||||
FString fullPath = _folderPrefix + us2fs(name);
|
FString fullPath = _folderPrefix + us2fs(name);
|
||||||
if (!_fileInfo.Find(fullPath))
|
if (!_fileInfo.Find(fullPath))
|
||||||
@@ -238,6 +257,14 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
|
|||||||
STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
|
STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||||
{
|
{
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
|
if (_subArchiveMode)
|
||||||
|
{
|
||||||
|
switch(propID)
|
||||||
|
{
|
||||||
|
case kpidName: prop = _subArchiveName; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
switch(propID)
|
switch(propID)
|
||||||
{
|
{
|
||||||
case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break;
|
case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace NMessageID {
|
namespace NMessageID {
|
||||||
|
|
||||||
const UINT k_Last_PropId_supported_by_plugin = kpidStreamId;
|
const unsigned k_Last_PropId_supported_by_plugin = kpidStreamId;
|
||||||
|
|
||||||
enum EEnum
|
enum EEnum
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
|
#include <commctrl.h>
|
||||||
|
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
#include "../../../Windows/CommonDialog.h"
|
#include "../../../Windows/CommonDialog.h"
|
||||||
#include "../../../Windows/Shell.h"
|
#include "../../../Windows/Shell.h"
|
||||||
@@ -106,7 +110,7 @@ class CBrowseDialog: public NControl::CModalDialog
|
|||||||
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
|
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
|
||||||
virtual void OnOK();
|
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);
|
bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);
|
||||||
// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
|
// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
|
||||||
@@ -295,7 +299,7 @@ bool CBrowseDialog::OnInit()
|
|||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
/* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,
|
/* 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. */
|
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
|
#endif
|
||||||
|
|
||||||
return CModalDialog::OnInit();
|
return CModalDialog::OnInit();
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include "../../../Common/MyInitGuid.h"
|
#include "../../../Common/MyInitGuid.h"
|
||||||
|
|
||||||
#include "../Agent/Agent.h"
|
#include "../Agent/Agent.h"
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
|
#include <shlwapi.h>
|
||||||
|
|
||||||
#include "../../../../C/Alloc.h"
|
#include "../../../../C/Alloc.h"
|
||||||
|
|
||||||
#include "../../../Common/IntToString.h"
|
#include "../../../Common/IntToString.h"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
#include <Winbase.h>
|
#include <Winbase.h>
|
||||||
|
|
||||||
#include "../../../Common/Defs.h"
|
#include "../../../Common/Defs.h"
|
||||||
@@ -585,7 +587,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
|||||||
|
|
||||||
CCopyState state;
|
CCopyState state;
|
||||||
state.ProgressInfo.TotalSize = stat.Size;
|
state.ProgressInfo.TotalSize = stat.Size;
|
||||||
state.ProgressInfo.TotalSize = stat.Size;
|
|
||||||
state.ProgressInfo.StartPos = 0;
|
state.ProgressInfo.StartPos = 0;
|
||||||
state.ProgressInfo.Progress = callback;
|
state.ProgressInfo.Progress = callback;
|
||||||
state.ProgressInfo.Init();
|
state.ProgressInfo.Init();
|
||||||
@@ -593,7 +594,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
|||||||
state.MoveMode = IntToBool(moveMode);
|
state.MoveMode = IntToBool(moveMode);
|
||||||
state.UseReadWriteMode = isAltDest;
|
state.UseReadWriteMode = isAltDest;
|
||||||
state.Prepare();
|
state.Prepare();
|
||||||
state.TotalSize = stat.Size;
|
|
||||||
|
|
||||||
for (UInt32 i = 0; i < numItems; i++)
|
for (UInt32 i = 0; i < numItems; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ static const UInt32 kLangIDs[] =
|
|||||||
|
|
||||||
static bool GetSymLink(CFSTR path, CReparseAttr &attr)
|
static bool GetSymLink(CFSTR path, CReparseAttr &attr)
|
||||||
{
|
{
|
||||||
NFile::NIO::CInFile file;
|
NIO::CInFile file;
|
||||||
if (!file.Open(path,
|
if (!file.Open(path,
|
||||||
FILE_SHARE_READ,
|
FILE_SHARE_READ,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
@@ -88,12 +88,13 @@ bool CLinkDialog::OnInit()
|
|||||||
LangSetWindowText(*this, IDD_LINK);
|
LangSetWindowText(*this, IDD_LINK);
|
||||||
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
|
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
|
_pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
|
||||||
_pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
|
_pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
|
||||||
|
|
||||||
if (!FilePath.IsEmpty())
|
if (!FilePath.IsEmpty())
|
||||||
{
|
{
|
||||||
NFile::NFind::CFileInfo fi;
|
NFind::CFileInfo fi;
|
||||||
int linkType = 0;
|
int linkType = 0;
|
||||||
if (!fi.Find(us2fs(FilePath)))
|
if (!fi.Find(us2fs(FilePath)))
|
||||||
linkType = IDR_LINK_TYPE_SYM_FILE;
|
linkType = IDR_LINK_TYPE_SYM_FILE;
|
||||||
@@ -219,7 +220,7 @@ void CLinkDialog::OnButton_SetPath(bool to)
|
|||||||
UString resultPath;
|
UString resultPath;
|
||||||
if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
|
if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
|
||||||
return;
|
return;
|
||||||
NFile::NName::NormalizeDirPathPrefix(resultPath);
|
NName::NormalizeDirPathPrefix(resultPath);
|
||||||
combo.SetCurSel(-1);
|
combo.SetCurSel(-1);
|
||||||
combo.SetText(resultPath);
|
combo.SetText(resultPath);
|
||||||
}
|
}
|
||||||
@@ -239,16 +240,23 @@ void CLinkDialog::OnButton_Link()
|
|||||||
UString from, to;
|
UString from, to;
|
||||||
_pathFromCombo.GetText(from);
|
_pathFromCombo.GetText(from);
|
||||||
_pathToCombo.GetText(to);
|
_pathToCombo.GetText(to);
|
||||||
int i;
|
|
||||||
for (i = 0; i < ARRAY_SIZE(k_LinkType_Buttons); i++)
|
if (from.IsEmpty())
|
||||||
if (IsButtonCheckedBool(k_LinkType_Buttons[i]))
|
|
||||||
break;
|
|
||||||
if (i >= ARRAY_SIZE(k_LinkType_Buttons))
|
|
||||||
return;
|
return;
|
||||||
|
if (!NName::IsAbsolutePath(from))
|
||||||
|
from.Insert(0, CurDirPrefix);
|
||||||
|
|
||||||
int idb = k_LinkType_Buttons[i];
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
NFile::NFind::CFileInfo info1, info2;
|
NFind::CFileInfo info1, info2;
|
||||||
bool finded1 = info1.Find(us2fs(from));
|
bool finded1 = info1.Find(us2fs(from));
|
||||||
bool finded2 = info2.Find(us2fs(to));
|
bool finded2 = info2.Find(us2fs(to));
|
||||||
|
|
||||||
@@ -259,14 +267,13 @@ void CLinkDialog::OnButton_Link()
|
|||||||
if (finded1 && info1.IsDir() != isDirLink ||
|
if (finded1 && info1.IsDir() != isDirLink ||
|
||||||
finded2 && info2.IsDir() != isDirLink)
|
finded2 && info2.IsDir() != isDirLink)
|
||||||
{
|
{
|
||||||
ShowError(L"Incorrect linkType");
|
ShowError(L"Incorrect link type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idb == IDR_LINK_TYPE_HARD)
|
if (idb == IDR_LINK_TYPE_HARD)
|
||||||
{
|
{
|
||||||
bool res = NFile::NDir::MyCreateHardLink(us2fs(from), us2fs(to));
|
if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to)))
|
||||||
if (!res)
|
|
||||||
{
|
{
|
||||||
ShowLastErrorMessage();
|
ShowLastErrorMessage();
|
||||||
return;
|
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();
|
ShowLastErrorMessage();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +329,8 @@ void CApp::Link()
|
|||||||
int index = indices[0];
|
int index = indices[0];
|
||||||
const UString itemName = srcPanel.GetItemName(index);
|
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;
|
UString path = srcPath;
|
||||||
{
|
{
|
||||||
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
|
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
|
||||||
@@ -332,6 +341,7 @@ void CApp::Link()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CLinkDialog dlg;
|
CLinkDialog dlg;
|
||||||
|
dlg.CurDirPrefix = fsPrefix;
|
||||||
dlg.FilePath = srcPath + itemName;
|
dlg.FilePath = srcPath + itemName;
|
||||||
dlg.AnotherPath = path;
|
dlg.AnotherPath = path;
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CLinkDialog: public NWindows::NControl::CModalDialog
|
|||||||
void ShowError(const wchar_t *s);
|
void ShowError(const wchar_t *s);
|
||||||
void Set_LinkType_Radio(int idb);
|
void Set_LinkType_Radio(int idb);
|
||||||
public:
|
public:
|
||||||
|
UString CurDirPrefix;
|
||||||
UString FilePath;
|
UString FilePath;
|
||||||
UString AnotherPath;
|
UString AnotherPath;
|
||||||
|
|
||||||
|
|||||||
@@ -795,7 +795,7 @@ void CPanel::Change_ShowNtfsStrems_Mode()
|
|||||||
void CPanel::Post_Refresh_StatusBar()
|
void CPanel::Post_Refresh_StatusBar()
|
||||||
{
|
{
|
||||||
if (_processStatusBar)
|
if (_processStatusBar)
|
||||||
PostMessage(kRefresh_StatusBar);
|
PostMsg(kRefresh_StatusBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPanel::AddToArchive()
|
void CPanel::AddToArchive()
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user