This commit is contained in:
DavidXanatos 2022-11-12 10:45:35 +01:00
parent c09dec5f61
commit 6e496381d8
56 changed files with 5237 additions and 8 deletions

View File

@ -6,6 +6,21 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [1.6.0 / 5.61.0] - 2022-??-??
### Added
- added ability to import/export boxes into 7z files
### Changed
- restructured the box context menu a bit
- sandman translations are now compressed and located in translations.7z
## [1.5.3 / 5.60.3] - 2022-11-??
### Added

View File

@ -0,0 +1,254 @@
/* Types.h -- Basic types
2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
#include <stddef.h>
#ifdef _WIN32
#include <windows.h>
#endif
#ifndef EXTERN_C_BEGIN
#ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif
#endif
EXTERN_C_BEGIN
#define SZ_OK 0
#define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17
typedef int SRes;
#ifdef _WIN32
typedef DWORD WRes;
#else
typedef int WRes;
#endif
#ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif
typedef unsigned char Byte;
typedef short Int16;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef long Int32;
typedef unsigned long UInt32;
#else
typedef int Int32;
typedef unsigned int UInt32;
#endif
#ifdef _SZ_NO_INT_64
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
NOTES: Some code will work incorrectly in that case! */
typedef long Int64;
typedef unsigned long UInt64;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n
#else
typedef long long int Int64;
typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL
#endif
#endif
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
typedef size_t SizeT;
#endif
typedef int Bool;
#define True 1
#define False 0
#ifdef _WIN32
#define MY_STD_CALL __stdcall
#else
#define MY_STD_CALL
#endif
#ifdef _MSC_VER
#if _MSC_VER >= 1300
#define MY_NO_INLINE __declspec(noinline)
#else
#define MY_NO_INLINE
#endif
#define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall
#else
#define MY_CDECL
#define MY_FAST_CALL
#endif
/* The following interfaces use first parameter as pointer to structure */
typedef struct
{
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn;
typedef struct
{
void (*Write)(void *p, Byte b);
} IByteOut;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
} ISeqInStream;
/* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
typedef struct
{
size_t (*Write)(void *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
} ISeqOutStream;
typedef enum
{
SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2
} ESzSeek;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ISeekInStream;
typedef struct
{
SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */
SRes (*Skip)(void *p, size_t offset);
/* offset must be <= output(*size) of Look */
SRes (*Read)(void *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ILookInStream;
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
#define LookToRead_BUF_SIZE (1 << 14)
typedef struct
{
ILookInStream s;
ISeekInStream *realStream;
size_t pos;
size_t size;
Byte buf[LookToRead_BUF_SIZE];
} CLookToRead;
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
void LookToRead_Init(CLookToRead *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p);
typedef struct
{
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress;
typedef struct
{
void *(*Alloc)(void *p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */
} ISzAlloc;
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\"
#else
#define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/"
#endif
EXTERN_C_END
#endif

View File

@ -0,0 +1,234 @@
// IArchive.h
#ifndef __IARCHIVE_H
#define __IARCHIVE_H
#include "../IProgress.h"
#include "../IStream.h"
#include "../PropID.h"
#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)
#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
namespace NFileTimeType
{
enum EEnum
{
kWindows,
kUnix,
kDOS
};
}
namespace NArchive
{
enum
{
kName = 0,
kClassID,
kExtension,
kAddExtension,
kUpdate,
kKeepName,
kStartSignature,
kFinishSignature,
kAssociate
};
namespace NExtract
{
namespace NAskMode
{
enum
{
kExtract = 0,
kTest,
kSkip
};
}
namespace NOperationResult
{
enum
{
kOK = 0,
kUnSupportedMethod,
kDataError,
kCRCError
};
}
}
namespace NUpdate
{
namespace NOperationResult
{
enum
{
kOK = 0,
kError
};
}
}
}
#define INTERFACE_IArchiveOpenCallback(x) \
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \
ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
{
INTERFACE_IArchiveOpenCallback(PURE);
};
#define INTERFACE_IArchiveExtractCallback(x) \
INTERFACE_IProgress(x) \
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \
STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
{
INTERFACE_IArchiveExtractCallback(PURE)
};
#define INTERFACE_IArchiveOpenVolumeCallback(x) \
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \
ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
{
INTERFACE_IArchiveOpenVolumeCallback(PURE);
};
ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
{
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
};
ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
{
STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
};
/*
IInArchive::Extract:
indices must be sorted
numItems = 0xFFFFFFFF means "all files"
testMode != 0 means "test files without writing to outStream"
*/
#define INTERFACE_IInArchive(x) \
STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(Close)() x; \
STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;
ARCHIVE_INTERFACE(IInArchive, 0x60)
{
INTERFACE_IInArchive(PURE)
};
ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61)
{
STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;
};
#define INTERFACE_IArchiveUpdateCallback(x) \
INTERFACE_IProgress(x); \
STDMETHOD(GetUpdateItemInfo)(UInt32 index, \
Int32 *newData, /*1 - new data, 0 - old data */ \
Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \
UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \
) x; \
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
STDMETHOD(SetOperationResult)(Int32 operationResult) x; \
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
{
INTERFACE_IArchiveUpdateCallback(PURE);
};
#define INTERFACE_IArchiveUpdateCallback2(x) \
INTERFACE_IArchiveUpdateCallback(x) \
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
{
INTERFACE_IArchiveUpdateCallback2(PURE);
};
#define INTERFACE_IOutArchive(x) \
STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
STDMETHOD(GetFileTimeType)(UInt32 *type) x;
ARCHIVE_INTERFACE(IOutArchive, 0xA0)
{
INTERFACE_IOutArchive(PURE)
};
ARCHIVE_INTERFACE(ISetProperties, 0x03)
{
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;
};
#define IMP_IInArchive_GetProp(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
const STATPROPSTG &srcItem = k[index]; \
*propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \
#define IMP_IInArchive_GetProp_WITH_NAME(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
const STATPROPSTG &srcItem = k[index]; \
*propID = srcItem.propid; *varType = srcItem.vt; \
if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \
#define IMP_IInArchive_Props \
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
{ *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)
#define IMP_IInArchive_Props_WITH_NAME \
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
{ *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)
#define IMP_IInArchive_ArcProps \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
{ *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)
#define IMP_IInArchive_ArcProps_WITH_NAME \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
{ *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps)
#define IMP_IInArchive_ArcProps_NO_Table \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
{ *numProperties = 0; return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \
{ return E_NOTIMPL; } \
#define IMP_IInArchive_ArcProps_NO \
IMP_IInArchive_ArcProps_NO_Table \
STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \
{ value->vt = VT_EMPTY; return S_OK; }
#endif

View File

@ -0,0 +1,186 @@
// ICoder.h
#ifndef __ICODER_H
#define __ICODER_H
#include "IStream.h"
#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x)
CODER_INTERFACE(ICompressProgressInfo, 0x04)
{
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;
};
CODER_INTERFACE(ICompressCoder, 0x05)
{
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress) PURE;
};
CODER_INTERFACE(ICompressCoder2, 0x18)
{
STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress) PURE;
};
namespace NCoderPropID
{
enum EEnum
{
kDefaultProp = 0,
kDictionarySize,
kUsedMemorySize,
kOrder,
kBlockSize,
kPosStateBits,
kLitContextBits,
kLitPosBits,
kNumFastBytes,
kMatchFinder,
kMatchFinderCycles,
kNumPasses,
kAlgorithm,
kNumThreads,
kEndMarker
};
}
CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
{
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
};
/*
CODER_INTERFACE(ICompressSetCoderProperties, 0x21)
{
STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;
};
*/
CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)
{
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;
};
CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)
{
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE;
};
CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)
{
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;
};
CODER_INTERFACE(ICompressSetCoderMt, 0x25)
{
STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;
};
CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)
{
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;
};
CODER_INTERFACE(ICompressSetInStream, 0x31)
{
STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;
STDMETHOD(ReleaseInStream)() PURE;
};
CODER_INTERFACE(ICompressSetOutStream, 0x32)
{
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;
STDMETHOD(ReleaseOutStream)() PURE;
};
CODER_INTERFACE(ICompressSetInStreamSize, 0x33)
{
STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;
};
CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
{
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;
};
CODER_INTERFACE(ICompressSetBufSize, 0x35)
{
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE;
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE;
};
CODER_INTERFACE(ICompressFilter, 0x40)
{
STDMETHOD(Init)() PURE;
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;
// Filter converts as most as possible bytes
// Filter return outSize (UInt32)
// if (outSize <= size): Filter have converted outSize bytes
// if (outSize > size): Filter have not converted anything.
// and it needs at least outSize bytes to convert one block
// (it's for crypto block algorithms).
};
CODER_INTERFACE(ICompressCodecsInfo, 0x60)
{
STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE;
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE;
STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE;
};
CODER_INTERFACE(ISetCompressCodecsInfo, 0x61)
{
STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE;
};
CODER_INTERFACE(ICryptoProperties, 0x80)
{
STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;
STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;
};
/*
CODER_INTERFACE(ICryptoResetSalt, 0x88)
{
STDMETHOD(ResetSalt)() PURE;
};
*/
CODER_INTERFACE(ICryptoResetInitVector, 0x8C)
{
STDMETHOD(ResetInitVector)() PURE;
};
CODER_INTERFACE(ICryptoSetPassword, 0x90)
{
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;
};
CODER_INTERFACE(ICryptoSetCRC, 0xA0)
{
STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;
};
//////////////////////
// It's for DLL file
namespace NMethodPropID
{
enum EEnum
{
kID,
kName,
kDecoder,
kEncoder,
kInStreams,
kOutStreams,
kDescription,
kDecoderIsAssigned,
kEncoderIsAssigned
};
}
#endif

View File

@ -0,0 +1,15 @@
// IDecl.h
#ifndef __IDECL_H
#define __IDECL_H
#include "../Common/MyUnknown.h"
#define DECL_INTERFACE_SUB(i, base, groupId, subId) \
DEFINE_GUID(IID_ ## i, \
0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \
struct i: public base
#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId)
#endif

View File

@ -0,0 +1,24 @@
// IPassword.h
#ifndef __IPASSWORD_H
#define __IPASSWORD_H
#include "../Common/MyUnknown.h"
#include "../Common/Types.h"
#include "IDecl.h"
#define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x)
PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10)
{
STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;
};
PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11)
{
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;
};
#endif

View File

@ -0,0 +1,33 @@
// Interface/IProgress.h
#ifndef __IPROGRESS_H
#define __IPROGRESS_H
#include "../Common/MyUnknown.h"
#include "../Common/Types.h"
#include "IDecl.h"
#define INTERFACE_IProgress(x) \
STDMETHOD(SetTotal)(UInt64 total) x; \
STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
DECL_INTERFACE(IProgress, 0, 5)
{
INTERFACE_IProgress(PURE)
};
/*
// {23170F69-40C1-278A-0000-000000050002}
DEFINE_GUID(IID_IProgress2,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002")
IProgress2: public IUnknown
{
public:
STDMETHOD(SetTotal)(const UInt64 *total) PURE;
STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE;
};
*/
#endif

View File

@ -0,0 +1,58 @@
// IStream.h
#ifndef __ISTREAM_H
#define __ISTREAM_H
#include "../Common/MyUnknown.h"
#include "../Common/Types.h"
#include "IDecl.h"
#define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x)
#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)
STREAM_INTERFACE(ISequentialInStream, 0x01)
{
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
/*
Out: if size != 0, return_value = S_OK and (*processedSize == 0),
then there are no more bytes in stream.
if (size > 0) && there are bytes in stream,
this function must read at least 1 byte.
This function is allowed to read less than number of remaining bytes in stream.
You must call Read function in loop, if you need exact amount of data
*/
};
STREAM_INTERFACE(ISequentialOutStream, 0x02)
{
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
/*
if (size > 0) this function must write at least 1 byte.
This function is allowed to write less than "size".
You must call Write function in loop, if you need to write exact amount of data
*/
};
STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)
{
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
};
STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)
{
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
STDMETHOD(SetSize)(UInt64 newSize) PURE;
};
STREAM_INTERFACE(IStreamGetSize, 0x06)
{
STDMETHOD(GetSize)(UInt64 *size) PURE;
};
STREAM_INTERFACE(IOutStreamFlush, 0x07)
{
STDMETHOD(Flush)() PURE;
};
#endif

View File

@ -0,0 +1,76 @@
// PropID.h
#ifndef __7ZIP_PROPID_H
#define __7ZIP_PROPID_H
enum
{
kpidNoProperty = 0,
kpidMainSubfile = 1,
kpidHandlerItemIndex = 2,
kpidPath,
kpidName,
kpidExtension,
kpidIsDir,
kpidSize,
kpidPackSize,
kpidAttrib,
kpidCTime,
kpidATime,
kpidMTime,
kpidSolid,
kpidCommented,
kpidEncrypted,
kpidSplitBefore,
kpidSplitAfter,
kpidDictionarySize,
kpidCRC,
kpidType,
kpidIsAnti,
kpidMethod,
kpidHostOS,
kpidFileSystem,
kpidUser,
kpidGroup,
kpidBlock,
kpidComment,
kpidPosition,
kpidPrefix,
kpidNumSubDirs,
kpidNumSubFiles,
kpidUnpackVer,
kpidVolume,
kpidIsVolume,
kpidOffset,
kpidLinks,
kpidNumBlocks,
kpidNumVolumes,
kpidTimeType,
kpidBit64,
kpidBigEndian,
kpidCpu,
kpidPhySize,
kpidHeadersSize,
kpidChecksum,
kpidCharacts,
kpidVa,
kpidId,
kpidShortName,
kpidCreatorApp,
kpidSectorSize,
kpidPosixAttrib,
kpidLink,
kpidError,
kpidTotalSize = 0x1100,
kpidFreeSpace,
kpidClusterSize,
kpidVolumeName,
kpidLocalName = 0x1200,
kpidProvider,
kpidUserDefined = 0x10000
};
#endif

View File

@ -0,0 +1,20 @@
// Common/Defs.h
#ifndef __COMMON_DEFS_H
#define __COMMON_DEFS_H
template <class T> inline T MyMin(T a, T b)
{ return a < b ? a : b; }
template <class T> inline T MyMax(T a, T b)
{ return a > b ? a : b; }
template <class T> inline int MyCompare(T a, T b)
{ return a < b ? -1 : (a == b ? 0 : 1); }
inline int BoolToInt(bool value)
{ return (value ? 1: 0); }
inline bool IntToBool(int value)
{ return (value != 0); }
#endif

View File

@ -0,0 +1,225 @@
// MyCom.h
#ifndef __MYCOM_H
#define __MYCOM_H
#include "MyWindows.h"
#ifndef RINOK
#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }
#endif
template <class T>
class CMyComPtr
{
T* _p;
public:
// typedef T _PtrClass;
CMyComPtr() { _p = NULL;}
CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }
CMyComPtr(const CMyComPtr<T>& lp)
{
if ((_p = lp._p) != NULL)
_p->AddRef();
}
~CMyComPtr() { if (_p) _p->Release(); }
void Release() { if (_p) { _p->Release(); _p = NULL; } }
operator T*() const { return (T*)_p; }
// T& operator*() const { return *_p; }
T** operator&() { return &_p; }
T* operator->() const { return _p; }
T* operator=(T* p)
{
if (p != 0)
p->AddRef();
if (_p)
_p->Release();
_p = p;
return p;
}
T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
bool operator!() const { return (_p == NULL); }
// bool operator==(T* pT) const { return _p == pT; }
// Compare two objects for equivalence
void Attach(T* p2)
{
Release();
_p = p2;
}
T* Detach()
{
T* pt = _p;
_p = NULL;
return pt;
}
#ifdef _WIN32
HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
{
return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
}
#endif
/*
HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
{
CLSID clsid;
HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
ATLASSERT(_p == NULL);
if (SUCCEEDED(hr))
hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
return hr;
}
*/
template <class Q>
HRESULT QueryInterface(REFGUID iid, Q** pp) const
{
return _p->QueryInterface(iid, (void**)pp);
}
};
//////////////////////////////////////////////////////////
inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
{
*bstr = ::SysAllocString(src);
return (*bstr != 0) ? S_OK : E_OUTOFMEMORY;
}
class CMyComBSTR
{
public:
BSTR m_str;
CMyComBSTR(): m_str(NULL) {}
CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
// CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
// CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }
CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
/*
CMyComBSTR(REFGUID src)
{
LPOLESTR szGuid;
StringFromCLSID(src, &szGuid);
m_str = ::SysAllocString(szGuid);
CoTaskMemFree(szGuid);
}
*/
~CMyComBSTR() { ::SysFreeString(m_str); }
CMyComBSTR& operator=(const CMyComBSTR& src)
{
if (m_str != src.m_str)
{
if (m_str)
::SysFreeString(m_str);
m_str = src.MyCopy();
}
return *this;
}
CMyComBSTR& operator=(LPCOLESTR src)
{
::SysFreeString(m_str);
m_str = ::SysAllocString(src);
return *this;
}
unsigned int Length() const { return ::SysStringLen(m_str); }
operator BSTR() const { return m_str; }
BSTR* operator&() { return &m_str; }
BSTR MyCopy() const
{
int byteLen = ::SysStringByteLen(m_str);
BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
memcpy(res, m_str, byteLen);
return res;
}
/*
void Attach(BSTR src) { m_str = src; }
BSTR Detach()
{
BSTR s = m_str;
m_str = NULL;
return s;
}
*/
void Empty()
{
::SysFreeString(m_str);
m_str = NULL;
}
bool operator!() const { return (m_str == NULL); }
};
//////////////////////////////////////////////////////////
class CMyUnknownImp
{
public:
ULONG __m_RefCount;
CMyUnknownImp(): __m_RefCount(0) {}
};
#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
(REFGUID iid, void **outObject) {
#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \
{ *outObject = (void *)(i *)this; AddRef(); return S_OK; }
#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \
{ *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; }
#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
MY_QUERYINTERFACE_ENTRY(i)
#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }
#define MY_ADDREF_RELEASE \
STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \
STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \
return __m_RefCount; delete this; return 0; }
#define MY_UNKNOWN_IMP_SPEC(i) \
MY_QUERYINTERFACE_BEGIN \
i \
MY_QUERYINTERFACE_END \
MY_ADDREF_RELEASE
#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \
MY_QUERYINTERFACE_END \
MY_ADDREF_RELEASE
#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
MY_QUERYINTERFACE_ENTRY(i) \
)
#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
MY_QUERYINTERFACE_ENTRY(i1) \
MY_QUERYINTERFACE_ENTRY(i2) \
)
#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
MY_QUERYINTERFACE_ENTRY(i1) \
MY_QUERYINTERFACE_ENTRY(i2) \
MY_QUERYINTERFACE_ENTRY(i3) \
)
#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
MY_QUERYINTERFACE_ENTRY(i1) \
MY_QUERYINTERFACE_ENTRY(i2) \
MY_QUERYINTERFACE_ENTRY(i3) \
MY_QUERYINTERFACE_ENTRY(i4) \
)
#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
MY_QUERYINTERFACE_ENTRY(i1) \
MY_QUERYINTERFACE_ENTRY(i2) \
MY_QUERYINTERFACE_ENTRY(i3) \
MY_QUERYINTERFACE_ENTRY(i4) \
MY_QUERYINTERFACE_ENTRY(i5) \
)
#endif

View File

@ -0,0 +1,22 @@
// Common/MyInitGuid.h
#ifndef __COMMON_MY_INITGUID_H
#define __COMMON_MY_INITGUID_H
#ifdef _WIN32
#ifdef UNDER_CE
#include <basetyps.h>
#endif
#include <initguid.h>
#ifdef UNDER_CE
DEFINE_GUID(IID_IUnknown,
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
#endif
#else
#define INITGUID
#include "MyGuidDef.h"
DEFINE_GUID(IID_IUnknown,
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
#endif
#endif

View File

@ -0,0 +1,13 @@
// MyUnknown.h
#ifndef __MY_UNKNOWN_H
#define __MY_UNKNOWN_H
#ifdef _WIN32
#include <basetyps.h>
#include <unknwn.h>
#else
#include "MyWindows.h"
#endif
#endif

View File

@ -0,0 +1,109 @@
// MyWindows.cpp
#include "StdAfx.h"
#ifndef _WIN32
#include "MyWindows.h"
#include "Types.h"
#include <malloc.h>
static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); }
static inline void FreeForBSTR(void *pv) { ::free(pv);}
static UINT MyStringLen(const wchar_t *s)
{
UINT i;
for (i = 0; s[i] != '\0'; i++);
return i;
}
BSTR SysAllocStringByteLen(LPCSTR psz, UINT len)
{
int realLen = len + sizeof(UINT) + sizeof(OLECHAR) + sizeof(OLECHAR);
void *p = AllocateForBSTR(realLen);
if (p == 0)
return 0;
*(UINT *)p = len;
BSTR bstr = (BSTR)((UINT *)p + 1);
memmove(bstr, psz, len);
Byte *pb = ((Byte *)bstr) + len;
for (int i = 0; i < sizeof(OLECHAR) * 2; i++)
pb[i] = 0;
return bstr;
}
BSTR SysAllocString(const OLECHAR *sz)
{
if (sz == 0)
return 0;
UINT strLen = MyStringLen(sz);
UINT len = (strLen + 1) * sizeof(OLECHAR);
void *p = AllocateForBSTR(len + sizeof(UINT));
if (p == 0)
return 0;
*(UINT *)p = strLen;
BSTR bstr = (BSTR)((UINT *)p + 1);
memmove(bstr, sz, len);
return bstr;
}
void SysFreeString(BSTR bstr)
{
if (bstr != 0)
FreeForBSTR((UINT *)bstr - 1);
}
UINT SysStringByteLen(BSTR bstr)
{
if (bstr == 0)
return 0;
return *((UINT *)bstr - 1);
}
UINT SysStringLen(BSTR bstr)
{
return SysStringByteLen(bstr) / sizeof(OLECHAR);
}
HRESULT VariantClear(VARIANTARG *prop)
{
if (prop->vt == VT_BSTR)
SysFreeString(prop->bstrVal);
prop->vt = VT_EMPTY;
return S_OK;
}
HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src)
{
HRESULT res = ::VariantClear(dest);
if (res != S_OK)
return res;
if (src->vt == VT_BSTR)
{
dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal,
SysStringByteLen(src->bstrVal));
if (dest->bstrVal == 0)
return E_OUTOFMEMORY;
dest->vt = VT_BSTR;
}
else
*dest = *src;
return S_OK;
}
LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2)
{
if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1;
if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1;
if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1;
if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1;
return 0;
}
DWORD GetLastError()
{
return 0;
}
#endif

View File

@ -0,0 +1,204 @@
// MyWindows.h
#ifndef __MYWINDOWS_H
#define __MYWINDOWS_H
#ifdef _WIN32
#include <windows.h>
#else
#include <stddef.h> // for wchar_t
#include <string.h>
#include "MyGuidDef.h"
typedef char CHAR;
typedef unsigned char UCHAR;
#undef BYTE
typedef unsigned char BYTE;
typedef short SHORT;
typedef unsigned short USHORT;
#undef WORD
typedef unsigned short WORD;
typedef short VARIANT_BOOL;
typedef int INT;
typedef Int32 INT32;
typedef unsigned int UINT;
typedef UInt32 UINT32;
typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit
typedef UINT32 ULONG;
#undef DWORD
typedef UINT32 DWORD;
typedef Int64 LONGLONG;
typedef UInt64 ULONGLONG;
typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;
typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;
typedef const CHAR *LPCSTR;
typedef CHAR TCHAR;
typedef const TCHAR *LPCTSTR;
typedef wchar_t WCHAR;
typedef WCHAR OLECHAR;
typedef const WCHAR *LPCWSTR;
typedef OLECHAR *BSTR;
typedef const OLECHAR *LPCOLESTR;
typedef OLECHAR *LPOLESTR;
typedef struct _FILETIME
{
DWORD dwLowDateTime;
DWORD dwHighDateTime;
}FILETIME;
#define HRESULT LONG
#define FAILED(Status) ((HRESULT)(Status)<0)
typedef ULONG PROPID;
typedef LONG SCODE;
#define S_OK ((HRESULT)0x00000000L)
#define S_FALSE ((HRESULT)0x00000001L)
#define E_NOTIMPL ((HRESULT)0x80004001L)
#define E_NOINTERFACE ((HRESULT)0x80004002L)
#define E_ABORT ((HRESULT)0x80004004L)
#define E_FAIL ((HRESULT)0x80004005L)
#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)
#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)
#define E_INVALIDARG ((HRESULT)0x80070057L)
#ifdef _MSC_VER
#define STDMETHODCALLTYPE __stdcall
#else
#define STDMETHODCALLTYPE
#endif
#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f
#define STDMETHOD(f) STDMETHOD_(HRESULT, f)
#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
#define STDMETHODIMP STDMETHODIMP_(HRESULT)
#define PURE = 0
#define MIDL_INTERFACE(x) struct
#ifdef __cplusplus
DEFINE_GUID(IID_IUnknown,
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
struct IUnknown
{
STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;
STDMETHOD_(ULONG, AddRef)() PURE;
STDMETHOD_(ULONG, Release)() PURE;
#ifndef _WIN32
virtual ~IUnknown() {}
#endif
};
typedef IUnknown *LPUNKNOWN;
#endif
#define VARIANT_TRUE ((VARIANT_BOOL)-1)
#define VARIANT_FALSE ((VARIANT_BOOL)0)
enum VARENUM
{
VT_EMPTY = 0,
VT_NULL = 1,
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_VARIANT = 12,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_VOID = 24,
VT_HRESULT = 25,
VT_FILETIME = 64
};
typedef unsigned short VARTYPE;
typedef WORD PROPVAR_PAD1;
typedef WORD PROPVAR_PAD2;
typedef WORD PROPVAR_PAD3;
#ifdef __cplusplus
typedef struct tagPROPVARIANT
{
VARTYPE vt;
PROPVAR_PAD1 wReserved1;
PROPVAR_PAD2 wReserved2;
PROPVAR_PAD3 wReserved3;
union
{
CHAR cVal;
UCHAR bVal;
SHORT iVal;
USHORT uiVal;
LONG lVal;
ULONG ulVal;
INT intVal;
UINT uintVal;
LARGE_INTEGER hVal;
ULARGE_INTEGER uhVal;
VARIANT_BOOL boolVal;
SCODE scode;
FILETIME filetime;
BSTR bstrVal;
};
} PROPVARIANT;
typedef PROPVARIANT tagVARIANT;
typedef tagVARIANT VARIANT;
typedef VARIANT VARIANTARG;
MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);
MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);
#endif
MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);
MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);
MY_EXTERN_C void SysFreeString(BSTR bstr);
MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);
MY_EXTERN_C UINT SysStringLen(BSTR bstr);
MY_EXTERN_C DWORD GetLastError();
MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);
#define CP_ACP 0
#define CP_OEMCP 1
typedef enum tagSTREAM_SEEK
{
STREAM_SEEK_SET = 0,
STREAM_SEEK_CUR = 1,
STREAM_SEEK_END = 2
} STREAM_SEEK;
#endif
#endif

View File

@ -0,0 +1,116 @@
// NewHandler.cpp
#include "StdAfx.h"
#include <stdlib.h>
#include "NewHandler.h"
// #define DEBUG_MEMORY_LEAK
#ifndef DEBUG_MEMORY_LEAK
#ifdef _WIN32
void *
#ifdef _MSC_VER
__cdecl
#endif
operator new(size_t size)
{
// void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
void *p = ::malloc(size);
if (p == 0)
throw CNewException();
return p;
}
void
#ifdef _MSC_VER
__cdecl
#endif
operator delete(void *p) throw()
{
/*
if (p == 0)
return;
::HeapFree(::GetProcessHeap(), 0, p);
*/
::free(p);
}
#endif
#else
#pragma init_seg(lib)
const int kDebugSize = 1000000;
static void *a[kDebugSize];
static int index = 0;
static int numAllocs = 0;
void * __cdecl operator new(size_t size)
{
numAllocs++;
void *p = HeapAlloc(GetProcessHeap(), 0, size);
if (index == 40)
{
int t = 1;
}
if (index < kDebugSize)
{
a[index] = p;
index++;
}
if (p == 0)
throw CNewException();
printf("Alloc %6d, size = %8d\n", numAllocs, size);
return p;
}
class CC
{
public:
CC()
{
for (int i = 0; i < kDebugSize; i++)
a[i] = 0;
}
~CC()
{
for (int i = 0; i < kDebugSize; i++)
if (a[i] != 0)
return;
}
} g_CC;
void __cdecl operator delete(void *p)
{
if (p == 0)
return;
/*
for (int i = 0; i < index; i++)
if (a[i] == p)
a[i] = 0;
*/
HeapFree(GetProcessHeap(), 0, p);
numAllocs--;
printf("Free %d\n", numAllocs);
}
#endif
/*
int MemErrorVC(size_t)
{
throw CNewException();
// return 1;
}
CNewHandlerSetter::CNewHandlerSetter()
{
// MemErrorOldVCFunction = _set_new_handler(MemErrorVC);
}
CNewHandlerSetter::~CNewHandlerSetter()
{
// _set_new_handler(MemErrorOldVCFunction);
}
*/

View File

@ -0,0 +1,16 @@
// Common/NewHandler.h
#ifndef __COMMON_NEWHANDLER_H
#define __COMMON_NEWHANDLER_H
class CNewException {};
#ifdef _WIN32
void
#ifdef _MSC_VER
__cdecl
#endif
operator delete(void *p) throw();
#endif
#endif

View File

@ -0,0 +1,11 @@
// Common/Types.h
#ifndef __COMMON_TYPES_H
#define __COMMON_TYPES_H
#include "../../C/Types.h"
typedef int HRes;
#endif

View File

@ -0,0 +1,17 @@
// Windows/Defs.h
#ifndef __WINDOWS_DEFS_H
#define __WINDOWS_DEFS_H
#include "../Common/MyWindows.h"
#ifdef _WIN32
inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); }
inline bool BOOLToBool(BOOL v) { return (v != FALSE); }
inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); }
#endif
inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); }
inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); }
#endif

View File

@ -0,0 +1,243 @@
// Windows/PropVariant.cpp
#include "StdAfx.h"
#include "PropVariant.h"
#include "../Common/Defs.h"
namespace NWindows {
namespace NCOM {
CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
{
vt = VT_EMPTY;
InternalCopy(&varSrc);
}
CPropVariant::CPropVariant(const CPropVariant &varSrc)
{
vt = VT_EMPTY;
InternalCopy(&varSrc);
}
CPropVariant::CPropVariant(BSTR bstrSrc)
{
vt = VT_EMPTY;
*this = bstrSrc;
}
CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
{
vt = VT_EMPTY;
*this = lpszSrc;
}
CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
{
InternalCopy(&varSrc);
return *this;
}
CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
{
InternalCopy(&varSrc);
return *this;
}
CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
{
*this = (LPCOLESTR)bstrSrc;
return *this;
}
static const char *kMemException = "out of memory";
CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
{
InternalClear();
vt = VT_BSTR;
wReserved1 = 0;
bstrVal = ::SysAllocString(lpszSrc);
if (bstrVal == NULL && lpszSrc != NULL)
{
throw kMemException;
// vt = VT_ERROR;
// scode = E_OUTOFMEMORY;
}
return *this;
}
CPropVariant& CPropVariant::operator=(const char *s)
{
InternalClear();
vt = VT_BSTR;
wReserved1 = 0;
UINT len = (UINT)strlen(s);
bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR));
if (bstrVal == NULL)
{
throw kMemException;
// vt = VT_ERROR;
// scode = E_OUTOFMEMORY;
}
else
{
for (UINT i = 0; i <= len; i++)
bstrVal[i] = s[i];
}
return *this;
}
CPropVariant& CPropVariant::operator=(bool bSrc)
{
if (vt != VT_BOOL)
{
InternalClear();
vt = VT_BOOL;
}
boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
return *this;
}
#define SET_PROP_FUNC(type, id, dest) \
CPropVariant& CPropVariant::operator=(type value) \
{ if (vt != id) { InternalClear(); vt = id; } \
dest = value; return *this; }
SET_PROP_FUNC(Byte, VT_UI1, bVal)
SET_PROP_FUNC(Int16, VT_I2, iVal)
SET_PROP_FUNC(Int32, VT_I4, lVal)
SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
static HRESULT MyPropVariantClear(PROPVARIANT *prop)
{
switch(prop->vt)
{
case VT_UI1:
case VT_I1:
case VT_I2:
case VT_UI2:
case VT_BOOL:
case VT_I4:
case VT_UI4:
case VT_R4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
case VT_FILETIME:
case VT_UI8:
case VT_R8:
case VT_CY:
case VT_DATE:
prop->vt = VT_EMPTY;
prop->wReserved1 = 0;
return S_OK;
}
return ::VariantClear((VARIANTARG *)prop);
}
HRESULT CPropVariant::Clear()
{
return MyPropVariantClear(this);
}
HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc)
{
::VariantClear((tagVARIANT *)this);
switch(pSrc->vt)
{
case VT_UI1:
case VT_I1:
case VT_I2:
case VT_UI2:
case VT_BOOL:
case VT_I4:
case VT_UI4:
case VT_R4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
case VT_FILETIME:
case VT_UI8:
case VT_R8:
case VT_CY:
case VT_DATE:
memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
return S_OK;
}
return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
}
HRESULT CPropVariant::Attach(PROPVARIANT *pSrc)
{
HRESULT hr = Clear();
if (FAILED(hr))
return hr;
memcpy(this, pSrc, sizeof(PROPVARIANT));
pSrc->vt = VT_EMPTY;
return S_OK;
}
HRESULT CPropVariant::Detach(PROPVARIANT *pDest)
{
HRESULT hr = MyPropVariantClear(pDest);
if (FAILED(hr))
return hr;
memcpy(pDest, this, sizeof(PROPVARIANT));
vt = VT_EMPTY;
return S_OK;
}
HRESULT CPropVariant::InternalClear()
{
HRESULT hr = Clear();
if (FAILED(hr))
{
vt = VT_ERROR;
scode = hr;
}
return hr;
}
void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
{
HRESULT hr = Copy(pSrc);
if (FAILED(hr))
{
if (hr == E_OUTOFMEMORY)
throw kMemException;
vt = VT_ERROR;
scode = hr;
}
}
int CPropVariant::Compare(const CPropVariant &a)
{
if (vt != a.vt)
return MyCompare(vt, a.vt);
switch (vt)
{
case VT_EMPTY: return 0;
// case VT_I1: return MyCompare(cVal, a.cVal);
case VT_UI1: return MyCompare(bVal, a.bVal);
case VT_I2: return MyCompare(iVal, a.iVal);
case VT_UI2: return MyCompare(uiVal, a.uiVal);
case VT_I4: return MyCompare(lVal, a.lVal);
case VT_UI4: return MyCompare(ulVal, a.ulVal);
// case VT_UINT: return MyCompare(uintVal, a.uintVal);
case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);
case VT_BSTR:
return 0; // Not implemented
// return MyCompare(aPropVarint.cVal);
default: return 0;
}
}
}}

View File

@ -0,0 +1,56 @@
// Windows/PropVariant.h
#ifndef __WINDOWS_PROPVARIANT_H
#define __WINDOWS_PROPVARIANT_H
#include "../Common/MyWindows.h"
#include "../Common/Types.h"
namespace NWindows {
namespace NCOM {
class CPropVariant : public tagPROPVARIANT
{
public:
CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; }
~CPropVariant() { Clear(); }
CPropVariant(const PROPVARIANT &varSrc);
CPropVariant(const CPropVariant &varSrc);
CPropVariant(BSTR bstrSrc);
CPropVariant(LPCOLESTR lpszSrc);
CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); };
CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }
CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; }
CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; }
CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }
CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; }
CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }
CPropVariant& operator=(const CPropVariant &varSrc);
CPropVariant& operator=(const PROPVARIANT &varSrc);
CPropVariant& operator=(BSTR bstrSrc);
CPropVariant& operator=(LPCOLESTR lpszSrc);
CPropVariant& operator=(const char *s);
CPropVariant& operator=(bool bSrc);
CPropVariant& operator=(Byte value);
CPropVariant& operator=(Int16 value);
CPropVariant& operator=(Int32 value);
CPropVariant& operator=(UInt32 value);
CPropVariant& operator=(Int64 value);
CPropVariant& operator=(UInt64 value);
CPropVariant& operator=(const FILETIME &value);
HRESULT Clear();
HRESULT Copy(const PROPVARIANT *pSrc);
HRESULT Attach(PROPVARIANT *pSrc);
HRESULT Detach(PROPVARIANT *pDest);
HRESULT InternalClear();
void InternalCopy(const PROPVARIANT *pSrc);
int Compare(const CPropVariant &a1);
};
}}
#endif

View File

@ -0,0 +1,9 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../Common/MyWindows.h"
#include "../Common/NewHandler.h"
#endif

View File

@ -0,0 +1,503 @@
#include "stdafx.h"
#include "ArchiveHelper.h"
#include "Archive.h"
#include "ArchiveInterface.h"
#include "ArchiveOpener.h"
#include "ArchiveExtractor.h"
#include "ArchiveUpdater.h"
#include "SplitFile.h"
#ifdef USE_7Z
CArchiveInterface theArc;
struct CArchive::SArchive
{
SArchive(CMyComPtr<IInArchive> &InArchive) {In = InArchive;}
~SArchive() {In->Close();}
CMyComPtr<IInArchive> In;
};
CArchive::CArchive(const QString &ArchivePath, QIODevice* pDevice)
{
Init();
m_pDevice = pDevice;
m_ArchivePath = ArchivePath;
m_Archive = NULL;
m_PartSize = -1;
m_PasswordUsed = false;
}
void CArchive::Init()
{
if(!theArc.IsOperational())
theArc.Init();
}
bool CArchive::IsInit()
{
return theArc.IsOperational();
}
CArchive::~CArchive()
{
Close();
}
int CArchive::Open()
{
if(!theArc.IsOperational())
{
LogError("Couldnt open interface");
return 0; // failed
}
if(m_Archive)
{
LogError("archive is already open");
return 0; // failes
}
if(!m_pDevice && !QFile::exists(m_ArchivePath))
{
LogError("archive does not exist");
return 0; // failed
}
SArcInfo Info = GetArcInfo(m_ArchivePath);
if(Info.FormatIndex == 0)
return -1; // unsupported format
for (int i = 0; i <= theArc.GetFormatCount(); i++)
{
CMyComPtr<IInArchive> InArchive;
if(!theArc.CreateInArchive(i ? i : Info.FormatIndex, InArchive)) // First try the most likely one and than try everyone else
break;
if (!InArchive)
continue;
// Open Archive
const UInt64 kMaxCheckStartPosition = 1 << 22; // 4MB
CMyComPtr<IArchiveOpenCallback> callback(new CArchiveOpener(this));
HRESULT Ret = InArchive->Open(new CArchiveIO(m_pDevice ? m_pDevice : new QFile(m_ArchivePath), QIODevice::ReadOnly, m_pDevice == NULL), &kMaxCheckStartPosition, callback);
if(Ret != S_OK)
{
InArchive->Close();
if(Ret == S_FALSE)
continue; // not supported
if(Ret == E_ABORT)
LogError(QString("Password required for archive"));
break; // error
}
//TRACE(L"%S Archive %S Opened for extraction", QS2CS(theArc.GetArchiveName(i ? i : Info.FormatIndex)), QS2CS(m_ArchivePath));
m_Archive = new SArchive(InArchive);
break;
}
if(m_Archive == NULL)
{
LogError("Failed to open archive");
return 0; // failed
}
// list archive content
UInt32 numItems = 0;
m_Archive->In->GetNumberOfItems(&numItems);
for (UInt32 i = 0; i < numItems; i++)
{
NWindows::NCOM::CPropVariant prop;
SFile File(i);
UInt32 numProps = 0;
m_Archive->In->GetNumberOfProperties(&numProps);
for(UInt32 j=0; j < numProps; j++)
{
m_Archive->In->GetProperty(i, j, &prop);
QVariant Propertie;
switch (prop.vt)
{
case VT_BSTR: Propertie = QString::fromStdWString(prop.bstrVal); break;
case VT_UI1: Propertie = prop.bVal; break;
case VT_UI2: Propertie = prop.uiVal; break;
case VT_UI4: Propertie = (qint32)prop.ulVal; break;
case VT_UI8: Propertie = (qint64)prop.uhVal.QuadPart; break;
case VT_BOOL: Propertie = VARIANT_BOOLToBool(prop.boolVal); break;
case VT_FILETIME: Propertie = *reinterpret_cast<qint64*>(&prop.filetime); break; // ToDo
default:
//TRACE(L"Unhandled archive property %S (%d)", QS2CS(GetPropertyName(j)), prop.vt);
case VT_EMPTY:
continue;
}
File.Properties.insert(GetPropertyName(j), Propertie);
//TRACE(L" >> File %S: %S=%S", QS2CS(File.Properties["Path"].toString()), QS2CS(GetPropertyName(j)), QS2CS(Propertie.toString()));
}
m_Files.append(File);
}
return 1; // success
}
bool CArchive::Extract(QString Path)
{
if(!m_Archive)
{
LogError("archive is not open");
return false;
}
if(Path.isEmpty())
Path = m_ArchivePath.left(m_ArchivePath.lastIndexOf(".")) + "/";
else if(Path.right(1) != "/")
Path.append("/");
QMap<int, QIODevice*> Files;
foreach(const SFile& File, m_Files)
{
if(File.Properties["IsDir"].toBool())
continue;
Files.insert(File.ArcIndex, new QFile(PrepareExtraction(File.Properties["Path"].toString(), Path)));
}
return Extract(&Files);
}
bool CArchive::Extract(QMap<int, QIODevice*> *FileList, bool bDelete)
{
if(!m_Archive)
{
LogError("archive is not open");
return false;
}
QMap<int, CArchiveIO*> Files;
foreach(int ArcIndex, FileList->keys())
{
FileProperty(ArcIndex, "Error", QVariant());
Files.insert(ArcIndex, new CArchiveIO(FileList->value(ArcIndex), QIODevice::NotOpen, bDelete));
}
CMyComPtr<IArchiveExtractCallback> callback(new CArchiveExtractor(this, Files));
if(m_Archive->In->Extract(NULL, (UInt32)(Int32)(-1), false, callback) != S_OK)
{
LogError(QString("Error(s) While extracting from archive"));
return false;
}
foreach(int ArcIndex, FileList->keys())
{
QVariant Error = FileProperty(ArcIndex, "Error");
if(Error.isValid())
return false;
}
return true;
}
bool CArchive::Close()
{
m_Files.clear();
if(m_Archive)
{
delete m_Archive;
m_Archive = NULL;
return true;
}
return false;
}
bool CArchive::Update(QMap<int, QIODevice*> *FileList, bool bDelete, int Level)
{
if(!theArc.IsOperational())
{
LogError("Couldnt open interface");
return false;
}
SArcInfo Info = GetArcInfo(m_ArchivePath);
CMyComPtr<IOutArchive> OutArchive;
if(!theArc.CreateOutArchive(Info.FormatIndex, OutArchive) || !OutArchive)
{
LogError("Archive can not be updated");
return false;
}
CMyComPtr<ISetProperties> setProperties;
OutArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties);
if (!setProperties)
{
TRACE(L"ISetProperties unsupported");
Q_ASSERT(0);
}
else
{
/* http://www.dotnetperls.com/7-zip-examples
Switch -mx0: Don't compress at all. This is called "copy mode."
Switch -mx1: Low compression. This is called "fastest" mode.
Switch -mx3: Fast compression mode. Will set various parameters automatically.
Switch -mx5: Same as above, but "normal."
Switch -mx7: This means "maximum" compression.
Switch -mx9: This means "ultra" compression. You probably want to use this.
Switch -ms=on: Enable solid mode. This is the default so you won't often need this.
Switch -ms=off: Disable solid mode. This is useful when you need to update individual files. Will reduce compression ratios normally.
*/
const wchar_t *names[] =
{
L"s",
L"x",
L"he"
};
const int kNumProps = sizeof(names) / sizeof(names[0]);
NWindows::NCOM::CPropVariant values[kNumProps] =
{
false, // solid mode OFF
(UInt32)Level, // compression level = 9 - ultra
true // file name encryption (7z only)
};
if(setProperties->SetProperties(names, values, kNumProps) != S_OK)
{
TRACE(L"ISetProperties failed");
Q_ASSERT(0);
}
}
QMap<int, CArchiveIO*> Files;
foreach(int ArcIndex, FileList->keys())
{
Files.insert(ArcIndex, new CArchiveIO(FileList->value(ArcIndex), QIODevice::NotOpen, bDelete));
FileProperty(ArcIndex, "Size", FileList->value(ArcIndex)->size());
FileProperty(ArcIndex, "Attrib", 32);
}
//TRACE(L"%S Archive %S Opened for update", QS2CS(theArc.GetArchiveName(Info.FormatIndex)), QS2CS(m_ArchivePath));
QIODevice* pFile = NULL;
bool bUpdate = false;
if(!m_pDevice)
{
if(m_PartSize != -1)
{
if(m_Archive)
{
LogError("can not update multipart archive");
return false;
}
pFile = new CSplitFile(m_ArchivePath, m_PartSize);
}
else if(m_Archive)
{
bUpdate = true;
pFile = new QFile(m_ArchivePath + ".tmp");
}
else
pFile = new QFile(m_ArchivePath);
}
else if(m_pDevice->isOpen())
{
bUpdate = true;
m_pDevice->close();
}
CMyComPtr<IArchiveUpdateCallback2> callback(new CArchiveUpdater(this, Files));
if(OutArchive->UpdateItems(new CArchiveIO(m_pDevice ? m_pDevice : pFile, QIODevice::WriteOnly, m_pDevice == NULL), FileCount(), callback) != S_OK)
{
LogError("Error(s) while updateing Archive");
return false;
}
Close(); // close even if it wasnt open to clear the file list
if(bUpdate)
{
if(!m_pDevice)
{
QFile::remove(m_ArchivePath);
QFile::rename(m_ArchivePath + ".tmp", m_ArchivePath);
}
return Open();
}
return true;
}
int CArchive::AddFile(QString Path)
{
if(FindByPath(Path) != -1)
return -1;
SFile File(m_Files.isEmpty() ? 0 : m_Files.last().ArcIndex+1);
//File.NewData = true;
m_Files.append(File);
FileProperty(File.ArcIndex,"Path",Path);
return File.ArcIndex;
}
int CArchive::FindByPath(QString Path)
{
if(Path.left(1) == "/")
Path.remove(0,1);
foreach(const SFile& File, m_Files)
{
if(Path.compare(File.Properties["Path"].toString().replace("\\","/")) == 0)
return File.ArcIndex;
}
return -1;
}
int CArchive::FindByIndex(int Index)
{
if(Index > m_Files.count())
return -1;
return m_Files[Index].ArcIndex;
}
int CArchive::GetIndex(int ArcIndex)
{
for(int Index = 0; Index < m_Files.count(); Index++)
{
const SFile& File = m_Files[Index];
if(File.ArcIndex == ArcIndex)
return Index;
}
return -1;
}
void CArchive::RemoveFile(int ArcIndex)
{
int Index = GetIndex(ArcIndex);
if(Index != -1)
m_Files.remove(Index);
}
QString CArchive::PrepareExtraction(QString FileName, QString Path)
{
// Cleanup
FileName.replace("\\","/");
FileName.remove(QRegularExpression("[:*?<>|\"]"));
if(FileName.left(1) == "/")
FileName.remove(0,1);
// Create Sub Paths if needed
QString SubPath = Path;
int Pos = FileName.lastIndexOf("/");
if(Pos != -1)
SubPath += FileName.left(Pos);
if(!QDir().exists(SubPath))
QDir().mkpath(SubPath);
return Path + FileName;
}
QString CArchive::GetNextPart(QString FileName)
{
if(!m_AuxParts.isEmpty())
{
SArcInfo ArcInfo = GetArcInfo(FileName);
foreach(const QString& Part, m_AuxParts)
{
if(GetArcInfo(Part).PartNumber == ArcInfo.PartNumber)
{
FileName = Part;
break;
}
}
}
int Pos = m_ArchivePath.lastIndexOf("/");
if(Pos != -1)
FileName.prepend(m_ArchivePath.left(Pos+1));
return FileName;
}
QVariant CArchive::FileProperty(int ArcIndex, QString Name)
{
int Index = GetIndex(ArcIndex);
if(Index != -1)
return m_Files[Index].Properties.value(Name);
return QVariant();
}
void CArchive::FileProperty(int ArcIndex, QString Name, QVariant Value)
{
int Index = GetIndex(ArcIndex);
if(Index != -1)
{
m_Files[Index].Properties.insert(Name, Value);
//m_Files[Index].NewInfo = true;
}
}
#endif
SArcInfo GetArcInfo(const QString &FileName)
{
SArcInfo ArcInfo;
ArcInfo.FileName = FileName.trimmed();
int Pos = ArcInfo.FileName.lastIndexOf("/");
if(Pos != -1)
ArcInfo.FileName.remove(0,Pos+1);
Pos = ArcInfo.FileName.lastIndexOf(".");
if(Pos != -1)
{
ArcInfo.ArchiveExt = ArcInfo.FileName.mid(Pos+1);
ArcInfo.FileName.remove(Pos, ArcInfo.FileName.length()-Pos);
}
// RAR spetial case
if(ArcInfo.ArchiveExt.indexOf(QRegularExpression("(rar|rev|r[0-9]{2,})", QRegularExpression::CaseInsensitiveOption)) == 0)
{
if(ArcInfo.ArchiveExt.compare("rar", Qt::CaseInsensitive) == 0 || ArcInfo.ArchiveExt.compare("rev", Qt::CaseInsensitive) == 0) // is this a new naming scheme
{
ArcInfo.PartNumber = 1; // rar is always to be threaded like multipart
Pos = ArcInfo.FileName.lastIndexOf("part", -1, Qt::CaseInsensitive);
if(Pos != -1)
{
int Pos1 = Pos+4;
int Pos2 = ArcInfo.FileName.indexOf(QRegularExpression("[^0-9]"), Pos1);
if(Pos2 == -1)
Pos2 = ArcInfo.FileName.length();
ArcInfo.FixRar = (ArcInfo.FileName.lastIndexOf(QRegularExpression("\\.part[0-9]+$", QRegularExpression::CaseInsensitiveOption), -1) + 1 != Pos);
ArcInfo.PartNumber = ArcInfo.FileName.mid(Pos1, Pos2-Pos1).toInt();
ArcInfo.FileName.remove(Pos, Pos2-Pos);
}
}
else // no its the old naming scheme
{
Pos = ArcInfo.ArchiveExt.indexOf(QRegularExpression("[0-9]", QRegularExpression::CaseInsensitiveOption));
ArcInfo.PartNumber = ArcInfo.ArchiveExt.mid(Pos).toInt()+2; // .rar is 1 .r00 is 2, etc....
}
ArcInfo.ArchiveExt = "rar";
}
if(ArcInfo.ArchiveExt.indexOf(QRegularExpression("(part|)[0-9]{3,}")) == 0)
{
ArcInfo.PartNumber = ArcInfo.ArchiveExt.toInt();
ArcInfo.ArchiveExt.clear();
Pos = ArcInfo.FileName.lastIndexOf(".");
if(Pos != -1)
{
ArcInfo.ArchiveExt = ArcInfo.FileName.mid(Pos+1);
ArcInfo.FileName.remove(Pos, ArcInfo.FileName.length()-Pos);
}
}
#ifdef USE_7Z
if(ArcInfo.ArchiveExt.indexOf(QRegularExpression("(rar|zip|7z)", QRegularExpression::CaseInsensitiveOption)) != -1)
ArcInfo.FormatIndex = theArc.FindByExt(ArcInfo.ArchiveExt);
#endif
ArcInfo.FileName += "." + ArcInfo.ArchiveExt;
if(ArcInfo.FormatIndex == 0) // not a known archive
ArcInfo.ArchiveExt.clear();
return ArcInfo;
}

View File

@ -0,0 +1,124 @@
#pragma once
#include "../mischelpers_global.h"
// *Note* no archiver specific includes here
#define USE_7Z
#ifdef USE_7Z
class MISCHELPERS_EXPORT CArchive
{
public:
CArchive(const QString &ArchivePath, QIODevice* pDevice = NULL);
static void Init();
static bool IsInit();
~CArchive();
QString GetPassword(bool bSet = false) {if(bSet) m_PasswordUsed = true; return m_Password;}
void SetPassword(const QString& Password) {m_Password = Password; m_PasswordUsed = false;}
bool HasUsedPassword() {return m_PasswordUsed;}
bool SetPartSize(quint64 PartSize) {if(m_Archive) return false; m_PartSize = PartSize; return true;}
int Open();
bool Extract(QString Path = "");
bool Extract(QMap<int, QIODevice*> *FileList, bool bDelete = true);
bool Close();
bool Update(QMap<int, QIODevice*> *FileList, bool bDelete = true, int Level = 0);
int AddFile(QString Path);
int FileCount() {return m_Files.count();}
int FindByPath(QString Path);
int FindByIndex(int Index);
void RemoveFile(int ArcIndex);
QVariant FileProperty(int ArcIndex, QString Name);
void FileProperty(int ArcIndex, QString Name, QVariant Value);
quint64 GetPartSize() {return m_PartSize;}
const QString& GetArchivePath() {return m_ArchivePath;}
double GetProgress() {return m_Progress.GetValue();}
void SetPartList(const QStringList& Parts) {m_AuxParts = Parts;}
static QString PrepareExtraction(QString FileName, QString Path);
protected:
int GetIndex(int ArcIndex);
QString GetNextPart(QString FileName);
virtual void LogError(const QString &Error) {}
friend class CArchiveOpener;
friend class CArchiveExtractor;
friend class CArchiveUpdater;
QString m_ArchivePath;
QIODevice* m_pDevice;
QString m_Password;
bool m_PasswordUsed;
quint64 m_PartSize;
QStringList m_AuxParts;
struct SArchive;
SArchive* m_Archive;
struct SFile
{
SFile(int Index = -1)
{
ArcIndex = Index;
//NewData = false;
//NewInfo = false;
}
int ArcIndex;
QVariantMap Properties;
//bool NewData;
//bool NewInfo;
};
QVector<SFile> m_Files;
struct SProgress
{
SProgress(){
uTotal = 0;
uCompleted = 0;
}
void SetTotal(quint64 Total) {uTotal = Total;}
void SetCompleted(quint64 Completed) {uCompleted = Completed;}
double GetValue()
{
double Total = uTotal;
double Completed = uCompleted;
return (Total > 0) ? Completed/Total : 0;
}
quint64 uTotal;
quint64 uCompleted;
} m_Progress;
};
#endif
struct MISCHELPERS_EXPORT SArcInfo
{
SArcInfo()
{
PartNumber = -1; // Single Part
FormatIndex = 0; // Not an archive (only a split file) or unsupported format
FixRar = false; // indicates if rar file name needs fixing
}
QString FileName; // Filename after extension removal
QString ArchiveExt; // Archive Extension
int FormatIndex; // Archive format Index
int PartNumber; // Part Number, -1 means not a multipart , 1 means first part
bool FixRar;
};
SArcInfo MISCHELPERS_EXPORT GetArcInfo(const QString &FileName);
class CArchiveInterface;
extern CArchiveInterface theArc;

View File

@ -0,0 +1,103 @@
#include "stdafx.h"
#include "ArchiveExtractor.h"
#include "Archive.h"
#ifdef USE_7Z
CArchiveExtractor::CArchiveExtractor(CArchive* pArchive, const QMap<int,CArchiveIO*>& Files)
{
m_pArchive = pArchive;
m_Index = -1;
m_Files = Files;
}
CArchiveExtractor::~CArchiveExtractor()
{
foreach(CArchiveIO* pFile, m_Files)
delete pFile;
}
STDMETHODIMP CArchiveExtractor::SetTotal(UInt64 size)
{
m_pArchive->m_Progress.SetTotal(size);
return S_OK;
}
STDMETHODIMP CArchiveExtractor::SetCompleted(const UInt64 *completeValue)
{
ASSERT(completeValue);
m_pArchive->m_Progress.SetCompleted(*completeValue);
return S_OK;
}
STDMETHODIMP CArchiveExtractor::PrepareOperation (Int32 askExtractMode)
{
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract:
//TRACE(L"Extracting ...");
break;
case NArchive::NExtract::NAskMode::kTest:
//TRACE(L"Testing ...");
break;
case NArchive::NExtract::NAskMode::kSkip:
//TRACE(L"Skipping ...");
break;
default: Q_ASSERT(0);
}
return S_OK;
}
STDMETHODIMP CArchiveExtractor::GetStream (UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
{
*outStream = NULL;
Q_ASSERT(index < m_pArchive->m_Files.count());
m_Index = index;
//TRACE(L"Archive Item '%S'", QS2CS(m_pArchive->FileProperty(m_Index, "Path").toString()));
if(CArchiveIO* pFile = m_Files.take(m_Index))
{
Q_ASSERT(askExtractMode == NArchive::NExtract::NAskMode::kExtract);
if (!pFile->Open(QIODevice::WriteOnly))
return S_FALSE;
CMyComPtr<IOutStream> outStreamLoc = pFile;
*outStream = outStreamLoc.Detach();
}
return S_OK;
}
STDMETHODIMP CArchiveExtractor::SetOperationResult (Int32 operationResult)
{
switch(operationResult)
{
case NArchive::NExtract::NOperationResult::kOK:
//TRACE(L"... Completed");
break;
case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
//TRACE(L"... Error (Un Supported Method)");
m_pArchive->LogError(QString("File Extraction Failes (Un Supported Method): %1").arg(m_pArchive->FileProperty(m_Index, "Path").toString()));
m_pArchive->FileProperty(m_Index, "Error", "Un Supported Method");
break;
case NArchive::NExtract::NOperationResult::kCRCError:
//TRACE(L"... Error (CRC)");
m_pArchive->LogError(QString("File Extraction Failes (CRC Error): %1").arg(m_pArchive->FileProperty(m_Index, "Path").toString()));
m_pArchive->FileProperty(m_Index, "Error", "CRC Error");
break;
case NArchive::NExtract::NOperationResult::kDataError:
//TRACE(L"... Error (Data)");
m_pArchive->LogError(QString("File Extraction Failes (Data Error): %1").arg(m_pArchive->FileProperty(m_Index, "Path").toString()));
m_pArchive->FileProperty(m_Index, "Error", "Data Error");
break;
default: Q_ASSERT(0);
}
return S_OK;
}
STDMETHODIMP CArchiveExtractor::CryptoGetTextPassword(BSTR *password)
{
QString Password = m_pArchive->GetPassword(true);
if(Password.isEmpty())
return E_ABORT;
return StringToBstr(Password.toStdWString().c_str(), password);
}
#endif

View File

@ -0,0 +1,34 @@
#pragma once
#include "ArchiveHelper.h"
#ifdef USE_7Z
class CArchiveExtractor: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICryptoGetTextPassword)
CArchiveExtractor(CArchive* pArchive, const QMap<int,CArchiveIO*>& Files);
~CArchiveExtractor();
// IProgress
STDMETHOD(SetTotal)(UInt64 size);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IArchiveExtractCallback
STDMETHOD(PrepareOperation)(Int32 askExtractMode);
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
STDMETHOD(SetOperationResult)(Int32 operationResult);
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
protected:
CArchive* m_pArchive;
QMap<int,CArchiveIO*> m_Files;
int m_Index;
};
#endif

View File

@ -0,0 +1,284 @@
#include "stdafx.h"
#include "ArchiveFS.h"
#include "../Common/Common.h"
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngineIterator
//
class C7zFileEngineIterator : public QAbstractFileEngineIterator
{
public:
C7zFileEngineIterator(QDir::Filters filters, const QStringList& filterNames,
const QStringList& allEntries)
: QAbstractFileEngineIterator(filters, filterNames), entries(allEntries), index(0) {}
~C7zFileEngineIterator() {}
QString next() override
{
if (!hasNext())
return QString();
++index;
return currentFilePath();
}
bool hasNext() const override
{
return index < entries.size();
}
QString currentFileName() const override
{
if (index <= 0 || index > entries.size())
return QString();
return entries.at(index - 1);
}
private:
mutable QStringList entries;
mutable int index;
};
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngine
//
C7zFileEngine::C7zFileEngine(const QString& filename, CArchive* pArchive, QMutex* pMutex)
: _flags(0), _size(0), _pos(0), _pArchive(pArchive), _pMutex(pMutex)
{
setFileName(filename);
}
C7zFileEngine::~C7zFileEngine()
{
close();
}
bool C7zFileEngine::open(QIODevice::OpenMode openMode)
{
close();
//if (openMode & QIODevice::WriteOnly) {
//
//} else
if (openMode & QIODevice::ReadOnly) {
QMutexLocker Lock(_pMutex);
QMap<int, QIODevice*> Files;
Files.insert(_index, new QBuffer(&_data));
_pArchive->Extract(&Files);
_size = _data.size();
_pos = 0;
} else
//if (openMode & QIODevice::Append) {
//
//} else
{
qWarning("Bad file open mode: %d", (int)openMode);
return false;
}
return true;
}
bool C7zFileEngine::close()
{
if (!isOpened())
return false;
_data.clear();
_size = 0;
_pos = 0;
return true;
}
bool C7zFileEngine::flush()
{
return true;
}
qint64 C7zFileEngine::size() const
{
return _size;
}
qint64 C7zFileEngine::pos() const
{
return _pos;
}
bool C7zFileEngine::seek(qint64 pos)
{
_pos = pos;
return true;
}
bool C7zFileEngine::isSequential() const
{
return true;
}
bool C7zFileEngine::remove()
{
return false;
}
bool C7zFileEngine::mkdir(const QString& dirName, bool createParentDirectories) const
{
return false;
}
bool C7zFileEngine::rmdir(const QString& dirName, bool recurseParentDirectories) const
{
return false;
}
bool C7zFileEngine::caseSensitive() const
{
return false;
}
bool C7zFileEngine::isRelativePath() const
{
return false;
}
QAbstractFileEngine::Iterator *C7zFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
{
QMutexLocker Lock(_pMutex);
QStringList allEntries;
for (int i = 0; i < _pArchive->FileCount(); i++) {
QString Path = _pArchive->FileProperty(i, "Path").toString();
if (!_filename.isEmpty()) {
if (!Path.startsWith(_filename))
continue;
Path = Path.mid(_filename.length() + 1);
}
if (!Path.isEmpty() && !Path.contains("\\"))
allEntries.append(Path);
}
return new C7zFileEngineIterator(filters, filterNames, allEntries);
}
QAbstractFileEngine::FileFlags C7zFileEngine::fileFlags(FileFlags type) const
{
return type & _flags;
}
QString C7zFileEngine::fileName(FileName file) const
{
return _filename;
}
QDateTime C7zFileEngine::fileTime(FileTime time) const
{
switch (time)
{
case QAbstractFileEngine::ModificationTime:
default:
return _datetime;
break;
};
}
void C7zFileEngine::setFileName(const QString& file)
{
int pos = file.indexOf(":") + 2;
_filename = file.mid(pos);
if (_filename.isEmpty()) { // root
_flags = ExistsFlag | DirectoryType | ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm;
return;
}
QMutexLocker Lock(_pMutex);
_index = _pArchive->FindByPath(_filename);
if (_index != -1) {
_flags = ExistsFlag | ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm;
if (_pArchive->FileProperty(_index, "IsDir").toBool())
_flags |= DirectoryType;
else
_flags |= FileType;
}
}
bool C7zFileEngine::atEnd() const
{
return _pos >= _data.size();
}
qint64 C7zFileEngine::read(char* data, qint64 maxlen)
{
qint64 togo = qMin(maxlen, _size - _pos);
if (togo > 0) {
memcpy(data, _data.constData() + _pos, togo);
_pos += togo;
}
return togo;
}
qint64 C7zFileEngine::readLine(char* data, qint64 maxlen)
{
return -1; // todo
}
qint64 C7zFileEngine::write(const char* data, qint64 len)
{
return -1;
}
bool C7zFileEngine::isOpened() const
{
return _size != 0;
}
QFile::FileError C7zFileEngine::error() const
{
return QFile::UnspecifiedError;
}
QString C7zFileEngine::errorString() const
{
return "";
}
bool C7zFileEngine::supportsExtension(Extension extension) const
{
return extension == QAbstractFileEngine::AtEndExtension;
}
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngineHandler
//
C7zFileEngineHandler::C7zFileEngineHandler(const QString& ArchivePath, const QString& Scheme, QObject* parent)
: QObject(parent), m_pArchive(NULL)
{
CArchive* pArchive = new CArchive(ArchivePath);
if (pArchive->Open() > 0)
m_pArchive = pArchive;
else
delete pArchive;
m_Scheme = Scheme + ":";
}
C7zFileEngineHandler::~C7zFileEngineHandler()
{
delete m_pArchive;
}
QAbstractFileEngine* C7zFileEngineHandler::create(const QString& filename) const
{
if (m_pArchive && filename.startsWith(m_Scheme))
return new C7zFileEngine(filename, m_pArchive, &m_Mutex);
return NULL;
}

View File

@ -0,0 +1,84 @@
#pragma once
#include <private/qabstractfileengine_p.h>
#include "Archive.h"
#include "../mischelpers_global.h"
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngine
//
class MISCHELPERS_EXPORT C7zFileEngine : public QAbstractFileEngine
{
protected:
friend class C7zFileEngineHandler;
C7zFileEngine(const QString& filename, CArchive* pArchive, QMutex* pMutex);
public:
virtual ~C7zFileEngine();
virtual bool open(QIODevice::OpenMode openMode);
virtual bool close();
virtual bool flush();
virtual qint64 size() const;
virtual qint64 pos() const;
virtual bool seek(qint64 pos);
virtual bool isSequential() const;
virtual bool remove();
virtual bool mkdir(const QString& dirName, bool createParentDirectories) const;
virtual bool rmdir(const QString& dirName, bool recurseParentDirectories) const;
virtual bool caseSensitive() const;
virtual bool isRelativePath() const;
virtual FileFlags fileFlags(FileFlags type = FileInfoAll) const;
virtual QString fileName(FileName file = DefaultName) const;
virtual QDateTime fileTime(FileTime time) const;
virtual void setFileName(const QString& file);
bool atEnd() const;
virtual qint64 read(char* data, qint64 maxlen);
virtual qint64 readLine(char* data, qint64 maxlen);
virtual qint64 write(const char* data, qint64 len);
bool isOpened() const;
QAbstractFileEngine::Iterator* beginEntryList(QDir::Filters filters, const QStringList& filterNames);
QFile::FileError error() const;
QString errorString() const;
virtual bool supportsExtension(Extension extension) const;
private:
qint64 _size;
FileFlags _flags;
QString _filename;
QDateTime _datetime;
int _index;
QByteArray _data;
qint64 _pos;
CArchive* _pArchive;
QMutex* _pMutex;
};
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngineHandler
//
class MISCHELPERS_EXPORT C7zFileEngineHandler : public QObject, public QAbstractFileEngineHandler
{
public:
C7zFileEngineHandler(const QString& ArchivePath, const QString& Scheme, QObject* parent = NULL);
~C7zFileEngineHandler();
bool IsOpen() { return m_pArchive != NULL; }
QString Prefix() { return m_Scheme; }
QAbstractFileEngine* create(const QString& filename) const;
private:
QString m_Scheme;
CArchive* m_pArchive;
mutable QMutex m_Mutex;
};

View File

@ -0,0 +1,156 @@
#include "stdafx.h"
#ifndef WIN32
#define INITGUID
#endif
#include "ArchiveHelper.h"
#ifdef USE_7Z
HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned)
{
NWindows::NCOM::CPropVariant prop;
isAssigned = false;
RINOK(getMethodProperty(index, propId, &prop));
if (prop.vt == VT_BSTR)
{
isAssigned = true;
clsId = *(const GUID *)prop.bstrVal;
}
else if (prop.vt != VT_EMPTY)
return E_FAIL;
return S_OK;
}
HRESULT ReadProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NWindows::NCOM::CPropVariant &prop)
{
if (getProp2)
return getProp2(index, propID, &prop);;
return getProp(propID, &prop);
}
HRESULT ReadStringProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, QString &res)
{
NWindows::NCOM::CPropVariant prop;
RINOK(ReadProp(getProp, getProp2, index, propID, prop));
if (prop.vt == VT_BSTR)
res = QString::fromStdWString(prop.bstrVal ? prop.bstrVal : L"");
else if (prop.vt != VT_EMPTY)
return E_FAIL;
return S_OK;
}
HRESULT ReadBoolProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res)
{
NWindows::NCOM::CPropVariant prop;
RINOK(ReadProp(getProp, getProp2, index, propID, prop));
if (prop.vt == VT_BOOL)
res = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt != VT_EMPTY)
return E_FAIL;
return S_OK;
}
HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
{
NWindows::NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, propID, &prop));
if (prop.vt == VT_BOOL)
result = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt == VT_EMPTY)
result = false;
else
return E_FAIL;
return S_OK;
}
struct SPropertyNames{
SPropertyNames();
QMap<PROPID,QString> Map;
} SPropertyNames;
SPropertyNames::SPropertyNames()
{
Map.insert(kpidPath, "Path");
Map.insert(kpidName, "Name");
Map.insert(kpidExtension, "Extension");
Map.insert(kpidIsDir, "IsDir");
Map.insert(kpidSize, "Size");
Map.insert(kpidPackSize, "PackSize");
Map.insert(kpidAttrib, "Attrib");
Map.insert(kpidCTime, "CTime");
Map.insert(kpidATime, "ATime");
Map.insert(kpidMTime, "MTime");
Map.insert(kpidSolid, "Solid");
Map.insert(kpidCommented, "Commented");
Map.insert(kpidEncrypted, "Encrypted");
Map.insert(kpidSplitBefore, "SplitBefore");
Map.insert(kpidSplitAfter, "SplitAfter");
Map.insert(kpidDictionarySize, "DictionarySize");
Map.insert(kpidCRC, "CRC");
Map.insert(kpidType, "Type");
Map.insert(kpidIsAnti, "IsAnti");
Map.insert(kpidMethod, "Method");
Map.insert(kpidHostOS, "HostOS");
Map.insert(kpidFileSystem, "FileSystem");
Map.insert(kpidUser, "User");
Map.insert(kpidGroup, "Group");
Map.insert(kpidBlock, "Block");
Map.insert(kpidComment, "Comment");
Map.insert(kpidPosition, "Position");
Map.insert(kpidPrefix, "Prefix");
Map.insert(kpidNumSubDirs, "NumSubDirs");
Map.insert(kpidNumSubFiles, "NumSubFiles");
Map.insert(kpidUnpackVer, "UnpackVer");
Map.insert(kpidVolume, "Volume");
Map.insert(kpidIsVolume, "IsVolume");
Map.insert(kpidOffset, "Offset");
Map.insert(kpidLinks, "Links");
Map.insert(kpidNumBlocks, "NumBlocks");
Map.insert(kpidNumVolumes, "NumVolumes");
Map.insert(kpidBit64, "Bit64");
Map.insert(kpidBigEndian, "BigEndian");
Map.insert(kpidCpu, "Cpu");
Map.insert(kpidPhySize, "PhySize");
Map.insert(kpidHeadersSize, "HeadersSize");
Map.insert(kpidChecksum, "Checksum");
Map.insert(kpidCharacts, "Characts");
Map.insert(kpidVa, "Va");
Map.insert(kpidId, "Id");
Map.insert(kpidShortName, "ShortName");
Map.insert(kpidCreatorApp, "CreatorApp");
Map.insert(kpidSectorSize, "SectorSize");
Map.insert(kpidPosixAttrib, "PosixAttrib");
Map.insert(kpidLink, "Link");
Map.insert(kpidError, "Error");
Map.insert(kpidTotalSize, "TotalSize");
Map.insert(kpidFreeSpace, "FreeSpace");
Map.insert(kpidClusterSize, "ClusterSize");
Map.insert(kpidVolumeName, "VolumeName");
Map.insert(kpidLocalName, "LocalName");
Map.insert(kpidProvider, "Provider");
};
QString GetPropertyName(PROPID PropID)
{
return SPropertyNames.Map.value(PropID, "unknown");
}
#if 1
#include "./7z/CPP/Windows/PropVariant.cpp"
#else
#ifndef WIN32
#include "../../7-Zip/p7zip_9.20.1/CPP/Windows/PropVariant.cpp"
#include "../../7-Zip/p7zip_9.20.1/CPP/Common/MyWindows.cpp"
#else
#include "../../7-Zip/7z/CPP/Windows/PropVariant.cpp"
#endif
#endif
#endif

View File

@ -0,0 +1,85 @@
#pragma once
#include "Archive.h"
#ifdef USE_7Z
#if 1
#include "./7z/CPP/Common/MyInitGuid.h"
#include "./7z/CPP/Common/MyCom.h"
#include "./7z/CPP/7zip/Archive/IArchive.h"
#include "./7z/CPP/7zip/IPassword.h"
#include "./7z/CPP/7zip/IProgress.h"
#include "./7z/CPP/Windows/PropVariant.h"
#include "./7z/CPP/Common/Defs.h"
#include "./7z/CPP/Windows/Defs.h"
#include "./7z/CPP/7zip/ICoder.h"
#else
#ifndef WIN32
#include "../../7-Zip/p7zip_9.20.1/CPP/myWindows/StdAfx.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/Common/MyCom.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/Common/MyGuidDef.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/Archive/IArchive.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/IPassword.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/IProgress.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/Windows/PropVariant.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/Common/Defs.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/Windows/Defs.h"
#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/ICoder.h"
#else
#include "../../7-Zip/7z920/CPP/Common/MyInitGuid.h"
#include "../../7-Zip/7z920/CPP/Common/MyCom.h"
#include "../../7-Zip/7z920/CPP/7zip/Archive/IArchive.h"
#include "../../7-Zip/7z920/CPP/7zip/IPassword.h"
#include "../../7-Zip/7z920/CPP/7zip/IProgress.h"
#include "../../7-Zip/7z920/CPP/Windows/PropVariant.h"
#include "../../7-Zip/7z920/CPP/Common/Defs.h"
#include "../../7-Zip/7z920/CPP/Windows/Defs.h"
#include "../../7-Zip/7z920/CPP/7zip/ICoder.h"
#endif
#endif
#include <QLibrary>
#include "ArchiveIO.h"
typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value);
typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);
typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);
typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);
typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);
typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject);
HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned);
HRESULT ReadProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NWindows::NCOM::CPropVariant &prop);
HRESULT ReadStringProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, QString &res);
HRESULT ReadBoolProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res);
HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result);
QString GetPropertyName(PROPID PropID);
/*
DEFINE_GUID(CLSID_7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); // 7z - 7-Zip Arcive
DEFINE_GUID(CLSID_rar, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x00); // rar r00 - WinRar Archive
DEFINE_GUID(CLSID_cab, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0x00); // cab - Cabinet File
DEFINE_GUID(CLSID_tar, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEE, 0x00, 0x00); // tar - Tar Archive
DEFINE_GUID(CLSID_zip, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00); // zip jar xpi odt ods docx xlsx - Zip Archive
DEFINE_GUID(CLSID_hfs, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE3, 0x00, 0x00); // hfs - HFS Image
DEFINE_GUID(CLSID_iso, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE7, 0x00, 0x00); // iso img - ISO Image
DEFINE_GUID(CLSID_udf, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE0, 0x00, 0x00); // iso img - UDF Image
DEFINE_GUID(CLSID_wim, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE6, 0x00, 0x00); // wim swm - Windows Image
DEFINE_GUID(CLSID_chm, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE9, 0x00, 0x00); // chm chi chq chw hxs hxi hxr hxq hxw lit - Compressed HTML Help
DEFINE_GUID(CLSID_msi, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE5, 0x00, 0x00); // msi msp doc xls ppt - Microsoft Installer
DEFINE_GUID(CLSID_nsis, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x09, 0x00, 0x00); // - Nullsoft Scriptable Install System
*/
#ifndef TRACE
#define TRACE
#endif
#define QS2CS(x) (x.toLatin1().data())
#endif

View File

@ -0,0 +1,84 @@
#pragma once
#include "ArchiveHelper.h"
#ifdef USE_7Z
class CArchiveIO: public IOutStream, public IInStream, public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(IOutStream, IInStream)
CArchiveIO(QIODevice* pFile, QIODevice::OpenMode Mode, bool bDelete = true)
{
Q_ASSERT(pFile);
m_pFile = pFile;
if(Mode != QIODevice::NotOpen)
m_pFile->open(Mode);
m_bDelete = bDelete;
}
~CArchiveIO()
{
m_pFile->close();
if(m_bDelete)
delete m_pFile;
}
bool Open(QIODevice::OpenMode Mode) {
return m_pFile->open(Mode);
}
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize)
{
quint64 read = m_pFile->read((char*)data, size);
if(read == -1)
return E_FAIL;
if(processedSize)
*processedSize = read;
return S_OK;
}
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize)
{
quint64 writen = m_pFile->write((const char*)data, size);
if(writen == -1)
return E_FAIL;
if(processedSize)
*processedSize = writen;
return S_OK;
}
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
switch(seekOrigin)
{
case 0: break; // FILE_BEGIN
case 1: offset += m_pFile->pos(); break; // FILE_CURRENT
case 2: offset += m_pFile->size(); break; // FILE_END
default: Q_ASSERT(0); return E_FAIL;
}
if(!m_pFile->seek(offset))
return E_FAIL;
if(newPosition)
*newPosition = offset;
return S_OK;
}
STDMETHOD(SetSize)(UInt64 newSize)
{
return S_OK;
}
STDMETHOD(GetSize)(UInt64 *size)
{
*size = m_pFile->size();
return S_OK;
}
protected:
QIODevice* m_pFile;
bool m_bDelete;
};
#endif

View File

@ -0,0 +1,193 @@
#include "stdafx.h"
#include "ArchiveInterface.h"
//#include "../Functions.h"
#ifdef __APPLE__
#include <QCoreApplication>
#endif
#ifdef USE_7Z
CArchiveInterface::CArchiveInterface()
: m_7z("7z")
{
m_Operational = false;
}
bool CArchiveInterface::Init()
{
QMutexLocker Locker(&m_Mutex);
if(m_Operational)
return true;
#ifdef __APPLE__
m_7z.setFileName(QCoreApplication::applicationDirPath() + "/7z.so");
#endif
//LogLine(LOG_INFO | LOG_DEBUG, QObject::tr("7z: Loading Library..."));
if(!m_7z.load())
{
//LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: failed to load!"));
return false;
}
// Load Available Coders
/*GetMethodPropertyFunc getMethodPropertyFunc = (GetMethodPropertyFunc)m_7z.resolve("GetMethodProperty");
GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)m_7z.resolve("GetNumberOfMethods");
if(!getNumberOfMethodsFunc || !getMethodPropertyFunc)
return false;
UInt32 numMethods = 1;
if(getNumberOfMethodsFunc(&numMethods) != S_OK)
return false;
for(UInt32 i = 0; i < numMethods; i++)
{
CCdrInfo info;
info.Index = i;
Q_ASSERT(GetCoderClass(getMethodPropertyFunc, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned) == S_OK);
Q_ASSERT(GetCoderClass(getMethodPropertyFunc, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned) == S_OK);
m_Coders.append(info);
}*/
// Load Supported Formats
GetHandlerPropertyFunc getProp = NULL;
GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)m_7z.resolve("GetHandlerProperty2");
if (getProp2 == NULL)
{
getProp = (GetHandlerPropertyFunc)m_7z.resolve("GetHandlerProperty");
if(!getProp)
{
//LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to resolve GetHandlerProperty!"));
return false;
}
}
UInt32 numFormats = 1;
GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)m_7z.resolve("GetNumberOfFormats");
if (getNumberOfFormats != NULL)
{
if(getNumberOfFormats(&numFormats) != S_OK)
{
//LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to enumerate Formats!"));
return false;
}
}
if (getProp2 == NULL)
numFormats = 1;
for(UInt32 i = 0; i < numFormats; i++)
{
CArcInfoEx info;
if(ReadStringProp(getProp, getProp2, i, NArchive::kName, info.Name) != S_OK)
{
//LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to get Formats %1 Name!").arg(i));
return false;
}
NWindows::NCOM::CPropVariant prop;
if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)
continue;
if (prop.vt != VT_BSTR)
continue;
info.ClassID = *(const GUID *)prop.bstrVal;
prop.Clear();
QString ext, addExt;
if(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext) != S_OK)
{
//LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to get Formats %1 Property kExtension!").arg(i));
return false;
}
if(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt) != S_OK)
{
//LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to get Formats %1 Property kAddExtension!").arg(i));
return false;
}
info.AddExts(ext, addExt);
//TRACE(L"Archive Format %S supported %S, %S", QS2CS(info.Name), QS2CS(ext), QS2CS(addExt));
ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, info.UpdateEnabled);
if (info.UpdateEnabled)
ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, info.KeepName);
#ifdef _SFX
if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)
{
if (prop.vt == VT_BSTR)
info.StartSignature = QByteArray((char*)prop.bstrVal, ::SysStringByteLen(prop.bstrVal));
}
#endif
m_Formats.append(info);
}
createObjectFunc = (CreateObjectFunc)m_7z.resolve("CreateObject");
if(createObjectFunc == NULL)
{
//LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to resolve CreateObjectFunc!"));
return false;
}
//LogLine(LOG_SUCCESS | LOG_DEBUG, QObject::tr("7z: Loaded Successfuly"));
m_Operational = true;
return true;
}
int CArchiveInterface::FindByExt(const QString &Ext) const
{
QMutexLocker Locker(&m_Mutex);
for(int i=0; i<m_Formats.count(); i++)
{
if(Ext.compare(m_Formats[i].GetMainExt(), Qt::CaseInsensitive) == 0)
return i+1;
}
return 0;
}
/*QList<int> CArchiveInterface::FindByExt(const QString &Ext)
{
QMutexLocker Locker(&m_Mutex);
QList<int> ArcIndex;
for(int i=0; i<m_Formats.count(); i++)
{
if(m_Formats[i].FindExtension(Ext) != -1)
ArcIndex.append(i+1);
}
return ArcIndex;
}*/
QString CArchiveInterface::GetArchiveName(int formatIndex)
{
QMutexLocker Locker(&m_Mutex);
if(formatIndex > 0 && formatIndex <= m_Formats.count())
return m_Formats[formatIndex-1].Name;
return "";
}
bool CArchiveInterface::CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const
{
QMutexLocker Locker(&m_Mutex);
if(formatIndex > 0 && formatIndex <= m_Formats.count())
return CreateArchiveHandler(m_Formats[formatIndex-1], (void **)&archive, false);
return false;
}
bool CArchiveInterface::CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const
{
QMutexLocker Locker(&m_Mutex);
if(formatIndex > 0 && formatIndex <= m_Formats.count())
return CreateArchiveHandler(m_Formats[formatIndex-1], (void **)&archive, true);
return false;
}
bool CArchiveInterface::CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const
{
if(createObjectFunc)
return createObjectFunc(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive) == S_OK;
return false;
}
#endif

View File

@ -0,0 +1,114 @@
#pragma once
#include "ArchiveHelper.h"
#ifdef USE_7Z
/*struct CCdrInfo
{
UInt32 Index;
CLSID Encoder;
CLSID Decoder;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
};*/
struct CArcInfoEx
{
CArcInfoEx(): UpdateEnabled(false), KeepName(false) {}
CLSID ClassID;
QString Name;
bool UpdateEnabled;
bool KeepName;
struct CArcExtInfo
{
CArcExtInfo(const QString ext = "", const QString addExt = ""): Ext(ext), AddExt(addExt) {}
QString Ext;
QString AddExt;
};
QList<CArcExtInfo> Exts;
#ifdef _SFX
QByteArray StartSignature;
// CByteBuffer FinishSignature;
#endif
QString GetMainExt() const
{
if (Exts.isEmpty())
return "";
return Exts[0].Ext;
}
int FindExtension(const QString &ext) const
{
for (int i = 0; i < Exts.count(); i++)
if (ext.compare(Exts[i].Ext, Qt::CaseInsensitive) == 0)
return i;
return -1;
}
QString GetAllExtensions() const
{
QString s;
for (int i = 0; i < Exts.count(); i++)
{
if (i > 0)
s += ' ';
s += Exts[i].Ext;
}
return s;
}
void AddExts(const QString &ext, const QString &addExt)
{
QStringList exts = ext.split(" ");
exts.removeAll("");
QStringList addExts = addExt.split(" ");
addExts.removeAll("");
for (int i = 0; i < exts.count(); i++)
{
CArcExtInfo extInfo;
extInfo.Ext = exts[i];
if (i < addExts.count())
{
extInfo.AddExt = addExts[i];
if (extInfo.AddExt == "*")
extInfo.AddExt.clear();
}
Exts.append(extInfo);
}
}
};
class CArchiveInterface
{
public:
CArchiveInterface();
bool Init();
bool IsOperational() {return m_Operational;}
int FindByExt(const QString &Ext) const;
//QList<int> FindByExt(const QString &Ext);
QString GetArchiveName(int formatIndex);
int GetFormatCount() {return m_Formats.count();}
bool CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const;
bool CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const;
protected:
bool CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const;
QLibrary m_7z;
//QList<CCdrInfo> m_Coders;
QVector<CArcInfoEx> m_Formats;
CreateObjectFunc createObjectFunc;
bool m_Operational;
mutable QMutex m_Mutex;
};
#endif

View File

@ -0,0 +1,53 @@
#include "stdafx.h"
#include "ArchiveOpener.h"
#include "Archive.h"
#ifdef USE_7Z
CArchiveOpener::CArchiveOpener(CArchive* pArchive)
{
m_pArchive = pArchive;
}
STDMETHODIMP CArchiveOpener::GetProperty(PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidName:
{
QString Name = m_pArchive->m_ArchivePath;
int Pos = m_pArchive->m_ArchivePath.lastIndexOf("/");
if(Pos != -1)
Name.remove(0,Pos+1);
prop = Name.toStdWString().c_str(); break;
}
default: Q_ASSERT(0);
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CArchiveOpener::GetStream(const wchar_t *name, IInStream **inStream)
{
m_pArchive->SetPartSize(0); // tell that this is multipart
QString Path = m_pArchive->GetNextPart(QString::fromStdWString(name));
if(QFile::exists(Path))
{
CMyComPtr<IInStream> inStreamLoc(new CArchiveIO(new QFile(Path), QIODevice::ReadOnly));
*inStream = inStreamLoc.Detach();
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CArchiveOpener::CryptoGetTextPassword(BSTR *password)
{
QString Password = m_pArchive->GetPassword(true);
if(Password.isEmpty())
return E_ABORT;
return StringToBstr(Password.toStdWString().c_str(), password);
}
#endif

View File

@ -0,0 +1,29 @@
#pragma once
#include "ArchiveHelper.h"
#ifdef USE_7Z
class CArchiveOpener: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public ICryptoGetTextPassword, public CMyUnknownImp
{
public:
CArchiveOpener(CArchive* pArchive);
MY_UNKNOWN_IMP3(IArchiveOpenCallback, IArchiveOpenVolumeCallback, ICryptoGetTextPassword)
// IArchiveOpenCallback
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) {return S_OK;}
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) {return S_OK;}
// IArchiveOpenVolumeCallback
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
// ICryptoGetTextPassword2
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
protected:
CArchive* m_pArchive;
};
#endif

View File

@ -0,0 +1,419 @@
#include "stdafx.h"
#include "ArchiveThread.h"
#include "SplitFile.h"
#include "../Common/Common.h"
#include "../Common/OtherFunctions.h"
int _QStringList_pType = qRegisterMetaType<QStringList>("QStringList");
CArchiveThread::CArchiveThread(const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QStringList& Parts)
{
#ifdef USE_7Z
m_Worker = new C7zWorker(ArchivePath, WorkingPath, Password, PartSize, Parts);
m_Worker->moveToThread(this);
start();
m_Worker->m_Lock.Lock();
#else
ASSERT(0);
#endif
}
CArchiveThread::CArchiveThread(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QString &CommentPath)
{
m_Worker = new CRarWorker(WinRarPath, ArchivePath, WorkingPath, Password, PartSize, CommentPath);
m_Worker->moveToThread(this);
start();
m_Worker->m_Lock.Lock();
}
void CArchiveThread::Terminate()
{
stop();
delete m_Worker;
delete this;
}
QStringList CArchiveThread::ListParts(const QString &ArchivePath, bool NamesOnly)
{
QStringList Parts;
StrPair PathName = Split2(ArchivePath, "/", true);
StrPair NameEx = Split2(PathName.second, ".", true);
QString PatternStr;
if(NameEx.second == "rar")
PatternStr = QRegularExpression::escape(NameEx.first) + "(\\.part[0-9]*)?\\.rar";
else
PatternStr = QRegularExpression::escape(NameEx.first + "." + NameEx.second) + "(\\.[0-9]*)?";
QRegularExpression Pattern = QRegularExpression(QRegularExpression::anchoredPattern(PatternStr), QRegularExpression::CaseInsensitiveOption);
QDir Dir(PathName.first);
foreach (const QString& File, Dir.entryList())
{
if (File.compare(".") == 0 || File.compare("..") == 0)
continue;
QRegularExpressionMatch Result = Pattern.match(File);
if(Result.hasMatch())
{
if(NamesOnly)
Parts.append(File);
else
Parts.append(PathName.first + "/" + File);
}
}
return Parts;
}
QStringList CArchiveThread::GetErrors()
{
QStringList Errors;
if(IsBusy())
return Errors;
Errors = m_Worker->m_Errors;
if(!Errors.isEmpty() && HasUsedPassword())
Errors.append("Wrong Password ?");
m_Worker->m_Errors.clear();
return Errors;
}
//////////////////////////////////////////////////////////////////////////
// Buildin 7z Library worker
//
#ifdef USE_7Z
C7zWorker::C7zWorker(const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QStringList& Parts)
: CArchive(ArchivePath)
{
SetPassword(Password);
SetPartSize(PartSize);
m_WorkingPath = WorkingPath;
SetPartList(Parts);
if(QFile::exists(ArchivePath))
{
if(!Open())
m_Errors.append("Open Failed");
}
}
C7zWorker::~C7zWorker()
{
Close();
}
QMap<QString, quint64> C7zWorker::GetFileList()
{
QMap<QString, quint64> FileList;
if(!m_Mutex.tryLock(100))
{
//LogLine(LOG_DEBUG | LOG_ERROR, tr("atempted to get the file list of a already busy archive thread"));
return FileList;
}
if(m_Archive)
{
foreach(const SFile& File, m_Files)
{
if(File.Properties["IsDir"].toBool())
continue;
FileList.insert(File.Properties["Path"].toString(), File.Properties["Size"].toULongLong());
}
}
//else
//LogLine(LOG_DEBUG | LOG_ERROR, tr("Archive %1, is not open for extraction").arg(m_ArchivePath));
m_Mutex.unlock();
return FileList;
}
void C7zWorker::OnExtractAllFiles()
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
SArcInfo Info = GetArcInfo(m_ArchivePath);
if(Info.FormatIndex == 0) // not an arcive just a split file
{
if(!QDir().exists(m_WorkingPath))
QDir().mkpath(m_WorkingPath);
if(Info.PartNumber == -1) // single aprt
{
if(!QFile::rename(m_ArchivePath,m_WorkingPath + Info.FileName))
m_Errors.append("Failed to move file");
}
else // multi part, to be merged
{
int Pos = m_ArchivePath.indexOf(QRegularExpression("\\.[0-9]+$"));
if(Pos != -1)
m_ArchivePath.truncate(Pos);
CSplitFile SplitFile(m_ArchivePath);
if(!SplitFile.open(QIODevice::ReadOnly))
m_Errors.append("Failed to open temp file");
else
{
QFile File(m_WorkingPath + Info.FileName);
if(!File.open(QIODevice::WriteOnly))
m_Errors.append("Failed to open file");
else
{
const qint64 Size = 16*1024;
char Buffer[Size];
while(!SplitFile.atEnd())
{
qint64 Temp = SplitFile.read(Buffer, Size);
File.write(Buffer, Temp);
}
}
}
}
}
else
if(!Extract(m_WorkingPath))
m_Errors.append("Extraction Failed");
}
void C7zWorker::OnInsertAllFiles()
{
OnInsertFiles(ListDir(m_WorkingPath));
}
void C7zWorker::OnExtractFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
if(!QDir().exists(m_WorkingPath))
QDir().mkpath(m_WorkingPath);
QMap<int, QIODevice*> Files;
foreach(const QString& Name, FileList)
{
int ArcIndex = FindByPath(Name);
if(ArcIndex != -1)
Files.insert(ArcIndex, new QFile(PrepareExtraction(Name, m_WorkingPath)));
//else
//LogLine(LOG_DEBUG, tr("file %1 couldn't be find in archive %2").arg(Name, m_ArchivePath)); // should not happen
}
if(!Extract(&Files))
m_Errors.append("Extraction Failed");
}
void C7zWorker::OnInsertFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QMap<int, QIODevice*> Files;
foreach(const QString& File, FileList)
{
StrPair RootName = Split2(File, "\\", true);
if(RootName.second.isEmpty())
{
RootName.second = RootName.first;
RootName.first = "";
}
int ArcIndex = AddFile(RootName.second);
if(ArcIndex != -1)
{
QString FileName = (RootName.first.isEmpty() ? m_WorkingPath : RootName.first) + RootName.second;
Files.insert(ArcIndex, new QFile(FileName));
}
//else
//LogLine(LOG_DEBUG, tr("file %1 is already present in archive %2").arg(RootName.second, m_ArchivePath)); // should not happen
}
if(!Update(&Files))
m_Errors.append("Insertion Failed");
}
#endif
//////////////////////////////////////////////////////////////////////////
// Extern WinRar worker
//
CRarWorker::CRarWorker(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QString &CommentPath)
{
m_WinRarPath = WinRarPath;
if(CommentPath.contains(" "))
m_CommentPath = "\"" + CommentPath + "\"";
else
m_CommentPath = CommentPath;
m_ArchivePath = ArchivePath;
m_WorkingPath = WorkingPath;
CreateDir(m_WorkingPath);
m_Password = Password;
m_PartSize = PartSize;
if(!QFile::exists(WinRarPath + "rar.exe"))
m_Errors.append("WinRar is not present or the path is wrong");
}
QMap<QString, quint64> CRarWorker::GetFileList()
{
QMap<QString, quint64> FileList;
if(!m_Mutex.tryLock(100))
{
//LogLine(LOG_DEBUG | LOG_ERROR, tr("atempted to get the file list of a already busy archive thread"));
return FileList;
}
QStringList Arguments;
Arguments.append("v");
if(!m_Password.isEmpty())
Arguments.append("-p" + m_Password);
Arguments.append(m_ArchivePath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "unrar.exe", Arguments);
/*for(;;)
{
bool bDone = pWinRar->waitForFinished(1000);
QStringList Test;
while(pWinRar->canReadLine())
{
QString Line = pWinRar->readLine();
Test.append(Line);
}
if(bDone)
break;
}*/
pWinRar->waitForFinished(-1);
QStringList Test;
int Index = -1;
QString Name;
while(pWinRar->canReadLine())
{
QString Line = pWinRar->readLine().trimmed();
if(Line == "-------------------------------------------------------------------------------")
{
if(Index == -1)
{
Index = 0;
continue;
}
break;
}
else if(Index == -1)
continue;
Index++;
if(Index % 2 == 1)
Name = Line.replace("\\","/");
else
FileList.insert(Name,Split2(Line," ").first.toULongLong());
}
delete pWinRar;
m_Mutex.unlock();
return FileList;
}
void CRarWorker::OnExtractAllFiles()
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("x");
if(!m_Password.isEmpty())
Arguments.append("-p" + m_Password);
Arguments.append(m_ArchivePath);
Arguments.append(m_WorkingPath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "unrar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
}
void CRarWorker::OnInsertAllFiles()
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("a");
Arguments.append("-m0");
if(!m_Password.isEmpty())
Arguments.append("-hp" + m_Password);
if(m_PartSize != -1)
Arguments.append("-v" + QString::number(m_PartSize) + "b");
if(!m_CommentPath.isEmpty())
Arguments.append("-z" + m_CommentPath);
Arguments.append(m_ArchivePath);
Arguments.append(m_WorkingPath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "rar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
}
void CRarWorker::OnExtractFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("x");
if(!m_Password.isEmpty())
Arguments.append("-p" + m_Password);
Arguments.append(m_ArchivePath);
foreach(const QString& File, FileList)
Arguments.append(File);
Arguments.append(m_WorkingPath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "unrar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
}
void CRarWorker::OnInsertFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("a");
Arguments.append("-m0");
Arguments.append("-ep");
Arguments.append("-ap" + Split2(Split2(m_ArchivePath, "/", true).second, ".", true).first.replace(" ", "_"));
if(!m_Password.isEmpty())
Arguments.append("-hp" + m_Password);
if(m_PartSize != -1)
Arguments.append("-v" + QString::number(m_PartSize) + "b");
if(!m_CommentPath.isEmpty())
Arguments.append("-z" + m_CommentPath);
Arguments.append(m_ArchivePath);
foreach(const QString& File, FileList)
{
StrPair RootName = Split2(File, "\\", true);
if(RootName.second.isEmpty())
{
RootName.second = RootName.first;
RootName.first = "";
}
QString FileName = (RootName.first.isEmpty() ? m_WorkingPath : RootName.first) + RootName.second;
Arguments.append(FileName);
}
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "rar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
}

View File

@ -0,0 +1,147 @@
#pragma once
#include "../mischelpers_global.h"
#include "../Common/MT/ThreadLock.h"
#include "Archive.h"
class CArchiveWorker: public QObject
{
Q_OBJECT
public:
virtual double GetProgress() = 0;
virtual const QString& GetArchivePath() = 0;
virtual quint64 GetPartSize() = 0;
virtual QString GetPassword() = 0;
virtual bool HasUsedPassword() = 0;
virtual QMap<QString, quint64> GetFileList() = 0;
public slots:
virtual void OnExtractAllFiles() = 0;
virtual void OnInsertAllFiles() = 0;
virtual void OnExtractFiles(QStringList FileList) = 0;
virtual void OnInsertFiles(QStringList FileList) = 0;
protected:
friend class CArchiveThread;
virtual void LogError(const QString &Error) {m_Errors.append(Error);}
QMutex m_Mutex;
CThreadLock m_Lock;
QString m_WorkingPath;
QStringList m_Errors;
};
class MISCHELPERS_EXPORT CArchiveThread: public QThread
{
Q_OBJECT
public:
CArchiveThread(const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QStringList& Parts = QStringList());
CArchiveThread(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QString &CommentPath = "");
void Terminate();
static QStringList ListParts(const QString &ArchivePath, bool NamesOnly = false);
QMap<QString, quint64> GetFileList() {return m_Worker->GetFileList();}
void ExtractAllFiles() {m_Worker->m_Lock.Reset(); emit AsyncExtractAllFiles(); m_Worker->m_Lock.Lock();}
void InsertAllFiles() {m_Worker->m_Lock.Reset(); emit AsyncInsertAllFiles(); m_Worker->m_Lock.Lock();}
void ExtractFiles(QStringList FileList) {m_Worker->m_Lock.Reset(); emit AsyncExtractFiles(FileList);m_Worker->m_Lock.Lock();} // paths in archive
void InsertFiles(QStringList FileList) {m_Worker->m_Lock.Reset(); emit AsyncInsertFiles(FileList); m_Worker->m_Lock.Lock();} // paths relative to the WorkingPath
bool IsBusy() {if(!m_Worker->m_Mutex.tryLock()) return true; m_Worker->m_Mutex.unlock(); return false;}
double GetProgress() {return m_Worker->GetProgress();}
QStringList GetArchiveParts(bool NamesOnly = false) {return ListParts(m_Worker->GetArchivePath(), NamesOnly);}
quint64 GetPartSize() {return m_Worker->GetPartSize();}
QStringList GetErrors();
bool HasUsedPassword() {return m_Worker->HasUsedPassword();}
QString GetPassword() {return m_Worker->GetPassword();}
void run()
{
connect(this, SIGNAL(AsyncExtractAllFiles()), m_Worker, SLOT(OnExtractAllFiles()));
connect(this, SIGNAL(AsyncInsertAllFiles()), m_Worker, SLOT(OnInsertAllFiles()));
connect(this, SIGNAL(AsyncExtractFiles(QStringList)), m_Worker, SLOT(OnExtractFiles(QStringList)));
connect(this, SIGNAL(AsyncInsertFiles(QStringList)), m_Worker, SLOT(OnInsertFiles(QStringList)));
m_Worker->m_Lock.Release();
exec();
}
void stop()
{
quit();
wait();
}
signals:
void AsyncExtractAllFiles();
void AsyncInsertAllFiles();
void AsyncExtractFiles(QStringList FileList);
void AsyncInsertFiles(QStringList FileList);
protected:
CArchiveWorker* m_Worker;
};
#ifdef USE_7Z
class MISCHELPERS_EXPORT C7zWorker: public CArchiveWorker, protected CArchive
{
Q_OBJECT
public:
C7zWorker(const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QStringList& Parts = QStringList());
~C7zWorker();
virtual double GetProgress() {return CArchive::GetProgress();}
virtual const QString& GetArchivePath() {return CArchive::GetArchivePath();}
quint64 GetPartSize() {return CArchive::GetPartSize();}
virtual bool HasUsedPassword() {return CArchive::HasUsedPassword();}
virtual QString GetPassword() {return CArchive::GetPassword();}
virtual QMap<QString, quint64> GetFileList();
public slots:
virtual void OnExtractAllFiles();
virtual void OnInsertAllFiles();
virtual void OnExtractFiles(QStringList FileList);
virtual void OnInsertFiles(QStringList FileList);
};
#endif
class MISCHELPERS_EXPORT CRarWorker: public CArchiveWorker
{
Q_OBJECT
public:
CRarWorker(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QString &CommentPath = "");
virtual double GetProgress() {return 0;}
virtual const QString& GetArchivePath() {return m_ArchivePath;}
quint64 GetPartSize() {return m_PartSize;}
virtual bool HasUsedPassword() {ASSERT(0); return false;} // rar should notbe used for unpacking
virtual QString GetPassword() {return m_Password;}
virtual QMap<QString, quint64> GetFileList();
public slots:
virtual void OnExtractAllFiles();
virtual void OnInsertAllFiles();
virtual void OnExtractFiles(QStringList FileList);
virtual void OnInsertFiles(QStringList FileList);
protected:
QString m_ArchivePath;
QString m_Password;
quint64 m_PartSize;
QString m_WinRarPath;
QString m_CommentPath;
};

View File

@ -0,0 +1,106 @@
#include "stdafx.h"
#include "ArchiveUpdater.h"
#include "Archive.h"
#ifdef USE_7Z
CArchiveUpdater::CArchiveUpdater(CArchive* pArchive, const QMap<int,CArchiveIO*>& Files)
{
m_pArchive = pArchive;
m_Files = Files;
}
CArchiveUpdater::~CArchiveUpdater()
{
foreach(CArchiveIO* pFile, m_Files)
delete pFile;
}
STDMETHODIMP CArchiveUpdater::SetTotal(UInt64 size)
{
m_pArchive->m_Progress.SetTotal(size);
return S_OK;
}
STDMETHODIMP CArchiveUpdater::SetCompleted(const UInt64 *completeValue)
{
ASSERT(completeValue);
m_pArchive->m_Progress.SetCompleted(*completeValue);
return S_OK;
}
STDMETHODIMP CArchiveUpdater::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
{
if (newData != NULL)
*newData = true;
if (newProperties != NULL)
*newProperties = true;
if (indexInArchive != NULL)
*indexInArchive = (UInt32)-1;
return S_OK;
}
STDMETHODIMP CArchiveUpdater::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
if (propID == kpidIsAnti)
prop = false;
else
{
Q_ASSERT(index < m_pArchive->m_Files.count());
int ArcIndex = m_pArchive->m_Files[index].ArcIndex;
switch(propID)
{
case kpidPath: prop = m_pArchive->FileProperty(ArcIndex, "Path").toString().toStdWString().c_str(); break;
case kpidSize: prop = m_pArchive->FileProperty(ArcIndex, "Size").toULongLong(); break;
case kpidAttrib: prop = m_pArchive->FileProperty(ArcIndex, "Attrib").toUInt(); break;
case kpidIsDir: prop = m_pArchive->FileProperty(ArcIndex, "IsDir").toBool(); break;
case kpidCTime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "CTime").toULongLong(); // ToDo
prop = *reinterpret_cast<FILETIME*>(&date);} break;
case kpidATime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "ATime").toULongLong(); // ToDo
prop = *reinterpret_cast<FILETIME*>(&date);} break;
case kpidMTime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "MTime").toULongLong(); // ToDo
prop = *reinterpret_cast<FILETIME*>(&date);} break;
//default: Q_ASSERT(0); // ToDo
}
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CArchiveUpdater::GetStream(UInt32 index, ISequentialInStream **inStream)
{
*inStream = NULL;
Q_ASSERT(index < m_pArchive->m_Files.count());
int ArcIndex = m_pArchive->m_Files[index].ArcIndex;
//TRACE(L"Archive Item '%S'", QS2CS(m_pArchive->FileProperty(ArcIndex, "Path").toString()));
CArchiveIO* pFile = m_Files.take(ArcIndex);
if(pFile == NULL)
{
QTemporaryFile* pTemp = new QTemporaryFile;
QMap<int, QIODevice*> Files;
Files.insert(ArcIndex, pTemp);
if(!m_pArchive->Extract(&Files,false))
{
m_pArchive->LogError(QString("Failed to extract old %1 file form source archive").arg(m_pArchive->FileProperty(ArcIndex, "Path").toString()));
TRACE(L"Failed to extract old file form source archive");
delete pTemp;
return E_ABORT;
}
pFile = new CArchiveIO(pTemp, QIODevice::ReadOnly);
}
if (!pFile->Open(QIODevice::ReadOnly))
return S_FALSE;
CMyComPtr<ISequentialInStream> inStreamLoc = pFile;
*inStream = inStreamLoc.Detach();
return S_OK;
}
STDMETHODIMP CArchiveUpdater::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
QString Password = m_pArchive->GetPassword(true);
*passwordIsDefined = Password.isEmpty() ? false : true;
return StringToBstr(Password.toStdWString().c_str(), password);
}
#endif

View File

@ -0,0 +1,38 @@
#pragma once
#include "ArchiveHelper.h"
#ifdef USE_7Z
class CArchiveUpdater: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
CArchiveUpdater(CArchive* pArchive, const QMap<int,CArchiveIO*>& Files);
~CArchiveUpdater();
// IProgress
STDMETHOD(SetTotal)(UInt64 size);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IArchiveUpdateCallback2
STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
STDMETHOD(SetOperationResult)(Int32 operationResult) {return S_OK;}
// depricated
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) {return S_FALSE;}
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) {return S_FALSE;}
// ICryptoGetTextPassword2
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
protected:
CArchive* m_pArchive;
QMap<int,CArchiveIO*> m_Files;
};
#endif

View File

@ -0,0 +1,37 @@
#include "stdafx.h"
#include "CachedArchive.h"
#ifdef USE_7Z
CCachedArchive::CCachedArchive(const QString &ArchivePath)
: CArchive(ArchivePath)
{
}
bool CCachedArchive::Extract(QMap<int, QIODevice*> *FileList, bool bDelete)
{
QMap<int, QIODevice*> Files;
foreach(int ArcIndex, FileList->keys())
{
if(!m_CacheMap.contains(ArcIndex))
Files.insert(ArcIndex, new QBuffer(&m_CacheMap[ArcIndex]));
}
if(!Files.isEmpty())
{
if(!CArchive::Extract(&Files))
return false;
}
foreach(int ArcIndex, FileList->keys())
{
QIODevice* pIO = FileList->value(ArcIndex);
pIO->open(QIODevice::WriteOnly);
pIO->write(m_CacheMap.value(ArcIndex));
pIO->close();
delete pIO;
}
return true;
}
#endif

View File

@ -0,0 +1,22 @@
#pragma once
#include "../mischelpers_global.h"
#include "Archive.h"
#ifdef USE_7Z
class MISCHELPERS_EXPORT CCachedArchive: public CArchive
{
public:
CCachedArchive(const QString &ArchivePath);
bool Update(QMap<int, QIODevice*> *FileList, bool bDelete = true) {LogError("Cachen archives can not be updated"); return false;}
bool Extract(QMap<int, QIODevice*> *FileList, bool bDelete = true);
protected:
QMap<int, QByteArray> m_CacheMap;
};
#endif

View File

@ -0,0 +1,186 @@
#include "stdafx.h"
#include "SplitFile.h"
CSplitFile::CSplitFile(const QString &name, quint64 size)
{
m_PartSize = size;
m_FileName = name;
m_Position = 0;
m_Index = -1;
}
CSplitFile::~CSplitFile()
{
QIODevice::close();
}
QString CSplitFile::GetPartName(int Index)
{
QString Ext = QString::number(Index+1);
while(Ext.length() < 3)
Ext.prepend("0");
return m_FileName + "." + Ext;
}
bool CSplitFile::open(OpenMode flags)
{
if(flags & ReadOnly)
{
for(int i = 0;; i++)
{
QString PartName = GetPartName(i);
if(!QFile::exists(PartName))
break;
QFile* pFile = new QFile(PartName, this);
pFile->open(flags);
m_FileParts.append(pFile);
}
}
m_Index = 0; // we are open for business
return QIODevice::open(flags);
}
void CSplitFile::close()
{
m_Position = 0;
m_Index = -1;
foreach(QFile* pPart, m_FileParts)
{
pPart->close();
delete pPart;
}
m_FileParts.clear();
QIODevice::close();
}
qint64 CSplitFile::size() const
{
quint64 uSize = 0;
foreach(QFile* pPart, m_FileParts)
uSize += pPart->size();
return uSize;
}
qint64 CSplitFile::pos() const
{
return m_Position;
}
bool CSplitFile::seek(qint64 offset)
{
if(m_Index == -1)
return false;
qint64 iToGo = offset - m_Position;
int i = m_Index;
while(iToGo)
{
if(iToGo > 0)
{
qint64 tmp = m_FileParts[i]->pos();
if(tmp + iToGo < (qint64)m_PartSize)
{
m_FileParts[i]->seek(tmp + iToGo);
//iToGo = 0;
break;
}
else
{
if(++i == m_FileParts.count())
{
QFile* pFile = new QFile(GetPartName(m_Index), this);
pFile->open(openMode());
m_FileParts.append(pFile);
}
iToGo -= tmp;
m_FileParts[i]->seek(0);
}
}
else if(iToGo < 0)
{
qint64 tmp = m_FileParts[i]->pos();
if(tmp -iToGo >= 0)
{
m_FileParts[i]->seek(tmp + iToGo);
//iToGo = 0;
break;
}
else
{
if(--i == -1)
return false;
iToGo += tmp;
m_FileParts[i]->seek(m_FileParts[i]->size()-1);
}
}
}
m_Index = i;
m_Position = offset;
return true;
}
qint64 CSplitFile::readData(char *data, qint64 maxlen)
{
if(m_Index == -1)
return -1;
quint64 read = 0;
while(maxlen - read)
{
if(m_Index >= m_FileParts.count())
break;
quint64 uToGo = maxlen - read;
quint64 uAvail = m_FileParts[m_Index]->size() - m_FileParts[m_Index]->pos();
if(uToGo > uAvail)
uToGo = uAvail;
quint64 Tmp = m_FileParts[m_Index]->read(data + read, uToGo);
if(Tmp == -1)
return -1;
read += Tmp;
m_Position += Tmp;
if(m_FileParts[m_Index]->pos() >= m_FileParts[m_Index]->size())
m_Index++;
}
return read;
}
qint64 CSplitFile::writeData(const char *data, qint64 len)
{
if(m_Index == -1)
return -1;
quint64 writen = 0;
while(len - writen)
{
if(m_Index >= m_FileParts.count())
{
QFile* pFile = new QFile(GetPartName(m_Index), this);
pFile->open(openMode());
m_FileParts.append(pFile);
}
quint64 uToGo = len - writen;
quint64 uAvail = m_PartSize - m_FileParts[m_Index]->pos();
if(uToGo > uAvail)
uToGo = uAvail;
quint64 Tmp = m_FileParts[m_Index]->write(data + writen, uToGo);
if(Tmp == -1)
return -1;
writen += Tmp;
m_Position += Tmp;
if(m_FileParts[m_Index]->pos() >= (qint64)m_PartSize)
m_Index++;
}
return writen;
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CSplitFile : public QIODevice
{
Q_OBJECT
public:
CSplitFile(const QString &name, quint64 size = -1);
~CSplitFile();
virtual bool open(OpenMode flags);
virtual void close();
virtual qint64 size() const;
virtual qint64 pos() const;
virtual bool seek(qint64 offset);
virtual bool atEnd() const {return pos() >= size();}
protected:
virtual qint64 readData(char *data, qint64 maxlen);
virtual qint64 writeData(const char *data, qint64 len);
QString GetPartName(int Index);
quint64 m_PartSize;
QString m_FileName;
QVector<QFile*> m_FileParts;
quint64 m_Position;
int m_Index;
};

View File

@ -144,7 +144,7 @@ QRegularExpression CFinder::GetRegExp() const
if(m_pRegExp->isChecked())
Exp = m_pSearch->text();
else
Exp = QRegularExpression::wildcardToRegularExpression("*" + m_pSearch->text() + "*");
Exp = ".*" + QRegularExpression::escape(m_pSearch->text()) + ".*";
return QRegularExpression(Exp, m_pCaseSensitive->isChecked() ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption);
}

View File

@ -0,0 +1,37 @@
#include "stdafx.h"
#include "ThreadLock.h"
/**********************************************************************************************
* CThreadLock
*/
CThreadLock::CThreadLock()
{
m_Released = false;
}
void CThreadLock::Reset()
{
m_Mutex.lock();
m_Released = false;
m_Mutex.unlock();
}
bool CThreadLock::Lock(unsigned long time)
{
bool bRet = true;
m_Mutex.lock();
if(m_Released == false)
bRet = m_Wait.wait(&m_Mutex, time);
m_Mutex.unlock();
return bRet;
}
void CThreadLock::Release()
{
m_Mutex.lock();
m_Released = true;
m_Wait.wakeAll();
m_Mutex.unlock();
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "../../mischelpers_global.h"
#include <QMutex>
#include <QWaitCondition>
/**********************************************************************************************
* CThreadLock
* This class allows to wait for events form a differet thread.
* When Lock returns successfuly it is guaranted that the other thread have issued a release.
* This works undependant of the real order Lock and Release ware calles
*/
class MISCHELPERS_EXPORT CThreadLock
{
public:
CThreadLock();
void Reset();
bool Lock(unsigned long time = ULONG_MAX);
void Release();
protected:
QMutex m_Mutex;
QWaitCondition m_Wait;
bool m_Released;
};

View File

@ -20,7 +20,9 @@ public:
m_pMessageLabel = new QLabel(Prompt);
m_pMessageLabel->setMinimumWidth(300);
//m_pMessageLabel->setMinimumHeight(40);
m_pMessageLabel->setWordWrap(true);
//m_pMessageLabel->setAlignment(Qt::AlignTop);
m_pMainLayout->addWidget(m_pMessageLabel, 0, 0, 1, 1);
m_pProgressBar = new QProgressBar();

View File

@ -34,7 +34,19 @@ HEADERS += ./MiscHelpers.h \
./Common/TreeWidgetEx.h \
./Common/CheckList.h \
./Common/NeonEffect.h \
./Common/NetworkAccessManager.h
./Common/NetworkAccessManager.h \
./Common/MT/ThreadLock.h \
./Archive/Archive.h \
./Archive/ArchiveFS.h \
./Archive/ArchiveExtractor.h \
./Archive/ArchiveHelper.h \
./Archive/ArchiveInterface.h \
./Archive/ArchiveIO.h \
./Archive/ArchiveOpener.h \
./Archive/ArchiveThread.h \
./Archive/ArchiveUpdater.h \
./Archive/CachedArchive.h \
./Archive/SplitFile.h
SOURCES += ./MiscHelpers.cpp \
./stdafx.cpp \
@ -58,4 +70,16 @@ SOURCES += ./MiscHelpers.cpp \
./Common/SplitTreeView.cpp \
./Common/TabPanel.cpp \
./Common/TreeItemModel.cpp \
./Common/Xml.cpp
./Common/Xml.cpp \
./Common/MT/ThreadLock.cpp \
./Archive/Archive.cpp \
./Archive/ArchiveFS.cpp \
./Archive/ArchiveExtractor.cpp \
./Archive/ArchiveHelper.cpp \
./Archive/ArchiveInterface.cpp \
./Archive/ArchiveOpener.cpp \
./Archive/ArchiveThread.cpp \
./Archive/ArchiveUpdater.cpp \
./Archive/CachedArchive.cpp \
./Archive/SplitFile.cpp

View File

@ -189,6 +189,16 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Archive\Archive.cpp" />
<ClCompile Include="Archive\ArchiveExtractor.cpp" />
<ClCompile Include="Archive\ArchiveFS.cpp" />
<ClCompile Include="Archive\ArchiveHelper.cpp" />
<ClCompile Include="Archive\ArchiveInterface.cpp" />
<ClCompile Include="Archive\ArchiveOpener.cpp" />
<ClCompile Include="Archive\ArchiveThread.cpp" />
<ClCompile Include="Archive\ArchiveUpdater.cpp" />
<ClCompile Include="Archive\CachedArchive.cpp" />
<ClCompile Include="Archive\SplitFile.cpp" />
<ClCompile Include="Common\CheckableMessageBox.cpp" />
<ClCompile Include="Common\ComboInputDialog.cpp" />
<ClCompile Include="Common\Common.cpp" />
@ -198,6 +208,7 @@
<ClCompile Include="Common\ItemChooser.cpp" />
<ClCompile Include="Common\KeyValueInputDialog.cpp" />
<ClCompile Include="Common\ListItemModel.cpp" />
<ClCompile Include="Common\MT\ThreadLock.cpp" />
<ClCompile Include="Common\MultiLineInputDialog.cpp" />
<ClCompile Include="Common\OtherFunctions.cpp" />
<ClCompile Include="Common\PanelView.cpp" />
@ -222,6 +233,17 @@
<QtMoc Include="Common\CheckableMessageBox.h" />
<QtMoc Include="Common\ComboInputDialog.h" />
<QtMoc Include="Common\CheckList.h" />
<ClInclude Include="Archive\Archive.h" />
<ClInclude Include="Archive\ArchiveExtractor.h" />
<ClInclude Include="Archive\ArchiveFS.h" />
<ClInclude Include="Archive\ArchiveHelper.h" />
<ClInclude Include="Archive\ArchiveInterface.h" />
<ClInclude Include="Archive\ArchiveIO.h" />
<ClInclude Include="Archive\ArchiveOpener.h" />
<QtMoc Include="Archive\ArchiveThread.h" />
<ClInclude Include="Archive\ArchiveUpdater.h" />
<ClInclude Include="Archive\CachedArchive.h" />
<QtMoc Include="Archive\SplitFile.h" />
<ClInclude Include="Common\Common.h" />
<ClInclude Include="Common\DebugHelpers.h" />
<ClInclude Include="Common\ExitDialog.h" />
@ -244,6 +266,7 @@
<QtMoc Include="Common\TreeItemModel.h" />
<QtMoc Include="Common\TreeViewEx.h" />
<QtMoc Include="Common\TreeWidgetEx.h" />
<ClInclude Include="Common\MT\ThreadLock.h" />
<QtMoc Include="Common\NeonEffect.h" />
<ClInclude Include="Common\OtherFunctions.h" />
<ClInclude Include="Common\qRC4.h" />

View File

@ -22,6 +22,12 @@
<Filter Include="Common">
<UniqueIdentifier>{964acff8-ecee-4dfc-939d-e2406a533100}</UniqueIdentifier>
</Filter>
<Filter Include="Archive">
<UniqueIdentifier>{1e331c49-0544-4a02-83e5-e47774ab5fac}</UniqueIdentifier>
</Filter>
<Filter Include="Common\MT">
<UniqueIdentifier>{55ef64ac-4671-4600-8e4a-ca56d181c6ec}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="MiscHelpers.cpp">
@ -93,6 +99,39 @@
<ClCompile Include="Common\OtherFunctions.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Archive\Archive.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\ArchiveExtractor.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\ArchiveHelper.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\ArchiveInterface.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\ArchiveOpener.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\ArchiveUpdater.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\CachedArchive.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\SplitFile.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Archive\ArchiveThread.cpp">
<Filter>Archive</Filter>
</ClCompile>
<ClCompile Include="Common\MT\ThreadLock.cpp">
<Filter>Common\MT</Filter>
</ClCompile>
<ClCompile Include="Archive\ArchiveFS.cpp">
<Filter>Archive</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="MiscHelpers.h">
@ -128,6 +167,36 @@
<ClInclude Include="Common\OtherFunctions.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Archive\Archive.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Archive\ArchiveExtractor.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Archive\ArchiveHelper.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Archive\ArchiveInterface.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Archive\ArchiveIO.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Archive\ArchiveOpener.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Archive\ArchiveUpdater.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Archive\CachedArchive.h">
<Filter>Archive</Filter>
</ClInclude>
<ClInclude Include="Common\MT\ThreadLock.h">
<Filter>Common\MT</Filter>
</ClInclude>
<ClInclude Include="Archive\ArchiveFS.h">
<Filter>Archive</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="mischelpers_global.h">
@ -195,6 +264,12 @@
<QtMoc Include="Common\CheckList.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Archive\SplitFile.h">
<Filter>Archive</Filter>
</QtMoc>
<QtMoc Include="Archive\ArchiveThread.h">
<Filter>Archive</Filter>
</QtMoc>
<QtMoc Include="Common\NeonEffect.h">
<Filter>Common</Filter>
</QtMoc>

View File

@ -26,10 +26,13 @@
#include "../MiscHelpers/Common/OtherFunctions.h"
#include "../MiscHelpers/Common/Common.h"
#include "Windows/SupportDialog.h"
#include "../MiscHelpers/Archive/Archive.h"
#include "../MiscHelpers/Archive/ArchiveFS.h"
#include "Views/FileView.h"
#include "OnlineUpdater.h"
#include "../MiscHelpers/Common/NeonEffect.h"
#include <QVariantAnimation>
#include <QSessionManager>
CSbiePlusAPI* theAPI = NULL;
@ -110,6 +113,10 @@ CSandMan::CSandMan(QWidget *parent)
QApplication::instance()->installNativeEventFilter(new CNativeEventFilter);
#endif
CArchive::Init();
m_pTranslations = new C7zFileEngineHandler(QApplication::applicationDirPath() + "/translations.7z", "lang", this);
theGUI = this;
m_DarkTheme = false;
@ -447,6 +454,7 @@ void CSandMan::CreateMenus(bool bAdvanced)
m_pMenuFile = m_pMenuBar->addMenu(tr("&Sandbox"));
m_pNewBox = m_pMenuFile->addAction(CSandMan::GetIcon("NewBox"), tr("Create New Box"), this, SLOT(OnSandBoxAction()));
m_pNewGroup = m_pMenuFile->addAction(CSandMan::GetIcon("Group"), tr("Create Box Group"), this, SLOT(OnSandBoxAction()));
m_pImportBox = m_pMenuFile->addAction(CSandMan::GetIcon("UnPackBox"), tr("Import Box"), this, SLOT(OnSandBoxAction()));
m_pMenuFile->addSeparator();
m_pEmptyAll = m_pMenuFile->addAction(CSandMan::GetIcon("EmptyAll"), tr("Terminate All Processes"), this, SLOT(OnEmptyAll()));
m_pDisableForce = m_pMenuFile->addAction(tr("Pause Forcing Programs"), this, SLOT(OnDisableForce()));
@ -645,6 +653,7 @@ void CSandMan::CreateOldMenus()
m_pSandbox->addSeparator();
m_pNewBox = m_pSandbox->addAction(CSandMan::GetIcon("NewBox"), tr("Create New Sandbox"), this, SLOT(OnSandBoxAction()));
m_pNewGroup = m_pSandbox->addAction(CSandMan::GetIcon("Group"), tr("Create New Group"), this, SLOT(OnSandBoxAction()));
m_pImportBox = m_pSandbox->addAction(CSandMan::GetIcon("UnPackBox"), tr("Import Sandbox"), this, SLOT(OnSandBoxAction()));
QAction* m_pSetContainer = m_pSandbox->addAction(CSandMan::GetIcon("Advanced"), tr("Set Container Folder"), this, SLOT(OnSettingsAction()));
m_pSetContainer->setData(CSettingsWindow::eAdvanced);
@ -2167,10 +2176,48 @@ void CSandMan::OnSandBoxAction()
{
QAction* pAction = qobject_cast<QAction*>(sender());
if(pAction == m_pNewBox)
if (pAction == m_pNewBox)
GetBoxView()->AddNewBox();
else if(pAction == m_pNewGroup)
else if (pAction == m_pNewGroup)
GetBoxView()->AddNewGroup();
else if (pAction == m_pImportBox)
{
QString Value = QFileDialog::getOpenFileName(this, tr("Select file name"), "", tr("7-zip Archive (*.7z)"));
if (Value.isEmpty())
return;
StrPair PathName = Split2(Value, "/", true);
StrPair NameEx = Split2(PathName.second, ".", true);
QString Name = NameEx.first;
CSandBoxPtr pBox;
for (;;) {
pBox = theAPI->GetBoxByName(Name);
if (pBox.isNull())
break;
Name = QInputDialog::getText(this, "Sandboxie-Plus", tr("This Name is already in use, please select an alternative box name"), QLineEdit::Normal, Name);
if (Name.isEmpty())
return;
}
SB_PROGRESS Status = theAPI->CreateBox(Name);
if (!Status.IsError()) {
pBox = theAPI->GetBoxByName(Name);
if (pBox) {
auto pBoxEx = pBox.objectCast<CSandBoxPlus>();
Status = pBoxEx->ImportBox(Value);
}
}
if (Status.GetStatus() == OP_ASYNC) {
Status = theGUI->AddAsyncOp(Status.GetValue(), true, tr("Importing: %1").arg(Value));
if (Status.IsError()) {
theGUI->DeleteBoxContent(pBox, CSandMan::eForDelete);
pBox->RemoveBox();
}
}
else
CSandMan::CheckResults(QList<SB_STATUS>() << Status);
}
}
void CSandMan::OnEmptyAll()
@ -2832,6 +2879,13 @@ QString CSandMan::FormatError(const SB_STATUS& Error)
case SB_NameExists: Message = tr("A sandbox with that name already exists"); break;
case SB_PasswordBad: Message = tr("The config password must not be longer than 64 characters"); break;
case SB_Canceled: Message = tr("The operation was canceled by the user"); break;
case SBX_7zNotReady: Message = tr("Import/Export not available, 7z.dll could not be loaded"); break;
case SBX_7zCreateFailed: Message = tr("Failed to Create Box Archive"); break;
case SBX_7zOpenFailed: Message = tr("Failed to open the 7z archive"); break;
case SBX_7zExtractFailed: Message = tr("Failed to Unpack Box Archive"); break;
case SBX_NotBoxArchive: Message = tr("The sellected 7z file is NOT a Box Archive"); break;
default: return tr("Unknown Error Status: 0x%1").arg((quint32)Error.GetStatus(), 8, 16, QChar('0'));
}
@ -3033,7 +3087,11 @@ void CSandMan::LoadLanguage(const QString& Lang, const QString& Module, int Inde
QString LangAux = Lang; // Short version as fallback
LangAux.truncate(LangAux.lastIndexOf('_'));
QString LangDir = QApplication::applicationDirPath() + "/translations/";
QString LangDir;
if (m_pTranslations->IsOpen())
LangDir = m_pTranslations->Prefix() + "/";
else
LangDir = QApplication::applicationDirPath() + "/translations/";
QString LangPath = LangDir + Module + "_";
bool bAux = false;

View File

@ -282,6 +282,7 @@ private:
QMenu* m_pMenuFile;
QAction* m_pNewBox;
QAction* m_pNewGroup;
QAction* m_pImportBox;
QAction* m_pEmptyAll;
QAction* m_pWndFinder;
QAction* m_pDisableForce;
@ -381,6 +382,7 @@ public:
quint32 m_LanguageId;
bool m_DarkTheme;
bool m_FusionTheme;
class C7zFileEngineHandler* m_pTranslations;
};

View File

@ -8,6 +8,8 @@
#include "BoxMonitor.h"
#include "..\MiscHelpers\Common\OtherFunctions.h"
#include "../QSbieAPI/SbieUtils.h"
#include "../MiscHelpers/Archive/Archive.h"
#include <QtConcurrent>
CSbiePlusAPI::CSbiePlusAPI(QObject* parent) : CSbieAPI(parent)
{
@ -147,6 +149,160 @@ CSandBoxPlus::~CSandBoxPlus()
{
}
class QFileX : public QFile {
public:
QFileX(const QString& path, const CSbieProgressPtr& pProgress, CArchive* pArchive) : QFile(path)
{
m_pProgress = pProgress;
m_pArchive = pArchive;
}
bool open(OpenMode flags) override
{
if (m_pProgress->IsCanceled())
return false;
m_pProgress->ShowMessage(Split2(fileName(), "/", true).second);
m_pProgress->SetProgress((int)(m_pArchive->GetProgress() * 100.0));
return QFile::open(flags);
}
protected:
CSbieProgressPtr m_pProgress;
CArchive* m_pArchive;
};
void CSandBoxPlus::ExportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ExportPath, const QString& RootPath, const QString& Section)
{
//CArchive Archive(ExportPath + ".tmp");
CArchive Archive(ExportPath);
QMap<int, QIODevice*> Files;
//QTemporaryFile* pConfigFile = new QTemporaryFile;
//pConfigFile->open();
//pConfigFile->write(Section.toUtf8());
//pConfigFile->close();
//
//int ArcIndex = Archive.AddFile("BoxConfig.ini");
//Files.insert(ArcIndex, pConfigFile);
QFile File(RootPath + "\\" + "BoxConfig.ini");
if (File.open(QFile::WriteOnly)) {
File.write(Section.toUtf8());
File.close();
}
QStringList FileList = ListDir(RootPath + "\\");
foreach(const QString& File, FileList)
{
StrPair RootName = Split2(File, "\\", true);
if(RootName.second.isEmpty())
{
RootName.second = RootName.first;
RootName.first = "";
}
int ArcIndex = Archive.AddFile(RootName.second);
if(ArcIndex != -1)
{
QString FileName = (RootName.first.isEmpty() ? RootPath + "\\" : RootName.first) + RootName.second;
Files.insert(ArcIndex, new QFileX(FileName, pProgress, &Archive));
}
//else
// this file is already present in the archive, this should not happen !!!
}
SB_STATUS Status = SB_OK;
if (!Archive.Update(&Files))
Status = SB_ERR((ESbieMsgCodes)SBX_7zCreateFailed);
//if(!Status.IsError() && !pProgress->IsCanceled())
// QFile::rename(ExportPath + ".tmp", ExportPath);
//else
// QFile::remove(ExportPath + ".tmp");
File.remove();
pProgress->Finish(Status);
}
SB_PROGRESS CSandBoxPlus::ExportBox(const QString& FileName)
{
if (!CArchive::IsInit())
return SB_ERR((ESbieMsgCodes)SBX_7zNotReady);
if (theAPI->HasProcesses(m_Name))
return SB_ERR(SB_SnapIsRunning); // todo
if (!IsInitialized())
return SB_ERR(SB_SnapIsEmpty); // todo
QString Section = theAPI->SbieIniGetEx(m_Name, "");
CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
QtConcurrent::run(CSandBoxPlus::ExportBoxAsync, pProgress, FileName, m_FilePath, Section);
return SB_PROGRESS(OP_ASYNC, pProgress);
}
void CSandBoxPlus::ImportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ImportPath, const QString& RootPath, const QString& BoxName)
{
CArchive Archive(ImportPath);
if (Archive.Open() != 1) {
pProgress->Finish(SB_ERR((ESbieMsgCodes)SBX_7zOpenFailed));
return;
}
bool IsBoxArchive = false;
QMap<int, QIODevice*> Files;
for (int i = 0; i < Archive.FileCount(); i++) {
int ArcIndex = Archive.FindByIndex(i);
if(Archive.FileProperty(ArcIndex, "IsDir").toBool())
continue;
QString File = Archive.FileProperty(ArcIndex, "Path").toString();
if (File == "BoxConfig.ini")
IsBoxArchive = true;
Files.insert(ArcIndex, new QFileX(CArchive::PrepareExtraction(File, RootPath + "\\"), pProgress, &Archive));
}
if(!IsBoxArchive) {
pProgress->Finish(SB_ERR((ESbieMsgCodes)SBX_NotBoxArchive));
return;
}
SB_STATUS Status = SB_OK;
if (!Archive.Extract(&Files))
Status = SB_ERR((ESbieMsgCodes)SBX_7zExtractFailed);
if (!Status.IsError() && !pProgress->IsCanceled())
{
QFile File(RootPath + "\\" + "BoxConfig.ini");
if (File.open(QFile::ReadOnly)) {
QMetaObject::invokeMethod(theAPI, "SbieIniSetSection", Qt::BlockingQueuedConnection, // run this in the main thread
Q_ARG(QString, BoxName),
Q_ARG(QString, QString::fromUtf8(File.readAll()))
);
File.close();
}
File.remove();
}
pProgress->Finish(Status);
}
SB_PROGRESS CSandBoxPlus::ImportBox(const QString& FileName)
{
if (!CArchive::IsInit())
return SB_ERR((ESbieMsgCodes)SBX_7zNotReady);
CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
QtConcurrent::run(CSandBoxPlus::ImportBoxAsync, pProgress, FileName, m_FilePath, m_Name);
return SB_PROGRESS(OP_ASYNC, pProgress);
}
void CSandBoxPlus::UpdateDetails()
{
//m_bLogApiFound = GetTextList("OpenPipePath", false).contains("\\Device\\NamedPipe\\LogAPI");

View File

@ -3,6 +3,15 @@
#include "../QSbieAPI/SbieAPI.h"
#include "BoxJob.h"
enum ESbieExMsgCodes
{
SBX_FirstError = SB_LastError,
SBX_7zNotReady,
SBX_7zCreateFailed,
SBX_7zOpenFailed,
SBX_7zExtractFailed,
SBX_NotBoxArchive
};
class CSbiePlusAPI : public CSbieAPI
{
@ -27,6 +36,7 @@ public:
private slots:
virtual void OnStartFinished();
virtual void SbieIniSetSection(const QString& Section, const QString& Value) { SbieIniSet(Section, "", Value); }
protected:
friend class CSandBoxPlus;
@ -56,6 +66,9 @@ public:
CSandBoxPlus(const QString& BoxName, class CSbieAPI* pAPI);
virtual ~CSandBoxPlus();
SB_PROGRESS ExportBox(const QString& FileName);
SB_PROGRESS ImportBox(const QString& FileName);
virtual void UpdateDetails();
virtual void ScanStartMenu();
@ -167,6 +180,9 @@ protected:
void AddJobToQueue(CBoxJob* pJob);
void StartNextJob();
static void ExportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ExportPath, const QString& RootPath, const QString& Section);
static void ImportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ImportPath, const QString& RootPath, const QString& BoxName);
QList<QSharedPointer<CBoxJob>> m_JobQueue;
bool m_bLogApiFound;

View File

@ -185,10 +185,14 @@ void CSbieView::CreateMenu()
m_pMenuContent->addSeparator();
m_pMenuExplore = m_pMenuContent->addAction(CSandMan::GetIcon("Explore"), tr("Explore Content"), this, SLOT(OnSandBoxAction()));
m_pMenuRegEdit = m_pMenuContent->addAction(CSandMan::GetIcon("RegEdit"), tr("Open Registry"), this, SLOT(OnSandBoxAction()));
m_pMenuSnapshots = m_pMenuBox->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction()));
m_pMenuRecover = m_pMenuBox->addAction(CSandMan::GetIcon("Recover"), tr("Recover Files"), this, SLOT(OnSandBoxAction()));
m_pMenuCleanUp = m_pMenuBox->addAction(CSandMan::GetIcon("Erase"), tr("Delete Content"), this, SLOT(OnSandBoxAction()));
m_pMenuBox->addSeparator();
m_pMenuOptions = m_pMenuBox->addAction(CSandMan::GetIcon("Options"), tr("Sandbox Options"), this, SLOT(OnSandBoxAction()));
QFont f = m_pMenuOptions->font();
f.setBold(true);
m_pMenuOptions->setFont(f);
m_pMenuPresets = m_pMenuBox->addMenu(CSandMan::GetIcon("Presets"), tr("Sandbox Presets"));
m_pMenuPresetsAdmin = new QActionGroup(m_pMenuPresets);
@ -212,9 +216,8 @@ void CSbieView::CreateMenu()
m_pMenuPresetsRecovery->setCheckable(true);
m_pMenuTools = m_pMenuBox->addMenu(CSandMan::GetIcon("Maintenance"), tr("Sandbox Tools"));
m_pMenuSnapshots = m_pMenuTools->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction()));
m_pMenuTools->addSeparator();
m_pMenuDuplicate = m_pMenuTools->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Box Config"), this, SLOT(OnSandBoxAction()));
m_pMenuExport = m_pMenuTools->addAction(CSandMan::GetIcon("PackBox"), tr("Export Box"), this, SLOT(OnSandBoxAction()));
m_pMenuRename = m_pMenuBox->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction()));
m_pMenuMoveTo = m_pMenuBox->addMenu(CSandMan::GetIcon("Group"), tr("Move Sandbox"));
@ -303,6 +306,7 @@ void CSbieView::CreateOldMenu()
m_pMenuTools->addSeparator();
m_pMenuDuplicate = m_pMenuTools->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Sandbox Config"), this, SLOT(OnSandBoxAction()));
m_pMenuExport = m_pMenuTools->addAction(CSandMan::GetIcon("PackBox"), tr("Export Sandbox"), this, SLOT(OnSandBoxAction()));
m_pMenuTools->addSeparator();
m_pMenuRefresh = m_pMenuTools->addAction(CSandMan::GetIcon("Refresh"), tr("Refresh Info"), this, SLOT(OnSandBoxAction()));
@ -1226,6 +1230,20 @@ void CSbieView::OnSandBoxAction(QAction* Action, const QList<CSandBoxPtr>& SandB
Results.append(Status);
}
else if (Action == m_pMenuExport)
{
QString Value = QFileDialog::getSaveFileName(this, tr("Select file name"), SandBoxes.first()->GetName() + ".7z", tr("7-zip Archive (*.7z)"));
if (Value.isEmpty())
return;
CSandBoxPtr pBox = SandBoxes.first();
auto pBoxEx = pBox.objectCast<CSandBoxPlus>();
SB_PROGRESS Status = pBoxEx->ExportBox(Value);
if (Status.GetStatus() == OP_ASYNC)
theGUI->AddAsyncOp(Status.GetValue(), false, tr("Exporting: %1").arg(Value));
else
Results.append(Status);
}
else if (Action == m_pMenuRename)
{
QString OldValue = SandBoxes.first()->GetName().replace("_", " ");

View File

@ -158,6 +158,7 @@ private:
QAction* m_pMenuRemove;
QMenu* m_pMenuTools;
QAction* m_pMenuDuplicate;
QAction* m_pMenuExport;
QAction* m_pMenuMoveUp;
//QAction* m_pMenuMoveBy;
QAction* m_pMenuMoveDown;