This commit is contained in:
Igor Pavlov
2003-12-11 00:00:00 +00:00
committed by Kornel Lesiński
commit 8c1b5c7b7e
982 changed files with 118799 additions and 0 deletions

4
7zip/Archive/7z/7z.def Executable file
View File

@@ -0,0 +1,4 @@
EXPORTS
CreateObject PRIVATE
GetHandlerProperty PRIVATE

533
7zip/Archive/7z/7z.dsp Executable file
View File

@@ -0,0 +1,533 @@
# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=7z - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "7z.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "7z - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /Yu"StdAfx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-zip\Formats\7z.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-zip\Formats\7z.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "7z - Win32 Release"
# Name "7z - Win32 Debug"
# Begin Group "Spec"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\7z.def
# End Source File
# Begin Source File
SOURCE=.\DllExports.cpp
# End Source File
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"StdAfx.h"
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Engine"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\7zCompressionMode.cpp
# End Source File
# Begin Source File
SOURCE=.\7zCompressionMode.h
# End Source File
# Begin Source File
SOURCE=.\7zDecode.cpp
# End Source File
# Begin Source File
SOURCE=.\7zDecode.h
# End Source File
# Begin Source File
SOURCE=.\7zEncode.cpp
# End Source File
# Begin Source File
SOURCE=.\7zEncode.h
# End Source File
# Begin Source File
SOURCE=.\7zExtract.cpp
# End Source File
# Begin Source File
SOURCE=.\7zFolderInStream.cpp
# End Source File
# Begin Source File
SOURCE=.\7zFolderInStream.h
# End Source File
# Begin Source File
SOURCE=.\7zFolderOutStream.cpp
# End Source File
# Begin Source File
SOURCE=.\7zFolderOutStream.h
# End Source File
# Begin Source File
SOURCE=.\7zHandler.cpp
# End Source File
# Begin Source File
SOURCE=.\7zHandler.h
# End Source File
# Begin Source File
SOURCE=.\7zHandlerOut.cpp
# End Source File
# Begin Source File
SOURCE=.\7zHeader.cpp
# End Source File
# Begin Source File
SOURCE=.\7zHeader.h
# End Source File
# Begin Source File
SOURCE=.\7zIn.cpp
# End Source File
# Begin Source File
SOURCE=.\7zIn.h
# End Source File
# Begin Source File
SOURCE=.\7zItem.h
# End Source File
# Begin Source File
SOURCE=.\7zMethodID.cpp
# End Source File
# Begin Source File
SOURCE=.\7zMethodID.h
# End Source File
# Begin Source File
SOURCE=.\7zMethods.cpp
# End Source File
# Begin Source File
SOURCE=.\7zMethods.h
# End Source File
# Begin Source File
SOURCE=.\7zOut.cpp
# End Source File
# Begin Source File
SOURCE=.\7zOut.h
# End Source File
# Begin Source File
SOURCE=.\7zProperties.cpp
# End Source File
# Begin Source File
SOURCE=.\7zProperties.h
# End Source File
# Begin Source File
SOURCE=.\7zSpecStream.cpp
# End Source File
# Begin Source File
SOURCE=.\7zSpecStream.h
# End Source File
# Begin Source File
SOURCE=.\7zUpdate.cpp
# End Source File
# Begin Source File
SOURCE=.\7zUpdate.h
# End Source File
# End Group
# Begin Group "Interface"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\IArchive.h
# End Source File
# Begin Source File
SOURCE=..\..\ICoder.h
# End Source File
# Begin Source File
SOURCE=..\..\ICoderProperties.h
# End Source File
# Begin Source File
SOURCE=..\..\IMyUnknown.h
# End Source File
# Begin Source File
SOURCE=..\..\IPassword.h
# End Source File
# Begin Source File
SOURCE=..\..\IProgress.h
# End Source File
# Begin Source File
SOURCE=..\..\IStream.h
# End Source File
# Begin Source File
SOURCE=..\..\PropID.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Buffer.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\IntToString.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\String.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\String.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringConvert.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringConvert.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringToInt.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringToInt.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Vector.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Vector.h
# End Source File
# End Group
# Begin Group "Archive Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Common\CodecsPath.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CodecsPath.h
# End Source File
# Begin Source File
SOURCE=..\Common\CoderLoader.h
# End Source File
# Begin Source File
SOURCE=..\Common\CoderMixer2.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CoderMixer2.h
# End Source File
# Begin Source File
SOURCE=..\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CrossThreadProgress.h
# End Source File
# Begin Source File
SOURCE=..\Common\InStreamWithCRC.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\InStreamWithCRC.h
# End Source File
# Begin Source File
SOURCE=..\Common\ItemNameUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ItemNameUtils.h
# End Source File
# Begin Source File
SOURCE=..\Common\OutStreamWithCRC.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\OutStreamWithCRC.h
# End Source File
# End Group
# Begin Group "7-Zip Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Common\InOutTempBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\InOutTempBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\LimitedStreams.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\LimitedStreams.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MultiStream.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MultiStream.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\ProgressUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\ProgressUtils.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamBinder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamBinder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamObjects.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamObjects.h
# End Source File
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Windows\DLL.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\DLL.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileDir.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileDir.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileFind.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileFind.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileIO.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileIO.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileName.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Handle.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Thread.h
# End Source File
# End Group
# Begin Group "Compress"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Compress\Copy\CopyCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Copy\CopyCoder.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\7z.ico
# End Source File
# End Target
# End Project

29
7zip/Archive/7z/7z.dsw Executable file
View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "7z"=".\7z.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

BIN
7zip/Archive/7z/7z.ico Executable file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,3 @@
// CompressionMethod.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,60 @@
// 7zCompressionMode.h
#pragma once
#ifndef __7Z_COMPRESSION_MODE_H
#define __7Z_COMPRESSION_MODE_H
#include "../../../Windows/PropVariant.h"
#include "7zMethodID.h"
namespace NArchive {
namespace N7z {
struct CProperty
{
PROPID PropID;
NWindows::NCOM::CPropVariant Value;
};
struct CMethodFull
{
CMethodID MethodID;
UINT32 NumInStreams;
UINT32 NumOutStreams;
bool IsSimpleCoder() const
{ return (NumInStreams == 1) && (NumOutStreams == 1); }
#ifdef EXCLUDE_COM
#else
CLSID EncoderClassID;
CSysString FilePath;
#endif
CObjectVector<CProperty> CoderProperties;
};
struct CBind
{
UINT32 InCoder;
UINT32 InStream;
UINT32 OutCoder;
UINT32 OutStream;
};
struct CCompressionMethodMode
{
CObjectVector<CMethodFull> Methods;
CRecordVector<CBind> Binds;
bool MultiThread;
bool PasswordIsDefined;
UString Password;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
CCompressionMethodMode(): PasswordIsDefined(false), MultiThread(false) {}
};
}}
#endif

377
7zip/Archive/7z/7zDecode.cpp Executable file
View File

@@ -0,0 +1,377 @@
// Decode.cpp
#include "StdAfx.h"
#include "7zDecode.h"
#include "../../Common/MultiStream.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "7zMethods.h"
#include "../../IPassword.h"
#ifdef COMPRESS_LZMA
#include "../../Compress/LZMA/LZMADecoder.h"
static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
#endif
#ifdef COMPRESS_PPMD
#include "../../Compress/PPMD/PPMDDecoder.h"
static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
#endif
#ifdef COMPRESS_BCJ_X86
#include "../../Compress/Branch/x86.h"
static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
#endif
#ifdef COMPRESS_BCJ2
#include "../../Compress/Branch/x86_2.h"
static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
#endif
#ifdef COMPRESS_DEFLATE
#include "../../Compress/Deflate/DeflateDecoder.h"
static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
#endif
#ifdef COMPRESS_BZIP2
#include "../../Compress/BZip2/BZip2Decoder.h"
static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
#endif
#ifdef COMPRESS_COPY
#include "../../Compress/Copy/CopyCoder.h"
static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };
#endif
#ifdef CRYPTO_7ZAES
#include "../../Crypto/7zAES/7zAES.h"
static NArchive::N7z::CMethodID k_7zAES = { { 0x6, 0xF1, 0x07, 0x01 }, 4 };
#endif
namespace NArchive {
namespace N7z {
static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
CBindInfoEx &bindInfo)
{
bindInfo.Coders.Clear();
bindInfo.CoderMethodIDs.Clear();
bindInfo.OutStreams.Clear();
bindInfo.InStreams.Clear();
bindInfo.BindPairs.Clear();
int i;
for (i = 0; i < folder.BindPairs.Size(); i++)
{
NCoderMixer2::CBindPair bindPair;
bindPair.InIndex = (UINT32)folder.BindPairs[i].InIndex;
bindPair.OutIndex = (UINT32)folder.BindPairs[i].OutIndex;
bindInfo.BindPairs.Add(bindPair);
}
UINT32 outStreamIndex = 0;
for (i = 0; i < folder.Coders.Size(); i++)
{
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
const CCoderInfo &coderInfo = folder.Coders[i];
coderStreamsInfo.NumInStreams = (UINT32)coderInfo.NumInStreams;
coderStreamsInfo.NumOutStreams = (UINT32)coderInfo.NumOutStreams;
bindInfo.Coders.Add(coderStreamsInfo);
const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
bindInfo.CoderMethodIDs.Add(altCoderInfo.MethodID);
for (UINT32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
bindInfo.OutStreams.Add(outStreamIndex);
}
for (i = 0; i < folder.PackStreams.Size(); i++)
bindInfo.InStreams.Add((UINT32)folder.PackStreams[i].Index);
}
static bool AreCodersEqual(const NCoderMixer2::CCoderStreamsInfo &a1,
const NCoderMixer2::CCoderStreamsInfo &a2)
{
return (a1.NumInStreams == a2.NumInStreams) &&
(a1.NumOutStreams == a2.NumOutStreams);
}
static bool AreBindPairsEqual(const NCoderMixer2::CBindPair &a1, const NCoderMixer2::CBindPair &a2)
{
return (a1.InIndex == a2.InIndex) &&
(a1.OutIndex == a2.OutIndex);
}
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
{
if (a1.Coders.Size() != a2.Coders.Size())
return false;
int i;
for (i = 0; i < a1.Coders.Size(); i++)
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
return false;
if (a1.BindPairs.Size() != a2.BindPairs.Size())
return false;
for (i = 0; i < a1.BindPairs.Size(); i++)
if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
return false;
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
return false;
if (a1.InStreams.Size() != a2.InStreams.Size())
return false;
if (a1.OutStreams.Size() != a2.OutStreams.Size())
return false;
return true;
}
CDecoder::CDecoder()
{
_bindInfoExPrevIsDefinded = false;
#ifndef EXCLUDE_COM
LoadMethodMap();
#endif
}
HRESULT CDecoder::Decode(IInStream *inStream,
UINT64 startPos,
const UINT64 *packSizes,
const CFolder &folderInfo,
ISequentialOutStream *outStream,
ICompressProgressInfo *compressProgress
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getTextPassword
#endif
)
{
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
CLockedInStream lockedInStream;
lockedInStream.Init(inStream);
for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
{
CLockedSequentialInStreamImp *lockedStreamImpSpec = new
CLockedSequentialInStreamImp;
CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
lockedStreamImpSpec->Init(&lockedInStream, startPos);
startPos += packSizes[j];
CLimitedSequentialInStream *streamSpec = new
CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream = streamSpec;
streamSpec->Init(lockedStreamImp, packSizes[j]);
inStreams.Add(inStream);
}
int numCoders = folderInfo.Coders.Size();
CBindInfoEx bindInfo;
ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
bool createNewCoders;
if (!_bindInfoExPrevIsDefinded)
createNewCoders = true;
else
createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
if (createNewCoders)
{
int i;
_decoders.Clear();
// _decoders2.Clear();
_mixerCoder.Release();
_mixerCoderSpec = new NCoderMixer2::CCoderMixer2;
_mixerCoder = _mixerCoderSpec;
_mixerCoderSpec->SetBindInfo(bindInfo);
for (i = 0; i < numCoders; i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
#ifndef EXCLUDE_COM
CMethodInfo methodInfo;
if (!GetMethodInfo(altCoderInfo.MethodID, methodInfo))
return E_NOTIMPL;
#endif
if (coderInfo.IsSimpleCoder())
{
CMyComPtr<ICompressCoder> decoder;
#ifdef COMPRESS_LZMA
if (altCoderInfo.MethodID == k_LZMA)
decoder = new NCompress::NLZMA::CDecoder;
#endif
#ifdef COMPRESS_PPMD
if (altCoderInfo.MethodID == k_PPMD)
decoder = new NCompress::NPPMD::CDecoder;
#endif
#ifdef COMPRESS_BCJ_X86
if (altCoderInfo.MethodID == k_BCJ_X86)
decoder = new CBCJ_x86_Decoder;
#endif
#ifdef COMPRESS_DEFLATE
if (altCoderInfo.MethodID == k_Deflate)
decoder = new NCompress::NDeflate::NDecoder::CCOMCoder;
#endif
#ifdef COMPRESS_BZIP2
if (altCoderInfo.MethodID == k_BZip2)
decoder = new NCompress::NBZip2::CDecoder;
#endif
#ifdef COMPRESS_COPY
if (altCoderInfo.MethodID == k_Copy)
decoder = new NCompress::CCopyCoder;
#endif
#ifdef CRYPTO_7ZAES
if (altCoderInfo.MethodID == k_7zAES)
decoder = new NCrypto::NSevenZ::CDecoder;
#endif
#ifndef EXCLUDE_COM
if (decoder == 0)
{
RINOK(_libraries.CreateCoder(methodInfo.FilePath,
methodInfo.Decoder, &decoder));
}
#endif
if (decoder == 0)
return E_NOTIMPL;
_decoders.Add((IUnknown *)decoder);
_mixerCoderSpec->AddCoder(decoder);
}
else
{
CMyComPtr<ICompressCoder2> decoder;
#ifdef COMPRESS_BCJ2
if (altCoderInfo.MethodID == k_BCJ2)
decoder = new CBCJ2_x86_Decoder;
#endif
#ifndef EXCLUDE_COM
if (decoder == 0)
{
RINOK(_libraries.CreateCoder2(methodInfo.FilePath,
methodInfo.Decoder, &decoder));
}
#endif
if (decoder == 0)
return E_NOTIMPL;
_decoders.Add((IUnknown *)decoder);
_mixerCoderSpec->AddCoder2(decoder);
}
}
_bindInfoExPrev = bindInfo;
_bindInfoExPrevIsDefinded = true;
}
int i;
_mixerCoderSpec->ReInit();
UINT32 packStreamIndex = 0, unPackStreamIndex = 0;
UINT32 coderIndex = 0;
// UINT32 coder2Index = 0;
for (i = 0; i < numCoders; i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
CMyComPtr<ICompressSetDecoderProperties> compressSetDecoderProperties;
HRESULT result = _decoders[coderIndex].QueryInterface(
IID_ICompressSetDecoderProperties, &compressSetDecoderProperties);
if (result == S_OK)
{
const CByteBuffer &properties = altCoderInfo.Properties;
UINT32 size = properties.GetCapacity();
if (size > 0)
{
CSequentialInStreamImp *inStreamSpec = new CSequentialInStreamImp;
CMyComPtr<ISequentialInStream> inStream(inStreamSpec);
inStreamSpec->Init((const BYTE *)properties, size);
RINOK(compressSetDecoderProperties->SetDecoderProperties(inStream));
}
}
else if (result != E_NOINTERFACE)
return result;
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
result = _decoders[coderIndex].QueryInterface(
IID_ICryptoSetPassword, &cryptoSetPassword);
if (result == S_OK)
{
if (getTextPassword == 0)
return E_FAIL;
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password));
UString unicodePassword(password);
RINOK(cryptoSetPassword->CryptoSetPassword(
(const BYTE *)(const wchar_t *)unicodePassword,
unicodePassword.Length() * sizeof(wchar_t)));
}
else if (result != E_NOINTERFACE)
return result;
#endif
coderIndex++;
UINT32 numInStreams = (UINT32)coderInfo.NumInStreams;
UINT32 numOutStreams = (UINT32)coderInfo.NumOutStreams;
CRecordVector<const UINT64 *> packSizesPointers;
CRecordVector<const UINT64 *> unPackSizesPointers;
packSizesPointers.Reserve(numInStreams);
unPackSizesPointers.Reserve(numOutStreams);
UINT32 j;
for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
for (j = 0; j < numInStreams; j++, packStreamIndex++)
{
int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
if (bindPairIndex >= 0)
packSizesPointers.Add(
&folderInfo.UnPackSizes[(UINT32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
else
{
int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
if (index < 0)
return E_FAIL;
packSizesPointers.Add(&packSizes[index]);
}
}
_mixerCoderSpec->SetCoderInfo(i,
&packSizesPointers.Front(),
&unPackSizesPointers.Front());
}
UINT32 mainCoder, temp;
bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
_mixerCoderSpec->SetProgressCoderIndex(mainCoder);
if (numCoders == 0)
return 0;
CRecordVector<ISequentialInStream *> inStreamPointers;
inStreamPointers.Reserve(inStreams.Size());
for (i = 0; i < inStreams.Size(); i++)
inStreamPointers.Add(inStreams[i]);
ISequentialOutStream *outStreamPointer = outStream;
return _mixerCoderSpec->Code(&inStreamPointers.Front(), NULL,
inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
}
}}

54
7zip/Archive/7z/7zDecode.h Executable file
View File

@@ -0,0 +1,54 @@
// 7zDecode.h
#pragma once
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
#include "../../IStream.h"
#include "../../IPassword.h"
#include "../Common/CoderMixer2.h"
#ifndef EXCLUDE_COM
#include "../Common/CoderLoader.h"
#endif
#include "7zItem.h"
namespace NArchive {
namespace N7z {
struct CBindInfoEx: public NCoderMixer2::CBindInfo
{
CRecordVector<CMethodID> CoderMethodIDs;
};
class CDecoder
{
#ifndef EXCLUDE_COM
CCoderLibraries _libraries;
#endif
bool _bindInfoExPrevIsDefinded;
CBindInfoEx _bindInfoExPrev;
NCoderMixer2::CCoderMixer2 *_mixerCoderSpec;
CMyComPtr<ICompressCoder2> _mixerCoder;
CObjectVector<CMyComPtr<IUnknown> > _decoders;
// CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
public:
CDecoder();
HRESULT Decode(IInStream *inStream,
UINT64 startPos,
const UINT64 *packSizes,
const CFolder &folder,
ISequentialOutStream *outStream,
ICompressProgressInfo *compressProgress
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getTextPasswordSpec
#endif
);
};
}}
#endif

570
7zip/Archive/7z/7zEncode.cpp Executable file
View File

@@ -0,0 +1,570 @@
// Encode.cpp
#include "StdAfx.h"
#include "7zEncode.h"
#include "7zSpecStream.h"
#include "7zMethods.h"
#include "../../IPassword.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/InOutTempBuffer.h"
#include "../../Common/StreamObjects.h"
#ifdef COMPRESS_COPY
static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };
#include "../../Compress/Copy/CopyCoder.h"
#endif
#ifdef COMPRESS_LZMA
#include "../../Compress/LZMA/LZMAEncoder.h"
static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
#endif
#ifdef COMPRESS_PPMD
#include "../../Compress/PPMD/PPMDEncoder.h"
static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
#endif
#ifdef COMPRESS_BCJ_X86
static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
#include "../../Compress/Branch/x86.h"
#endif
#ifdef COMPRESS_BCJ2
static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
#include "../../Compress/Branch/x86_2.h"
#endif
#ifdef COMPRESS_DEFLATE
#include "../../Compress/Deflate/DeflateEncoder.h"
static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
#endif
#ifdef COMPRESS_BZIP2
#include "../../Compress/BZip2/BZip2Encoder.h"
static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
#endif
static NArchive::N7z::CMethodID k_AES = { { 0x6, 0xF1, 0x7, 0x1}, 4 };
#ifndef EXCLUDE_COM
static const wchar_t *kCryproMethod = L"7zAES";
/*
// {23170F69-40C1-278B-06F1-070100000100}
DEFINE_GUID(CLSID_CCrypto7zAESEncoder,
0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x07, 0x01, 0x00, 0x00, 0x01, 0x00);
*/
#endif
#ifdef CRYPTO_7ZAES
#include "../../Crypto/7zAES/7zAES.h"
#endif
namespace NArchive {
namespace N7z {
static void ConvertBindInfoToFolderItemInfo(const NCoderMixer2::CBindInfo &bindInfo,
const CRecordVector<CMethodID> decompressionMethods,
CFolder &folder)
{
folder.Coders.Clear();
// bindInfo.CoderMethodIDs.Clear();
// folder.OutStreams.Clear();
folder.PackStreams.Clear();
folder.BindPairs.Clear();
int i;
for (i = 0; i < bindInfo.BindPairs.Size(); i++)
{
CBindPair bindPair;
bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
folder.BindPairs.Add(bindPair);
}
for (i = 0; i < bindInfo.Coders.Size(); i++)
{
CCoderInfo coderInfo;
const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
// coderInfo.MethodID = decompressionMethods[i];
// if (coderInfo.AltCoders.Size() == 0)
coderInfo.AltCoders.Add(CAltCoderInfo());
CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
altCoderInfo.MethodID = decompressionMethods[i];
folder.Coders.Add(coderInfo);
}
for (i = 0; i < bindInfo.InStreams.Size(); i++)
{
CPackStreamInfo packStreamInfo;
packStreamInfo.Index = bindInfo.InStreams[i];
folder.PackStreams.Add(packStreamInfo);
}
}
HRESULT CEncoder::CreateMixerCoder()
{
_mixerCoderSpec = new NCoderMixer2::CCoderMixer2;
_mixerCoder = _mixerCoderSpec;
_mixerCoderSpec->SetBindInfo(_bindInfo);
for (int i = 0; i < _options.Methods.Size(); i++)
{
const CMethodFull &methodFull = _options.Methods[i];
_codersInfo.Add(CCoderInfo());
CCoderInfo &encodingInfo = _codersInfo.Back();
CMyComPtr<ICompressCoder> encoder;
CMyComPtr<ICompressCoder2> encoder2;
if (methodFull.IsSimpleCoder())
{
#ifdef COMPRESS_LZMA
if (methodFull.MethodID == k_LZMA)
encoder = new NCompress::NLZMA::CEncoder;
#endif
#ifdef COMPRESS_PPMD
if (methodFull.MethodID == k_PPMD)
encoder = new NCompress::NPPMD::CEncoder;
#endif
#ifdef COMPRESS_BCJ_X86
if (methodFull.MethodID == k_BCJ_X86)
encoder = new CBCJ_x86_Encoder;
#endif
#ifdef COMPRESS_COPY
if (methodFull.MethodID == k_Copy)
encoder = new NCompress::CCopyCoder;
#endif
#ifdef COMPRESS_BZIP2
if (methodFull.MethodID == k_BZip2)
encoder = new NCompress::NBZip2::CEncoder;
#endif
#ifdef COMPRESS_DEFLATE
if (methodFull.MethodID == k_Deflate)
encoder = new NCompress::NDeflate::NEncoder::CCOMCoder;
#endif
#ifdef CRYPTO_7ZAES
if (methodFull.MethodID == k_AES)
encoder = new NCrypto::NSevenZ::CEncoder;
#endif
#ifndef EXCLUDE_COM
if (encoder == 0)
{
RINOK(_libraries.CreateCoder(methodFull.FilePath,
methodFull.EncoderClassID, &encoder));
}
#endif
if (encoder == 0)
return E_FAIL;
}
else
{
#ifdef COMPRESS_BCJ2
if (methodFull.MethodID == k_BCJ2)
encoder2 = new CBCJ2_x86_Encoder;
#endif
#ifndef EXCLUDE_COM
if (encoder2 == 0)
{
RINOK(_libraries.CreateCoder2(methodFull.FilePath,
methodFull.EncoderClassID, &encoder2));
}
#else
if (encoder2 == 0)
return E_FAIL;
#endif
}
if (methodFull.CoderProperties.Size() > 0)
{
std::vector<NWindows::NCOM::CPropVariant> properties;
std::vector<PROPID> propIDs;
INT32 numProperties = methodFull.CoderProperties.Size();
for (int i = 0; i < numProperties; i++)
{
const CProperty &property = methodFull.CoderProperties[i];
propIDs.push_back(property.PropID);
properties.push_back(property.Value);
}
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
if (methodFull.IsSimpleCoder())
{
RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties,
&setCoderProperties));
}
else
{
RINOK(encoder2.QueryInterface(IID_ICompressSetCoderProperties,
&setCoderProperties));
}
RINOK(setCoderProperties->SetCoderProperties(&propIDs.front(),
&properties.front(), numProperties));
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
if (methodFull.IsSimpleCoder())
{
encoder.QueryInterface(IID_ICompressWriteCoderProperties,
&writeCoderProperties);
}
else
{
encoder2.QueryInterface(IID_ICompressWriteCoderProperties,
&writeCoderProperties);
}
if (writeCoderProperties != NULL)
{
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init();
writeCoderProperties->WriteCoderProperties(outStream);
UINT32 size = outStreamSpec->GetSize();
// encodingInfo.Properties.SetCapacity(size);
if (encodingInfo.AltCoders.Size() == 0)
encodingInfo.AltCoders.Add(CAltCoderInfo());
CAltCoderInfo &altCoderInfo = encodingInfo.AltCoders.Front();
altCoderInfo.Properties.SetCapacity(size);
memmove(altCoderInfo.Properties, outStreamSpec->GetBuffer(), size);
}
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
if (methodFull.IsSimpleCoder())
{
encoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
}
else
{
encoder2.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
}
if (cryptoSetPassword)
{
RINOK(cryptoSetPassword->CryptoSetPassword(
(const BYTE *)(const wchar_t *)_options.Password,
_options.Password.Length() * sizeof(wchar_t)));
}
// public ICompressWriteCoderProperties,
if (methodFull.IsSimpleCoder())
{
_mixerCoderSpec->AddCoder(encoder);
}
else
{
_mixerCoderSpec->AddCoder2(encoder2);
}
}
return S_OK;
}
HRESULT CEncoder::Encode(ISequentialInStream *inStream,
const UINT64 *inStreamSize,
CFolder &folderItem,
ISequentialOutStream *outStream,
CRecordVector<UINT64> &packSizes,
ICompressProgressInfo *compressProgress)
{
if (_mixerCoderSpec == NULL)
{
RINOK(CreateMixerCoder());
}
_mixerCoderSpec->ReInit();
// _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
int numMethods = _bindInfo.Coders.Size();
int i;
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{
inOutTempBuffers.Add(CInOutTempBuffer());
inOutTempBuffers.Back().Create();
inOutTempBuffers.Back().InitWriting();
}
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{
CSequentialOutTempBufferImp *tempBufferSpec =
new CSequentialOutTempBufferImp;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer);
tempBufferSpecs.Add(tempBufferSpec);
}
for (i = 0; i < numMethods; i++)
_mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
if (_bindInfo.InStreams.IsEmpty())
return E_FAIL;
UINT32 mainCoderIndex, mainStreamIndex;
_bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
_mixerCoderSpec->SetProgressCoderIndex(mainCoderIndex);
if (inStreamSize != NULL)
{
CRecordVector<const UINT64 *> sizePointers;
for (int i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
if (i == mainStreamIndex)
sizePointers.Add(inStreamSize);
else
sizePointers.Add(NULL);
_mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
}
// UINT64 outStreamStartPos;
// RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec =
new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
CSequentialOutStreamSizeCount *outStreamSizeCountSpec =
new CSequentialOutStreamSizeCount;
CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
inStreamSizeCountSpec->Init(inStream);
outStreamSizeCountSpec->Init(outStream);
CRecordVector<ISequentialInStream *> inStreamPointers;
CRecordVector<ISequentialOutStream *> outStreamPointers;
inStreamPointers.Add(inStreamSizeCount);
outStreamPointers.Add(outStreamSizeCount);
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
outStreamPointers.Add(tempBuffers[i - 1]);
RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
&outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
folderItem);
packSizes.Add(outStreamSizeCountSpec->GetSize());
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
inOutTempBuffer.FlushWrite();
inOutTempBuffer.InitReading();
inOutTempBuffer.WriteToStream(outStream);
packSizes.Add(inOutTempBuffer.GetDataSize());
}
for (i = 0; i < _bindReverseConverter->NumSrcInStreams; i++)
{
int binder = _bindInfo.FindBinderForInStream(
_bindReverseConverter->DestOutToSrcInMap[i]);
UINT64 streamSize;
if (binder < 0)
streamSize = inStreamSizeCountSpec->GetSize();
else
streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
folderItem.UnPackSizes.Add(streamSize);
}
for (i = numMethods - 1; i >= 0; i--)
{
// folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties;
for (int j = 0; j < _codersInfo[i].AltCoders.Size(); j++)
folderItem.Coders[numMethods - 1 - i].AltCoders[j].Properties
= _codersInfo[i].AltCoders[j].Properties;
}
return S_OK;
}
CEncoder::CEncoder(const CCompressionMethodMode &options):
_bindReverseConverter(0)
{
if (options.IsEmpty())
throw 1;
_options = options;
_mixerCoderSpec = NULL;
if (options.Methods.IsEmpty())
{
// it has only password method;
if (!options.PasswordIsDefined)
throw 1;
if (!options.Binds.IsEmpty())
throw 1;
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method;
method.NumInStreams = 1;
method.NumOutStreams = 1;
coderStreamsInfo.NumInStreams = method.NumOutStreams;
coderStreamsInfo.NumOutStreams = method.NumInStreams;
method.MethodID = k_AES;
#ifndef EXCLUDE_COM
CMethodInfo2 methodInfo;
if (!GetMethodInfo(kCryproMethod, methodInfo))
throw 2;
method.FilePath = methodInfo.FilePath;
method.EncoderClassID = methodInfo.Encoder;
// method.EncoderClassID = CLSID_CCrypto7zAESEncoder;
#endif
_options.Methods.Add(method);
_bindInfo.Coders.Add(coderStreamsInfo);
_bindInfo.InStreams.Add(0);
_bindInfo.OutStreams.Add(0);
}
else
{
UINT32 numInStreams = 0, numOutStreams = 0;
int i;
for (i = 0; i < options.Methods.Size(); i++)
{
const CMethodFull &methodFull = options.Methods[i];
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
if (options.Binds.IsEmpty())
{
if (i < options.Methods.Size() - 1)
{
NCoderMixer2::CBindPair bindPair;
bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
bindPair.OutIndex = numOutStreams;
_bindInfo.BindPairs.Add(bindPair);
}
else
_bindInfo.OutStreams.Insert(0, numOutStreams);
for (UINT32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
_bindInfo.OutStreams.Add(numOutStreams + j);
}
numInStreams += coderStreamsInfo.NumInStreams;
numOutStreams += coderStreamsInfo.NumOutStreams;
_bindInfo.Coders.Add(coderStreamsInfo);
}
if (!options.Binds.IsEmpty())
{
for (int i = 0; i < options.Binds.Size(); i++)
{
NCoderMixer2::CBindPair bindPair;
const CBind &bind = options.Binds[i];
bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
_bindInfo.BindPairs.Add(bindPair);
}
for (i = 0; i < numOutStreams; i++)
if (_bindInfo.FindBinderForOutStream(i) == -1)
_bindInfo.OutStreams.Add(i);
}
for (i = 0; i < numInStreams; i++)
if (_bindInfo.FindBinderForInStream(i) == -1)
_bindInfo.InStreams.Add(i);
if (_bindInfo.InStreams.IsEmpty())
throw 1; // this is error
// Make main stream first in list
int inIndex = _bindInfo.InStreams[0];
while (true)
{
UINT32 coderIndex, coderStreamIndex;
_bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
UINT32 outIndex = _bindInfo.GetCoderStartOutStream(coderIndex);
int binder = _bindInfo.FindBinderForOutStream(outIndex);
if (binder >= 0)
{
inIndex = _bindInfo.BindPairs[binder].InIndex;
continue;
}
for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
if (_bindInfo.OutStreams[i] == outIndex)
{
_bindInfo.OutStreams.Delete(i);
_bindInfo.OutStreams.Insert(0, outIndex);
break;
}
break;
}
if (_options.PasswordIsDefined)
{
int numCryptoStreams = _bindInfo.OutStreams.Size();
for (i = 0; i < numCryptoStreams; i++)
{
NCoderMixer2::CBindPair bindPair;
bindPair.InIndex = numInStreams + i;
bindPair.OutIndex = _bindInfo.OutStreams[i];
_bindInfo.BindPairs.Add(bindPair);
}
_bindInfo.OutStreams.Clear();
/*
if (numCryptoStreams == 0)
numCryptoStreams = 1;
*/
for (i = 0; i < numCryptoStreams; i++)
{
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method;
method.NumInStreams = 1;
method.NumOutStreams = 1;
coderStreamsInfo.NumInStreams = method.NumOutStreams;
coderStreamsInfo.NumOutStreams = method.NumInStreams;
method.MethodID = k_AES;
#ifndef EXCLUDE_COM
CMethodInfo2 methodInfo;
if (!GetMethodInfo(kCryproMethod, methodInfo))
throw 2;
method.FilePath = methodInfo.FilePath;
method.EncoderClassID = methodInfo.Encoder;
// method.EncoderClassID = CLSID_CCrypto7zAESEncoder;
#endif
_options.Methods.Add(method);
_bindInfo.Coders.Add(coderStreamsInfo);
_bindInfo.OutStreams.Add(numOutStreams + i);
}
}
}
for (int i = _options.Methods.Size() - 1; i >= 0; i--)
{
const CMethodFull &methodFull = _options.Methods[i];
_decompressionMethods.Add(methodFull.MethodID);
}
_bindReverseConverter = new NCoderMixer2::CBindReverseConverter(_bindInfo);
_bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
}
CEncoder::~CEncoder()
{
delete _bindReverseConverter;
}
}}

56
7zip/Archive/7z/7zEncode.h Executable file
View File

@@ -0,0 +1,56 @@
// 7zEncode.h
#pragma once
#ifndef __7Z_ENCODE_H
#define __7Z_ENCODE_H
// #include "../../Common/StreamObjects.h"
#include "7zCompressionMode.h"
#include "../Common/CoderMixer2.h"
#ifndef EXCLUDE_COM
#include "../Common/CoderLoader.h"
#endif
#include "7zMethods.h"
#include "7zItem.h"
namespace NArchive {
namespace N7z {
class CEncoder
{
#ifndef EXCLUDE_COM
// CMethodMap _methodMap;
// it must be in top of objects
CCoderLibraries _libraries;
#endif
NCoderMixer2::CCoderMixer2 *_mixerCoderSpec;
CMyComPtr<ICompressCoder2> _mixerCoder;
CObjectVector<CCoderInfo> _codersInfo;
CCompressionMethodMode _options;
NCoderMixer2::CBindInfo _bindInfo;
NCoderMixer2::CBindInfo _decompressBindInfo;
NCoderMixer2::CBindReverseConverter *_bindReverseConverter;
CRecordVector<CMethodID> _decompressionMethods;
HRESULT CreateMixerCoder();
public:
CEncoder(const CCompressionMethodMode &options);
~CEncoder();
HRESULT Encode(ISequentialInStream *inStream,
const UINT64 *inStreamSize,
CFolder &folderItem,
ISequentialOutStream *outStream,
CRecordVector<UINT64> &packSizes,
ICompressProgressInfo *compressProgress);
};
}}
#endif

204
7zip/Archive/7z/7zExtract.cpp Executable file
View File

@@ -0,0 +1,204 @@
// 7zExtract.cpp
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zFolderOutStream.h"
#include "7zMethods.h"
#include "7zDecode.h"
#include "../../../Common/ComTry.h"
#include "../../Common/MultiStream.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
namespace NArchive {
namespace N7z {
struct CExtractFolderInfo
{
int FileIndex;
int FolderIndex;
CBoolVector ExtractStatuses;
UINT64 UnPackSize;
CExtractFolderInfo(int fileIndex, int folderIndex):
FileIndex(fileIndex),
FolderIndex(folderIndex),
UnPackSize(0)
{
if (fileIndex >= 0)
{
ExtractStatuses.Reserve(1);
ExtractStatuses.Add(true);
}
};
};
STDMETHODIMP CHandler::Extract(const UINT32* indices, UINT32 numItems,
INT32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
{
COM_TRY_BEGIN
bool testMode = (testModeSpec != 0);
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UINT64 importantTotalUnPacked = 0;
UINT64 censoredTotalUnPacked = 0, censoredTotalPacked = 0;
bool allFilesMode = (numItems == UINT32(-1));
if (allFilesMode)
numItems = _database.Files.Size();
if(numItems == 0)
return S_OK;
CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
for(UINT32 indexIndex = 0; indexIndex < numItems; indexIndex++)
{
int fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
int folderIndex = _database.FileIndexToFolderIndexMap[fileIndex];
if (folderIndex < 0)
{
extractFolderInfoVector.Add(CExtractFolderInfo(fileIndex, -1));
continue;
}
if (extractFolderInfoVector.IsEmpty() ||
folderIndex != extractFolderInfoVector.Back().FolderIndex)
{
extractFolderInfoVector.Add(CExtractFolderInfo(-1, folderIndex));
const CFolder &folderInfo = _database.Folders[folderIndex];
// Count full_folder_size
UINT64 unPackSize = folderInfo.GetUnPackSize();
importantTotalUnPacked += unPackSize;
extractFolderInfoVector.Back().UnPackSize = unPackSize;
}
CExtractFolderInfo &extractFolderInfo = extractFolderInfoVector.Back();
// const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
UINT32 startIndex = (UINT32)_database.FolderStartFileIndex[folderIndex];
for (UINT32 index = extractFolderInfo.ExtractStatuses.Size();
index <= fileIndex - startIndex; index++)
{
UINT64 unPackSize = _database.Files[startIndex + index].UnPackSize;
// Count partial_folder_size
// extractFolderInfo.UnPackSize += unPackSize;
// importantTotalUnPacked += unPackSize;
extractFolderInfo.ExtractStatuses.Add(index == fileIndex - startIndex);
}
}
extractCallback->SetTotal(importantTotalUnPacked);
CDecoder decoder;
UINT64 currentImportantTotalUnPacked = 0;
UINT64 totalFolderUnPacked;
for(int i = 0; i < extractFolderInfoVector.Size(); i++,
currentImportantTotalUnPacked += totalFolderUnPacked)
{
CExtractFolderInfo &extractFolderInfo = extractFolderInfoVector[i];
totalFolderUnPacked = extractFolderInfo.UnPackSize;
RINOK(extractCallback->SetCompleted(&currentImportantTotalUnPacked));
CFolderOutStream *folderOutStream = new CFolderOutStream;
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
UINT32 startIndex;
if (extractFolderInfo.FileIndex >= 0)
startIndex = extractFolderInfo.FileIndex;
else
startIndex = (UINT32)_database.FolderStartFileIndex[extractFolderInfo.FolderIndex];
RINOK(folderOutStream->Init(&_database, startIndex,
&extractFolderInfo.ExtractStatuses, extractCallback, testMode));
if (extractFolderInfo.FileIndex >= 0)
continue;
UINT32 folderIndex = extractFolderInfo.FolderIndex;
const CFolder &folderInfo = _database.Folders[folderIndex];
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
CLockedInStream lockedInStream;
lockedInStream.Init(_inStream);
UINT64 folderStartPackStreamIndex = _database.FolderStartPackStreamIndex[folderIndex];
for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
{
const CPackStreamInfo &packStreamInfo = folderInfo.PackStreams[j];
CLockedSequentialInStreamImp *lockedStreamImpSpec = new
CLockedSequentialInStreamImp;
CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
UINT64 streamStartPos = _database.GetFolderStreamPos(folderIndex, j);
lockedStreamImpSpec->Init(&lockedInStream, streamStartPos);
CLimitedSequentialInStream *streamSpec = new
CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream = streamSpec;
streamSpec->Init(lockedStreamImp,
_database.PackSizes[(UINT32)folderStartPackStreamIndex + j]);
inStreams.Add(inStream);
}
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
localProgressSpec->Init(extractCallback, false);
CLocalCompressProgressInfo *localCompressProgressSpec =
new CLocalCompressProgressInfo;
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
localCompressProgressSpec->Init(progress, NULL, &currentImportantTotalUnPacked);
UINT32 packStreamIndex = _database.FolderStartPackStreamIndex[folderIndex];
UINT64 folderStartPackPos = _database.GetFolderStreamPos(folderIndex, 0);
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (extractCallback)
extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
try
{
HRESULT result = decoder.Decode(_inStream,
folderStartPackPos,
&_database.PackSizes[packStreamIndex],
folderInfo,
outStream,
compressProgress
#ifndef _NO_CRYPTO
, getTextPassword
#endif
);
if (result == S_FALSE)
{
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
continue;
}
if (result == E_NOTIMPL)
{
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
continue;
}
if (result != S_OK)
return result;
RINOK(folderOutStream->WasWritingFinished());
}
catch(...)
{
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
continue;
}
}
return S_OK;
COM_TRY_END
}
}}

View File

@@ -0,0 +1,141 @@
// 7zFolderInStream.cpp
#include "StdAfx.h"
#include "7zFolderInStream.h"
namespace NArchive {
namespace N7z {
CFolderInStream::CFolderInStream()
{
_inStreamWithHashSpec = new CInStreamWithCRC;
_inStreamWithHash = _inStreamWithHashSpec;
}
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
const UINT32 *fileIndices, UINT32 numFiles)
{
_updateCallback = updateCallback;
_numFiles = numFiles;
_fileIndex = 0;
_fileIndices = fileIndices;
CRCs.Clear();
Sizes.Clear();
_fileIsOpen = false;
_currentSizeIsDefined = false;
}
HRESULT CFolderInStream::OpenStream()
{
_filePos = 0;
while (_fileIndex < _numFiles)
{
_currentSizeIsDefined = false;
CMyComPtr<IInStream> stream;
RINOK(_updateCallback->GetStream(_fileIndices[_fileIndex], &stream));
_fileIndex++;
_inStreamWithHashSpec->Init(stream);
if (!stream)
{
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
Sizes.Add(0);
AddDigest();
continue;
}
CMyComPtr<IStreamGetSize> streamGetSize;
if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
{
if(streamGetSize)
{
_currentSizeIsDefined = true;
RINOK(streamGetSize->GetSize(&_currentSize));
}
}
_fileIsOpen = true;
return S_OK;
}
return S_OK;
}
void CFolderInStream::AddDigest()
{
CRCs.Add(_inStreamWithHashSpec->GetCRC());
}
HRESULT CFolderInStream::CloseStream()
{
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
_inStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
Sizes.Add(_filePos);
AddDigest();
return S_OK;
}
STDMETHODIMP CFolderInStream::ReadPart(void *data, UINT32 size, UINT32 *processedSize)
{
UINT32 realProcessedSize = 0;
while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
{
if (_fileIsOpen)
{
UINT32 localProcessedSize;
RINOK(_inStreamWithHash->Read(
((BYTE *)data) + realProcessedSize, size, &localProcessedSize));
if (localProcessedSize == 0)
{
RINOK(CloseStream());
continue;
}
realProcessedSize += localProcessedSize;
_filePos += localProcessedSize;
size -= localProcessedSize;
break;
}
else
{
RINOK(OpenStream());
}
}
if (processedSize != 0)
*processedSize = realProcessedSize;
return S_OK;
}
STDMETHODIMP CFolderInStream::Read(void *data, UINT32 size, UINT32 *processedSize)
{
UINT32 realProcessedSize = 0;
while (size > 0)
{
UINT32 localProcessedSize;
RINOK(ReadPart(((BYTE *)data) + realProcessedSize, size, &localProcessedSize));
if (localProcessedSize == 0)
break;
size -= localProcessedSize;
realProcessedSize += localProcessedSize;
}
if (processedSize != 0)
*processedSize = realProcessedSize;
return S_OK;
}
STDMETHODIMP CFolderInStream::GetSubStreamSize(UINT64 subStream, UINT64 *value)
{
*value = 0;
if (subStream < Sizes.Size())
{
*value= Sizes[subStream];
return S_OK;
}
if (subStream > Sizes.Size())
return E_FAIL;
if (!_currentSizeIsDefined)
return S_FALSE;
*value = _currentSize;
return S_OK;
}
}}

View File

@@ -0,0 +1,68 @@
// 7z/FolderInStream.h
#pragma once
#ifndef __7Z_FOLDERINSTREAM_H
#define __7Z_FOLDERINSTREAM_H
#include "7zItem.h"
#include "7zHeader.h"
#include "../IArchive.h"
#include "../Common/InStreamWithCRC.h"
#include "../../IStream.h"
#include "../../ICoder.h"
namespace NArchive {
namespace N7z {
class CFolderInStream:
public ISequentialInStream,
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
CFolderInStream();
STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(GetSubStreamSize)(UINT64 subStream, UINT64 *value);
private:
CInStreamWithCRC *_inStreamWithHashSpec;
CMyComPtr<ISequentialInStream> _inStreamWithHash;
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
bool _currentSizeIsDefined;
UINT64 _currentSize;
bool _fileIsOpen;
UINT64 _filePos;
const UINT32 *_fileIndices;
UINT32 _numFiles;
UINT32 _fileIndex;
HRESULT OpenStream();
HRESULT CloseStream();
void AddDigest();
public:
void Init(IArchiveUpdateCallback *updateCallback,
const UINT32 *fileIndices, UINT32 numFiles);
CRecordVector<UINT32> CRCs;
CRecordVector<UINT64> Sizes;
UINT64 GetFullSize() const
{
UINT64 size = 0;
for (int i = 0; i < Sizes.Size(); i++)
size += Sizes[i];
return size;
}
};
}}
#endif

View File

@@ -0,0 +1,165 @@
// 7zFolderOutStream.cpp
#include "StdAfx.h"
#include "7zFolderOutStream.h"
namespace NArchive {
namespace N7z {
CFolderOutStream::CFolderOutStream()
{
_outStreamWithHashSpec = new COutStreamWithCRC;
_outStreamWithHash = _outStreamWithHashSpec;
}
HRESULT CFolderOutStream::Init(
CArchiveDatabaseEx *archiveDatabase,
UINT32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
bool testMode)
{
_archiveDatabase = archiveDatabase;
_startIndex = startIndex;
_extractStatuses = extractStatuses;
_extractCallback = extractCallback;
_testMode = testMode;
_currentIndex = 0;
_fileIsOpen = false;
return WriteEmptyFiles();
}
HRESULT CFolderOutStream::OpenFile()
{
INT32 askMode;
if((*_extractStatuses)[_currentIndex])
askMode = _testMode ?
NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract;
else
askMode = NArchive::NExtract::NAskMode::kSkip;
CMyComPtr<ISequentialOutStream> realOutStream;
UINT32 index = _startIndex + _currentIndex;
RINOK(_extractCallback->GetStream(index, &realOutStream, askMode));
_outStreamWithHashSpec->Init(realOutStream);
if (askMode == NArchive::NExtract::NAskMode::kExtract &&
(!realOutStream))
{
UINT32 index = _startIndex + _currentIndex;
const CFileItem &fileInfo = _archiveDatabase->Files[index];
if (!fileInfo.IsAnti && !fileInfo.IsDirectory)
askMode = NArchive::NExtract::NAskMode::kSkip;
}
return _extractCallback->PrepareOperation(askMode);
}
HRESULT CFolderOutStream::WriteEmptyFiles()
{
for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
{
UINT32 index = _startIndex + _currentIndex;
const CFileItem &fileInfo = _archiveDatabase->Files[index];
if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0)
return S_OK;
RINOK(OpenFile());
RINOK(_extractCallback->SetOperationResult(
NArchive::NExtract::NOperationResult::kOK));
_outStreamWithHashSpec->ReleaseStream();
}
return S_OK;
}
STDMETHODIMP CFolderOutStream::Write(const void *data,
UINT32 size, UINT32 *processedSize)
{
UINT32 realProcessedSize = 0;
while(_currentIndex < _extractStatuses->Size())
{
if (_fileIsOpen)
{
UINT32 index = _startIndex + _currentIndex;
const CFileItem &fileInfo = _archiveDatabase->Files[index];
UINT64 fileSize = fileInfo.UnPackSize;
UINT32 numBytesToWrite = (UINT32)MyMin(fileSize - _filePos,
UINT64(size - realProcessedSize));
UINT32 processedSizeLocal;
RINOK(_outStreamWithHash->Write((const BYTE *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal));
_filePos += processedSizeLocal;
realProcessedSize += processedSizeLocal;
if (_filePos == fileSize)
{
bool digestsAreEqual;
if (fileInfo.FileCRCIsDefined)
digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC();
else
digestsAreEqual = true;
RINOK(_extractCallback->SetOperationResult(
digestsAreEqual ?
NArchive::NExtract::NOperationResult::kOK :
NArchive::NExtract::NOperationResult::kCRCError));
_outStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
}
if (realProcessedSize == size)
{
if (processedSize != NULL)
*processedSize = realProcessedSize;
return WriteEmptyFiles();
}
}
else
{
RINOK(OpenFile());
_fileIsOpen = true;
_filePos = 0;
}
}
if (processedSize != NULL)
*processedSize = size;
return S_OK;
}
STDMETHODIMP CFolderOutStream::WritePart(const void *data,
UINT32 size, UINT32 *processedSize)
{
return Write(data, size, processedSize);
}
HRESULT CFolderOutStream::FlushCorrupted(INT32 resultEOperationResult)
{
while(_currentIndex < _extractStatuses->Size())
{
if (_fileIsOpen)
{
RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
_outStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
}
else
{
RINOK(OpenFile());
_fileIsOpen = true;
}
}
return S_OK;
}
HRESULT CFolderOutStream::WasWritingFinished()
{
if (_currentIndex == _extractStatuses->Size())
return S_OK;
return E_FAIL;
}
}}

View File

@@ -0,0 +1,58 @@
// 7zFolderOutStream.h
#pragma once
#ifndef __7Z_FOLDEROUTSTREAM_H
#define __7Z_FOLDEROUTSTREAM_H
#include "7zIn.h"
#include "../../IStream.h"
#include "../IArchive.h"
#include "../Common/OutStreamWithCRC.h"
namespace NArchive {
namespace N7z {
class CFolderOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
CFolderOutStream();
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
private:
COutStreamWithCRC *_outStreamWithHashSpec;
CMyComPtr<ISequentialOutStream> _outStreamWithHash;
CArchiveDatabaseEx *_archiveDatabase;
const CBoolVector *_extractStatuses;
UINT32 _startIndex;
int _currentIndex;
// UINT64 _currentDataPos;
CMyComPtr<IArchiveExtractCallback> _extractCallback;
bool _testMode;
bool _fileIsOpen;
UINT64 _filePos;
HRESULT OpenFile();
HRESULT WriteEmptyFiles();
public:
HRESULT Init(
CArchiveDatabaseEx *archiveDatabase,
UINT32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
bool testMode);
HRESULT FlushCorrupted(INT32 resultEOperationResult);
HRESULT WasWritingFinished();
};
}}
#endif

442
7zip/Archive/7z/7zHandler.cpp Executable file
View File

@@ -0,0 +1,442 @@
// 7z/Handler.cpp
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zProperties.h"
#include "../../../Common/IntToString.h"
// #include "../../../Common/StringConvert.h"
#include "../../../Common/ComTry.h"
#include "../../../Windows/Defs.h"
#include "../Common/ItemNameUtils.h"
// #include "7zMethods.h"
namespace NArchive {
namespace N7z {
CHandler::CHandler()
{
#ifndef EXTRACT_ONLY
Init();
#endif
#ifndef EXCLUDE_COM
LoadMethodMap();
#endif
}
/*
STDMETHODIMP CHandler::EnumProperties(IEnumSTATPROPSTG **enumerator)
{
#ifndef _SFX
COM_TRY_BEGIN
CComObjectNoLock<CEnumArchiveItemProperty> *enumeratorSpec =
new CComObjectNoLock<CEnumArchiveItemProperty>;
if (enumeratorSpec == NULL)
return E_OUTOFMEMORY;
CMyComPtr<IEnumSTATPROPSTG> tempEnumerator(enumeratorSpec);
enumeratorSpec->Init(_database.ArchiveInfo.FileInfoPopIDs);
*enumerator = tempEnumerator.Detach();
return S_OK;
// return tempEnumerator->QueryInterface(IID_IEnumSTATPROPSTG, (LPVOID*)enumerator);
COM_TRY_END
#else
return E_NOTIMPL;
#endif
}
*/
STDMETHODIMP CHandler::GetNumberOfItems(UINT32 *numItems)
{
COM_TRY_BEGIN
*numItems = _database.Files.Size();
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
value->vt = VT_EMPTY;
return S_OK;
}
#ifdef _SFX
STDMETHODIMP CHandler::GetNumberOfProperties(UINT32 *numProperties)
{
return E_NOTIMPL;
}
STDMETHODIMP CHandler::GetPropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
return E_NOTIMPL;
}
#endif
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UINT32 *numProperties)
{
*numProperties = 0;
return S_OK;
}
STDMETHODIMP CHandler::GetArchivePropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
return E_NOTIMPL;
}
static void MySetFileTime(bool timeDefined, FILETIME unixTime,
NWindows::NCOM::CPropVariant &propVariant)
{
// FILETIME fileTime;
if (timeDefined)
propVariant = unixTime;
// NTime::UnixTimeToFileTime((time_t)unixTime, fileTime);
else
{
return;
// fileTime.dwHighDateTime = fileTime.dwLowDateTime = 0;
}
// propVariant = fileTime;
}
/*
inline static wchar_t GetHex(BYTE value)
{
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
}
static UString ConvertBytesToHexString(const BYTE *data, UINT32 size)
{
UString result;
for (UINT32 i = 0; i < size; i++)
{
BYTE b = data[i];
result += GetHex(b >> 4);
result += GetHex(b & 0xF);
}
return result;
}
*/
#ifndef _SFX
static UString ConvertUINT32ToString(UINT32 value)
{
wchar_t buffer[32];
ConvertUINT64ToString(value, buffer);
return buffer;
}
static UString GetStringForSizeValue(UINT32 value)
{
for (int i = 31; i >= 0; i--)
if ((UINT32(1) << i) == value)
return ConvertUINT32ToString(i);
UString result;
if (value % (1 << 20) == 0)
{
result += ConvertUINT32ToString(value >> 20);
result += L"m";
}
else if (value % (1 << 10) == 0)
{
result += ConvertUINT32ToString(value >> 10);
result += L"k";
}
else
{
result += ConvertUINT32ToString(value);
result += L"b";
}
return result;
}
static CMethodID k_Copy = { { 0x0 }, 1 };
static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
static CMethodID k_BCJ = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
static CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
static inline char GetHex(BYTE value)
{
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
}
static inline UString GetHex2(BYTE value)
{
UString result;
result += GetHex(value >> 4);
result += GetHex(value & 0xF);
return result;
}
#endif
STDMETHODIMP CHandler::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant propVariant;
const CFileItem &item = _database.Files[index];
switch(propID)
{
case kpidPath:
{
propVariant = NArchive::NItemName::GetOSName(item.Name);
break;
}
case kpidIsFolder:
propVariant = item.IsDirectory;
break;
case kpidSize:
propVariant = item.UnPackSize;
break;
case kpidPackedSize:
{
{
int folderIndex = _database.FileIndexToFolderIndexMap[index];
if (folderIndex >= 0)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
if (_database.FolderStartFileIndex[folderIndex] == index)
propVariant = _database.GetFolderFullPackSize(folderIndex);
else
propVariant = UINT64(0);
}
else
propVariant = UINT64(0);
}
break;
}
case kpidLastAccessTime:
MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, propVariant);
break;
case kpidCreationTime:
MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, propVariant);
break;
case kpidLastWriteTime:
MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, propVariant);
break;
case kpidAttributes:
if (item.AreAttributesDefined)
propVariant = item.Attributes;
break;
case kpidCRC:
if (item.FileCRCIsDefined)
propVariant = item.FileCRC;
break;
#ifndef _SFX
case kpidMethod:
{
int folderIndex = _database.FileIndexToFolderIndexMap[index];
if (folderIndex >= 0)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
UString methodsString;
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
if (!methodsString.IsEmpty())
methodsString += L' ';
CMethodInfo methodInfo;
bool methodIsKnown;
for (int j = 0; j < coderInfo.AltCoders.Size(); j++)
{
if (j > 0)
methodsString += L"|";
const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders[j];
UString methodName;
#ifdef NO_REGISTRY
methodIsKnown = true;
if (altCoderInfo.MethodID == k_Copy)
methodName = L"Copy";
else if (altCoderInfo.MethodID == k_LZMA)
methodName = L"LZMA";
else if (altCoderInfo.MethodID == k_BCJ)
methodName = L"BCJ";
else if (altCoderInfo.MethodID == k_BCJ2)
methodName = L"BCJ2";
else if (altCoderInfo.MethodID == k_PPMD)
methodName = L"PPMD";
else if (altCoderInfo.MethodID == k_Deflate)
methodName = L"Deflate";
else if (altCoderInfo.MethodID == k_BZip2)
methodName = L"BZip2";
else
methodIsKnown = false;
#else
methodIsKnown = GetMethodInfo(
altCoderInfo.MethodID, methodInfo);
methodName = methodInfo.Name;
#endif
if (methodIsKnown)
{
methodsString += methodName;
if (altCoderInfo.MethodID == k_LZMA)
{
if (altCoderInfo.Properties.GetCapacity() == 5)
{
methodsString += L":";
UINT32 dicSize = *(const UINT32 *)
((const BYTE *)altCoderInfo.Properties + 1);
methodsString += GetStringForSizeValue(dicSize);
}
}
else if (altCoderInfo.MethodID == k_PPMD)
{
if (altCoderInfo.Properties.GetCapacity() == 5)
{
BYTE order = *(const BYTE *)altCoderInfo.Properties;
methodsString += L":o";
methodsString += ConvertUINT32ToString(order);
methodsString += L":mem";
UINT32 dicSize = *(const UINT32 *)
((const BYTE *)altCoderInfo.Properties + 1);
methodsString += GetStringForSizeValue(dicSize);
}
}
else
{
if (altCoderInfo.Properties.GetCapacity() > 0)
{
methodsString += L":[";
for (int bi = 0; bi < altCoderInfo.Properties.GetCapacity(); bi++)
{
if (bi > 2 && bi + 1 < altCoderInfo.Properties.GetCapacity())
{
methodsString += L"..";
break;
}
else
methodsString += GetHex2(altCoderInfo.Properties[bi]);
}
methodsString += L"]";
}
}
}
else
{
methodsString += altCoderInfo.MethodID.ConvertToString();
}
}
}
propVariant = methodsString;
}
}
break;
case kpidBlock:
{
int folderIndex = _database.FileIndexToFolderIndexMap[index];
if (folderIndex >= 0)
propVariant = (UINT32)folderIndex;
}
break;
case kpidPackedSize0:
case kpidPackedSize1:
case kpidPackedSize2:
case kpidPackedSize3:
case kpidPackedSize4:
{
int folderIndex = _database.FileIndexToFolderIndexMap[index];
if (folderIndex >= 0)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
if (_database.FolderStartFileIndex[folderIndex] == index &&
folderInfo.PackStreams.Size() > propID - kpidPackedSize0)
{
propVariant = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
}
else
propVariant = UINT64(0);
}
else
propVariant = UINT64(0);
}
break;
#endif
case kpidIsAnti:
propVariant = item.IsAnti;
break;
}
propVariant.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Open(IInStream *stream,
const UINT64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
_inStream.Release();
_database.Clear();
#ifndef _SFX
_fileInfoPopIDs.Clear();
#endif
try
{
CInArchive archive;
RINOK(archive.Open(stream, maxCheckStartPosition));
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (openArchiveCallback)
{
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
openArchiveCallbackTemp.QueryInterface(
IID_ICryptoGetTextPassword, &getTextPassword);
}
#endif
HRESULT result = archive.ReadDatabase(_database
#ifndef _NO_CRYPTO
, getTextPassword
#endif
);
RINOK(result);
result = archive.CheckIntegrity();
if (result != S_OK)
return E_FAIL;
_database.FillFolderStartPackStream();
_database.FillStartPos();
_database.FillFolderStartFileIndex();
}
catch(...)
{
return S_FALSE;
}
_inStream = stream;
#ifndef _SFX
FillPopIDs();
#endif
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
COM_TRY_BEGIN
_inStream.Release();
return S_OK;
COM_TRY_END
}
}}

208
7zip/Archive/7z/7zHandler.h Executable file
View File

@@ -0,0 +1,208 @@
// 7z/Handler.h
#pragma once
#ifndef __7Z_HANDLER_H
#define __7Z_HANDLER_H
#include "../IArchive.h"
// #include "../../../Compress/Interface/CompressInterface.h"
#include "7zIn.h"
#include "7zCompressionMode.h"
#ifndef _SFX
#include "7zMethods.h"
#endif
namespace NArchive {
namespace N7z {
#ifndef EXTRACT_ONLY
struct COneMethodInfo
{
CObjectVector<CProperty> CoderProperties;
UString MethodName;
};
#endif
// {23170F69-40C1-278A-1000-000110050000}
DEFINE_GUID(CLSID_CFormat7z,
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00);
class CHandler:
public IInArchive,
#ifndef EXTRACT_ONLY
public IOutArchive,
public ISetProperties,
#endif
public CMyUnknownImp
{
public:
#ifdef EXTRACT_ONLY
MY_UNKNOWN_IMP
#else
MY_UNKNOWN_IMP3(
IInArchive,
IOutArchive,
ISetProperties
)
#endif
STDMETHOD(Open)(IInStream *stream,
const UINT64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback);
STDMETHOD(Close)();
STDMETHOD(GetNumberOfItems)(UINT32 *numItems);
STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(Extract)(const UINT32* indices, UINT32 numItems,
INT32 testMode, IArchiveExtractCallback *extractCallback);
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value);
STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
STDMETHOD(GetPropertyInfo)(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType);
STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties);
STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType);
#ifndef EXTRACT_ONLY
// IOutArchiveHandler
STDMETHOD(UpdateItems)(IOutStream *outStream, UINT32 numItems,
IArchiveUpdateCallback *updateCallback);
STDMETHOD(GetFileTimeType)(UINT32 *type);
// ISetProperties
STDMETHOD(SetProperties)(const BSTR *names, const PROPVARIANT *values, INT32 numProperties);
HRESULT SetSolidSettings(const UString &s);
HRESULT SetSolidSettings(const PROPVARIANT &value);
#endif
CHandler();
private:
CMyComPtr<IInStream> _inStream;
NArchive::N7z::CArchiveDatabaseEx _database;
#ifndef EXTRACT_ONLY
CObjectVector<COneMethodInfo> _methods;
CRecordVector<CBind> _binds;
bool _removeSfxBlock;
UINT64 _numSolidFiles;
UINT64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
bool _compressHeaders;
bool _compressHeadersFull;
bool _encryptHeaders;
bool _copyMode;
UINT32 _defaultDicSize;
UINT32 _defaultAlgorithm;
UINT32 _defaultFastBytes;
UString _defaultMatchFinder;
bool _autoFilter;
bool _multiThread;
UINT32 _level;
HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);
HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);
HRESULT SetPassword(CCompressionMethodMode &methodMode,
IArchiveUpdateCallback *updateCallback);
HRESULT SetCompressionMethod(CCompressionMethodMode &method,
CObjectVector<COneMethodInfo> &methodsInfo,
bool multiThread);
HRESULT SetCompressionMethod(
CCompressionMethodMode &method,
CCompressionMethodMode &headerMethod);
#endif
#ifndef _SFX
CRecordVector<UINT64> _fileInfoPopIDs;
void FillPopIDs();
#endif
#ifndef EXTRACT_ONLY
UINT64 GetUINT64MAX() const
{
return
#if (__GNUC__)
0xFFFFFFFFFFFFFFFFLL
#else
0xFFFFFFFFFFFFFFFF
#endif
;
}
void InitSolidFiles() { _numSolidFiles = GetUINT64MAX(); }
void InitSolidSize() { _numSolidBytes = GetUINT64MAX(); }
void InitSolid()
{
InitSolidFiles();
InitSolidSize();
_solidExtension = false;
_numSolidBytesDefined = false;
}
/*
void InitSolidPart()
{
if (_numSolidFiles <= 1)
InitSolidFiles();
}
*/
void SetSolidBytesLimit()
{
_numSolidBytes = ((UINT64)_defaultDicSize) << 7;
const UINT64 kMinSize = (1<<24);
if (_numSolidBytes < kMinSize)
_numSolidBytes = kMinSize;
}
void CheckAndSetSolidBytesLimit()
{
if (!_numSolidBytesDefined)
{
if (_copyMode)
_numSolidBytes = 0;
else
SetSolidBytesLimit();
}
}
void Init()
{
_removeSfxBlock = false;
_compressHeaders = true;
_compressHeadersFull = true;
_encryptHeaders = false;
_multiThread = false;
_copyMode = false;
_defaultDicSize = (1 << 21);
_defaultAlgorithm = 1;
_defaultFastBytes = 32;
_defaultMatchFinder = L"BT4";
_level = 5;
_autoFilter = true;
InitSolid();
SetSolidBytesLimit();
}
#endif
};
}}
#endif

1160
7zip/Archive/7z/7zHandlerOut.cpp Executable file
View File

File diff suppressed because it is too large Load Diff

18
7zip/Archive/7z/7zHeader.cpp Executable file
View File

@@ -0,0 +1,18 @@
// 7z/Header.cpp
#include "StdAfx.h"
#include "7zHeader.h"
namespace NArchive {
namespace N7z {
BYTE kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
class SignatureInitializer
{
public:
SignatureInitializer() { kSignature[0]--; };
} g_SignatureInitializer;
}}

85
7zip/Archive/7z/7zHeader.h Executable file
View File

@@ -0,0 +1,85 @@
// 7z/Header.h
#pragma once
#ifndef __7Z_HEADER_H
#define __7Z_HEADER_H
// #include "Common/Types.h"
// #include "../../../Common/CRC.h"
#include "7zMethodID.h"
namespace NArchive {
namespace N7z {
#pragma pack( push, Pragma7zHeaders)
#pragma pack( push, 1)
const int kSignatureSize = 6;
extern BYTE kSignature[kSignatureSize];
struct CArchiveVersion
{
BYTE Major;
BYTE Minor;
};
struct CStartHeader
{
UINT64 NextHeaderOffset;
UINT64 NextHeaderSize;
UINT32 NextHeaderCRC;
};
namespace NID
{
enum EEnum
{
kEnd,
kHeader,
kArchiveProperties,
kAdditionalStreamsInfo,
kMainStreamsInfo,
kFilesInfo,
kPackInfo,
kUnPackInfo,
kSubStreamsInfo,
kSize,
kCRC,
kFolder,
kCodersUnPackSize,
kNumUnPackStream,
kEmptyStream,
kEmptyFile,
kAnti,
kName,
kCreationTime,
kLastAccessTime,
kLastWriteTime,
kWinAttributes,
kComment,
kEncodedHeader,
};
}
#pragma pack(pop)
#pragma pack(pop, Pragma7zHeaders)
const BYTE kMajorVersion = 0;
}}
#endif

1158
7zip/Archive/7z/7zIn.cpp Executable file
View File

File diff suppressed because it is too large Load Diff

266
7zip/Archive/7z/7zIn.h Executable file
View File

@@ -0,0 +1,266 @@
// 7zIn.h
#pragma once
#ifndef __7Z_IN_H
#define __7Z_IN_H
#include "../../IStream.h"
#include "../../IPassword.h"
#include "../../../Common/MyCom.h"
#include "../../Common/InBuffer.h"
#include "7zHeader.h"
#include "7zItem.h"
namespace NArchive {
namespace N7z {
class CInArchiveException
{
public:
enum CCauseType
{
kUnsupportedVersion = 0,
kUnexpectedEndOfArchive = 0,
kIncorrectHeader,
} Cause;
CInArchiveException(CCauseType cause);
};
struct CInArchiveInfo
{
CArchiveVersion Version;
UINT64 StartPosition;
UINT64 StartPositionAfterHeader;
UINT64 DataStartPosition;
UINT64 DataStartPosition2;
CRecordVector<UINT64> FileInfoPopIDs;
void Clear()
{
FileInfoPopIDs.Clear();
}
};
struct CArchiveDatabaseEx: public CArchiveDatabase
{
CInArchiveInfo ArchiveInfo;
CRecordVector<UINT64> PackStreamStartPositions;
CRecordVector<UINT32> FolderStartPackStreamIndex;
CRecordVector<UINT64> FolderStartFileIndex;
CRecordVector<int> FileIndexToFolderIndexMap;
void Clear()
{
CArchiveDatabase::Clear();
ArchiveInfo.Clear();
PackStreamStartPositions.Clear();
FolderStartPackStreamIndex.Clear();
FolderStartFileIndex.Clear();
FolderStartFileIndex.Clear();
}
void FillFolderStartPackStream();
void FillStartPos();
void FillFolderStartFileIndex();
UINT64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
{
return ArchiveInfo.DataStartPosition +
PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] +
indexInFolder];
}
UINT64 GetFolderFullPackSize(int folderIndex) const
{
UINT32 packStreamIndex = FolderStartPackStreamIndex[folderIndex];
const CFolder &folder = Folders[folderIndex];
UINT64 size = 0;
for (int i = 0; i < folder.PackStreams.Size(); i++)
size += PackSizes[packStreamIndex + i];
return size;
}
UINT64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
{
return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
}
};
class CInByte2
{
const BYTE *_buffer;
UINT32 _size;
UINT32 _pos;
public:
void Init(const BYTE *buffer, UINT32 size)
{
_buffer = buffer;
_size = size;
_pos = 0;
}
bool ReadByte(BYTE &b)
{
if(_pos >= _size)
return false;
b = _buffer[_pos++];
return true;
}
void ReadBytes(void *data, UINT32 size, UINT32 &processedSize)
{
for(processedSize = 0; processedSize < size && _pos < _size; processedSize++)
((BYTE *)data)[processedSize] = _buffer[_pos++];
}
bool ReadBytes(void *data, UINT32 size)
{
UINT32 processedSize;
ReadBytes(data, size, processedSize);
return (processedSize == size);
}
UINT32 GetProcessedSize() const { return _pos; }
};
class CStreamSwitch;
class CInArchive
{
friend class CStreamSwitch;
CMyComPtr<IInStream> _stream;
CObjectVector<CInByte2> _inByteVector;
CInByte2 *_inByteBack;
UINT64 _arhiveBeginStreamPosition;
UINT64 _position;
void AddByteStream(const BYTE *buffer, UINT32 size)
{
_inByteVector.Add(CInByte2());
_inByteBack = &_inByteVector.Back();
_inByteBack->Init(buffer, size);
}
void DeleteByteStream()
{
_inByteVector.DeleteBack();
if (!_inByteVector.IsEmpty())
_inByteBack = &_inByteVector.Back();
}
private:
HRESULT FindAndReadSignature(IInStream *stream, const UINT64 *searchHeaderSizeLimit); // S_FALSE means is not archive
HRESULT ReadFileNames(CObjectVector<CFileItem> &files);
HRESULT ReadBytes(IInStream *stream, void *data, UINT32 size,
UINT32 *processedSize);
HRESULT ReadBytes(void *data, UINT32 size, UINT32 *processedSize);
HRESULT SafeReadBytes(void *data, UINT32 size);
HRESULT SafeReadBytes2(void *data, UINT32 size)
{
if (!_inByteBack->ReadBytes(data, size))
return E_FAIL;
return S_OK;
}
HRESULT SafeReadByte2(BYTE &b)
{
if (!_inByteBack->ReadByte(b))
return E_FAIL;
return S_OK;
}
HRESULT SafeReadWideCharLE(wchar_t &c)
{
BYTE b1;
if (!_inByteBack->ReadByte(b1))
return E_FAIL;
BYTE b2;
if (!_inByteBack->ReadByte(b2))
return E_FAIL;
c = (int(b2) << 8) + b1;
return S_OK;
}
HRESULT ReadNumber(UINT64 &value);
HRESULT ReadID(UINT64 &value)
{
return ReadNumber(value);
}
HRESULT SkeepData(UINT64 size);
HRESULT SkeepData();
HRESULT WaitAttribute(UINT64 attribute);
HRESULT ReadArchiveProperties(CInArchiveInfo &archiveInfo);
HRESULT GetNextFolderItem(CFolder &itemInfo);
HRESULT ReadHashDigests(int numItems,
CRecordVector<bool> &digestsDefined, CRecordVector<UINT32> &digests);
HRESULT ReadPackInfo(
UINT64 &dataOffset,
CRecordVector<UINT64> &packSizes,
CRecordVector<bool> &packCRCsDefined,
CRecordVector<UINT32> &packCRCs);
HRESULT ReadUnPackInfo(
const CObjectVector<CByteBuffer> *dataVector,
CObjectVector<CFolder> &folders);
HRESULT ReadSubStreamsInfo(
const CObjectVector<CFolder> &folders,
CRecordVector<UINT64> &numUnPackStreamsInFolders,
CRecordVector<UINT64> &unPackSizes,
CRecordVector<bool> &digestsDefined,
CRecordVector<UINT32> &digests);
HRESULT CInArchive::ReadStreamsInfo(
const CObjectVector<CByteBuffer> *dataVector,
UINT64 &dataOffset,
CRecordVector<UINT64> &packSizes,
CRecordVector<bool> &packCRCsDefined,
CRecordVector<UINT32> &packCRCs,
CObjectVector<CFolder> &folders,
CRecordVector<UINT64> &numUnPackStreamsInFolders,
CRecordVector<UINT64> &unPackSizes,
CRecordVector<bool> &digestsDefined,
CRecordVector<UINT32> &digests);
HRESULT GetNextFileItem(CFileItem &itemInfo);
HRESULT ReadBoolVector(UINT32 numItems, CBoolVector &vector);
HRESULT ReadBoolVector2(UINT32 numItems, CBoolVector &vector);
HRESULT ReadTime(const CObjectVector<CByteBuffer> &dataVector,
CObjectVector<CFileItem> &files, UINT64 type);
HRESULT ReadAndDecodePackedStreams(UINT64 baseOffset, UINT64 &dataOffset,
CObjectVector<CByteBuffer> &dataVector
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getTextPassword
#endif
);
HRESULT ReadHeader(CArchiveDatabaseEx &database
#ifndef _NO_CRYPTO
,ICryptoGetTextPassword *getTextPassword
#endif
);
public:
HRESULT Open(IInStream *stream, const UINT64 *searchHeaderSizeLimit); // S_FALSE means is not archive
void Close();
HRESULT ReadDatabase(CArchiveDatabaseEx &database
#ifndef _NO_CRYPTO
,ICryptoGetTextPassword *getTextPassword
#endif
);
HRESULT CheckIntegrity();
};
}}
#endif

195
7zip/Archive/7z/7zItem.h Executable file
View File

@@ -0,0 +1,195 @@
// 7zItem.h
#pragma once
#ifndef __7Z_ITEM_H
#define __7Z_ITEM_H
#include "../../../Common/Buffer.h"
#include "7zMethodID.h"
#include "7zHeader.h"
namespace NArchive {
namespace N7z {
struct CAltCoderInfo
{
CMethodID MethodID;
CByteBuffer Properties;
};
struct CCoderInfo
{
UINT64 NumInStreams;
UINT64 NumOutStreams;
CObjectVector<CAltCoderInfo> AltCoders;
bool IsSimpleCoder() const
{ return (NumInStreams == 1) && (NumOutStreams == 1); }
};
struct CPackStreamInfo
{
UINT64 Index;
};
struct CBindPair
{
UINT64 InIndex;
UINT64 OutIndex;
};
struct CFolder
{
CObjectVector<CCoderInfo> Coders;
CRecordVector<CBindPair> BindPairs;
CRecordVector<CPackStreamInfo> PackStreams;
CRecordVector<UINT64> UnPackSizes;
bool UnPackCRCDefined;
UINT32 UnPackCRC;
CFolder(): UnPackCRCDefined(false) {}
UINT64 GetUnPackSize() const // test it
{
if (UnPackSizes.IsEmpty())
return 0;
for (int i = UnPackSizes.Size() - 1; i >= 0; i--)
if (FindBindPairForOutStream(i) < 0)
return UnPackSizes[i];
throw 1;
}
UINT64 GetNumOutStreams() const
{
UINT64 result = 0;
for (int i = 0; i < Coders.Size(); i++)
result += Coders[i].NumOutStreams;
return result;
}
int FindBindPairForInStream(int inStreamIndex) const
{
for(int i = 0; i < BindPairs.Size(); i++)
if (BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int FindBindPairForOutStream(int outStreamIndex) const
{
for(int i = 0; i < BindPairs.Size(); i++)
if (BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
int FindPackStreamArrayIndex(int inStreamIndex) const
{
for(int i = 0; i < PackStreams.Size(); i++)
if (PackStreams[i].Index == inStreamIndex)
return i;
return -1;
}
};
typedef FILETIME CArchiveFileTime;
class CFileItem
{
public:
CArchiveFileTime CreationTime;
CArchiveFileTime LastWriteTime;
CArchiveFileTime LastAccessTime;
UINT64 UnPackSize;
UINT32 Attributes;
UINT32 FileCRC;
UString Name;
bool HasStream; // Test it !!! it means that there is
// stream in some folder. It can be empty stream
bool IsDirectory;
bool IsAnti;
bool FileCRCIsDefined;
bool AreAttributesDefined;
bool IsCreationTimeDefined;
bool IsLastWriteTimeDefined;
bool IsLastAccessTimeDefined;
/*
const bool HasStream() const {
return !IsDirectory && !IsAnti && UnPackSize != 0; }
*/
CFileItem():
AreAttributesDefined(false),
IsCreationTimeDefined(false),
IsLastWriteTimeDefined(false),
IsLastAccessTimeDefined(false),
IsDirectory(false),
FileCRCIsDefined(false),
IsAnti(false),
HasStream(true)
{}
void SetAttributes(UINT32 attributes)
{
AreAttributesDefined = true;
Attributes = attributes;
}
void SetCreationTime(CArchiveFileTime creationTime)
{
IsCreationTimeDefined = true;
CreationTime = creationTime;
}
void SetLastWriteTime(CArchiveFileTime lastWriteTime)
{
IsLastWriteTimeDefined = true;
LastWriteTime = lastWriteTime;
}
void SetLastAccessTime(CArchiveFileTime lastAccessTime)
{
IsLastAccessTimeDefined = true;
LastAccessTime = lastAccessTime;
}
};
struct CArchiveDatabase
{
CRecordVector<UINT64> PackSizes;
CRecordVector<bool> PackCRCsDefined;
CRecordVector<UINT32> PackCRCs;
CObjectVector<CFolder> Folders;
CRecordVector<UINT64> NumUnPackStreamsVector;
CObjectVector<CFileItem> Files;
void Clear()
{
PackSizes.Clear();
PackCRCsDefined.Clear();
PackCRCs.Clear();
Folders.Clear();
NumUnPackStreamsVector.Clear();
Files.Clear();
}
bool IsEmpty() const
{
return (PackSizes.IsEmpty() &&
PackCRCsDefined.IsEmpty() &&
PackCRCs.IsEmpty() &&
Folders.IsEmpty() &&
NumUnPackStreamsVector.IsEmpty() &&
Files.IsEmpty());
}
};
struct CArchiveHeaderDatabase
{
CRecordVector<UINT64> PackSizes;
CObjectVector<CFolder> Folders;
CRecordVector<UINT32> CRCs;
void Clear()
{
PackSizes.Clear();
Folders.Clear();
CRCs.Clear();
}
};
}}
#endif

68
7zip/Archive/7z/7zMethodID.cpp Executable file
View File

@@ -0,0 +1,68 @@
// 7zMethodID.cpp
#include "StdAfx.h"
#include "7zMethodID.h"
namespace NArchive {
namespace N7z {
static inline wchar_t GetHex(BYTE value)
{
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
}
static bool HexCharToInt(wchar_t value, BYTE &result)
{
if (value >= '0' && value <= '9')
result = value - '0';
else if (value >= 'a' && value <= 'f')
result = 10 + value - 'a';
else if (value >= 'A' && value <= 'F')
result = 10 + value - 'A';
else
return false;
return true;
}
static bool TwoHexCharsToInt(wchar_t valueHigh, wchar_t valueLow, BYTE &result)
{
BYTE resultHigh, resultLow;
if (!HexCharToInt(valueHigh, resultHigh))
return false;
if (!HexCharToInt(valueLow, resultLow))
return false;
result = (resultHigh << 4) + resultLow;
return true;
}
UString CMethodID::ConvertToString() const
{
UString result;
for (int i = 0; i < IDSize; i++)
{
BYTE b = ID[i];
result += GetHex(b >> 4);
result += GetHex(b & 0xF);
}
return result;
}
bool CMethodID::ConvertFromString(const UString &srcString)
{
int length = srcString.Length();
if ((length & 1) != 0)
return false;
IDSize = length / 2;
if (IDSize > kMethodIDSize)
return false;
UINT32 i;
for(i = 0; i < IDSize; i++)
if (!TwoHexCharsToInt(srcString[i * 2], srcString[i * 2 + 1], ID[i]))
return false;
for(i = IDSize; i < kMethodIDSize; i++)
ID[i] = 0;
return true;
}
}}

38
7zip/Archive/7z/7zMethodID.h Executable file
View File

@@ -0,0 +1,38 @@
// 7zMethodID.h
#pragma once
#ifndef __7Z_METHOD_ID_H
#define __7Z_METHOD_ID_H
#include "../../../Common/String.h"
namespace NArchive {
namespace N7z {
const int kMethodIDSize = 16;
struct CMethodID
{
BYTE ID[kMethodIDSize];
UINT32 IDSize;
UString ConvertToString() const;
bool ConvertFromString(const UString &srcString);
};
inline bool operator==(const CMethodID &a1, const CMethodID &a2)
{
if (a1.IDSize != a2.IDSize)
return false;
for (UINT32 i = 0; i < a1.IDSize; i++)
if (a1.ID[i] != a2.ID[i])
return false;
return true;
}
inline bool operator!=(const CMethodID &a1, const CMethodID &a2)
{ return !(a1 == a2); }
}}
#endif

174
7zip/Archive/7z/7zMethods.cpp Executable file
View File

@@ -0,0 +1,174 @@
// 7zMethods.cpp
#include "StdAfx.h"
#include "7zMethods.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/Synchronization.h"
#include "../../ICoder.h"
#include "../Common/CodecsPath.h"
using namespace NWindows;
namespace NArchive {
namespace N7z {
static CObjectVector<CMethodInfo2> g_Methods;
static bool g_Loaded = false;
typedef UINT32 (WINAPI *GetNumberOfMethodsFunc)(UINT32 *numMethods);
typedef UINT32 (WINAPI *GetMethodPropertyFunc)(
UINT32 index, PROPID propID, PROPVARIANT *value);
static void Load(const CSysString &folderPrefix)
{
NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));
NFile::NFind::CFileInfo fileInfo;
while (enumerator.Next(fileInfo))
{
if (fileInfo.IsDirectory())
continue;
CSysString filePath = folderPrefix + fileInfo.Name;
{
NDLL::CLibrary library;
if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE))
continue;
}
NDLL::CLibrary library;
if (!library.Load(filePath))
continue;
GetMethodPropertyFunc getMethodProperty = (GetMethodPropertyFunc)
library.GetProcAddress("GetMethodProperty");
if (getMethodProperty == NULL)
continue;
UINT32 numMethods = 1;
GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)
library.GetProcAddress("GetNumberOfMethods");
if (getNumberOfMethodsFunc != NULL)
if (getNumberOfMethodsFunc(&numMethods) != S_OK)
continue;
for(UINT32 i = 0; i < numMethods; i++)
{
CMethodInfo2 info;
info.FilePath = filePath;
NWindows::NCOM::CPropVariant propVariant;
if (getMethodProperty(i, NMethodPropID::kID, &propVariant) != S_OK)
continue;
if (propVariant.vt != VT_BSTR)
continue;
info.MethodID.IDSize = SysStringByteLen(propVariant.bstrVal);
memmove(info.MethodID.ID, propVariant.bstrVal, info.MethodID.IDSize);
propVariant.Clear();
if (getMethodProperty(i, NMethodPropID::kName, &propVariant) != S_OK)
continue;
if (propVariant.vt == VT_EMPTY)
{
}
else if (propVariant.vt == VT_BSTR)
info.Name = propVariant.bstrVal;
else
continue;
propVariant.Clear();
if (getMethodProperty (i, NMethodPropID::kEncoder, &propVariant) != S_OK)
continue;
if (propVariant.vt == VT_EMPTY)
info.EncoderIsAssigned = false;
else if (propVariant.vt == VT_BSTR)
{
info.EncoderIsAssigned = true;
info.Encoder = *(const GUID *)propVariant.bstrVal;
}
else
continue;
propVariant.Clear();
if (getMethodProperty (i, NMethodPropID::kDecoder, &propVariant) != S_OK)
continue;
if (propVariant.vt == VT_EMPTY)
info.DecoderIsAssigned = false;
else if (propVariant.vt == VT_BSTR)
{
info.DecoderIsAssigned = true;
info.Decoder = *(const GUID *)propVariant.bstrVal;
}
else
continue;
propVariant.Clear();
if (getMethodProperty (i, NMethodPropID::kInStreams, &propVariant) != S_OK)
continue;
if (propVariant.vt == VT_EMPTY)
info.NumInStreams = 1;
else if (propVariant.vt == VT_UI4)
info.NumInStreams = propVariant.ulVal;
else
continue;
propVariant.Clear();
if (getMethodProperty (i, NMethodPropID::kOutStreams, &propVariant) != S_OK)
continue;
if (propVariant.vt == VT_EMPTY)
info.NumOutStreams = 1;
else if (propVariant.vt == VT_UI4)
info.NumOutStreams = propVariant.ulVal;
else
continue;
propVariant.Clear();
g_Methods.Add(info);
}
}
}
static NSynchronization::CCriticalSection g_CriticalSection;
void LoadMethodMap()
{
NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
if (g_Loaded)
return;
g_Loaded = true;
Load(GetCodecsFolderPrefix());
}
bool GetMethodInfo(const CMethodID &methodID, CMethodInfo &methodInfo)
{
for(int i = 0; i < g_Methods.Size(); i++)
{
const CMethodInfo2 &method = g_Methods[i];
if (method.MethodID == methodID)
{
methodInfo = (CMethodInfo)method;
return true;
}
}
return false;
}
bool GetMethodInfo(const UString &name, CMethodInfo2 &methodInfo)
{
for(int i = 0; i < g_Methods.Size(); i++)
{
const CMethodInfo2 &method = g_Methods[i];
if (method.Name.CollateNoCase(name) == 0)
{
methodInfo = method;
return true;
}
}
return false;
}
}}

36
7zip/Archive/7z/7zMethods.h Executable file
View File

@@ -0,0 +1,36 @@
// 7zMethods.h
#ifndef __7Z_METHODS_H
#define __7Z_METHODS_H
#include "7zMethodID.h"
namespace NArchive {
namespace N7z {
struct CMethodInfo
{
UString Name;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
UINT32 NumInStreams;
UINT32 NumOutStreams;
CLSID Encoder;
CLSID Decoder;
// UString Description;
CSysString FilePath;
};
struct CMethodInfo2: public CMethodInfo
{
CMethodID MethodID;
};
void LoadMethodMap();
bool GetMethodInfo(const CMethodID &methodID, CMethodInfo &methodInfo);
bool GetMethodInfo(const UString &name, CMethodInfo2 &methodInfo);
}}
#endif

853
7zip/Archive/7z/7zOut.cpp Executable file
View File

@@ -0,0 +1,853 @@
// 7zOut.cpp
#include "StdAfx.h"
#include "7zOut.h"
#include "../../Common/StreamObjects.h"
static HRESULT WriteBytes(IOutStream *stream, const void *data, UINT32 size)
{
UINT32 processedSize;
RINOK(stream->Write(data, size, &processedSize));
if(processedSize != size)
return E_FAIL;
return S_OK;
}
namespace NArchive {
namespace N7z {
HRESULT COutArchive::Create(IOutStream *stream)
{
Close();
RINOK(::WriteBytes(stream, kSignature, kSignatureSize));
CArchiveVersion archiveVersion;
archiveVersion.Major = kMajorVersion;
archiveVersion.Minor = 2;
RINOK(::WriteBytes(stream, &archiveVersion, sizeof(archiveVersion)));
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
Stream = stream;
return S_OK;
}
void COutArchive::Close()
{
Stream.Release();
}
HRESULT COutArchive::SkeepPrefixArchiveHeader()
{
return Stream->Seek(sizeof(CStartHeader) + sizeof(UINT32), STREAM_SEEK_CUR, NULL);
}
HRESULT COutArchive::WriteBytes(const void *data, UINT32 size)
{
return ::WriteBytes(Stream, data, size);
}
HRESULT COutArchive::WriteBytes2(const void *data, UINT32 size)
{
if (_mainMode)
{
if (_dynamicMode)
_dynamicBuffer.Write(data, size);
else
_outByte.WriteBytes(data, size);
_crc.Update(data, size);
}
else
{
if (_countMode)
_countSize += size;
else
RINOK(_outByte2.Write(data, size));
}
return S_OK;
}
HRESULT COutArchive::WriteBytes2(const CByteBuffer &data)
{
return WriteBytes2(data, data.GetCapacity());
}
HRESULT COutArchive::WriteByte2(BYTE b)
{
return WriteBytes2(&b, 1);
}
HRESULT COutArchive::WriteNumber(UINT64 value)
{
BYTE firstByte = 0;
BYTE mask = 0x80;
int i;
for (i = 0; i < 8; i++)
{
if (value < ((UINT64(1) << ( 7 * (i + 1)))))
{
firstByte |= BYTE(value >> (8 * i));
break;
}
firstByte |= mask;
mask >>= 1;
}
RINOK(WriteByte2(firstByte));
return WriteBytes2(&value, i);
}
static UINT32 GetBigNumberSize(UINT64 value)
{
int i;
for (i = 0; i < 8; i++)
if (value < ((UINT64(1) << ( 7 * (i + 1)))))
break;
return 1 + i;
}
HRESULT COutArchive::WriteFolderHeader(const CFolder &itemInfo)
{
RINOK(WriteNumber(itemInfo.Coders.Size()));
int i;
for (i = 0; i < itemInfo.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = itemInfo.Coders[i];
for (int j = 0; j < coderInfo.AltCoders.Size(); j++)
{
const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders[j];
UINT64 propertiesSize = altCoderInfo.Properties.GetCapacity();
BYTE b;
b = altCoderInfo.MethodID.IDSize & 0xF;
bool isComplex = (coderInfo.NumInStreams != 1) ||
(coderInfo.NumOutStreams != 1);
b |= (isComplex ? 0x10 : 0);
b |= ((propertiesSize != 0) ? 0x20 : 0 );
b |= ((j == coderInfo.AltCoders.Size() - 1) ? 0 : 0x80 );
RINOK(WriteByte2(b));
RINOK(WriteBytes2(&altCoderInfo.MethodID.ID[0],
altCoderInfo.MethodID.IDSize));
if (isComplex)
{
RINOK(WriteNumber(coderInfo.NumInStreams));
RINOK(WriteNumber(coderInfo.NumOutStreams));
}
if (propertiesSize == 0)
continue;
RINOK(WriteNumber(propertiesSize));
RINOK(WriteBytes2(altCoderInfo.Properties, (UINT32)propertiesSize));
}
}
// RINOK(WriteNumber(itemInfo.BindPairs.Size()));
for (i = 0; i < itemInfo.BindPairs.Size(); i++)
{
const CBindPair &bindPair = itemInfo.BindPairs[i];
RINOK(WriteNumber(bindPair.InIndex));
RINOK(WriteNumber(bindPair.OutIndex));
}
if (itemInfo.PackStreams.Size() > 1)
for (i = 0; i < itemInfo.PackStreams.Size(); i++)
{
const CPackStreamInfo &packStreamInfo = itemInfo.PackStreams[i];
RINOK(WriteNumber(packStreamInfo.Index));
}
return S_OK;
}
HRESULT COutArchive::WriteBoolVector(const CBoolVector &boolVector)
{
BYTE b = 0;
BYTE mask = 0x80;
for(int i = 0; i < boolVector.Size(); i++)
{
if (boolVector[i])
b |= mask;
mask >>= 1;
if (mask == 0)
{
RINOK(WriteBytes2(&b, 1));
mask = 0x80;
b = 0;
}
}
if (mask != 0x80)
{
RINOK(WriteBytes2(&b, 1));
}
return S_OK;
}
HRESULT COutArchive::WriteHashDigests(
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UINT32> &digests)
{
int numDefined = 0;
int i;
for(i = 0; i < digestsDefined.Size(); i++)
if (digestsDefined[i])
numDefined++;
if (numDefined == 0)
return S_OK;
RINOK(WriteByte2(NID::kCRC));
if (numDefined == digestsDefined.Size())
{
RINOK(WriteByte2(1));
}
else
{
RINOK(WriteByte2(0));
RINOK(WriteBoolVector(digestsDefined));
}
for(i = 0; i < digests.Size(); i++)
{
if(digestsDefined[i])
RINOK(WriteBytes2(&digests[i], sizeof(digests[i])));
}
return S_OK;
}
HRESULT COutArchive::WritePackInfo(
UINT64 dataOffset,
const CRecordVector<UINT64> &packSizes,
const CRecordVector<bool> &packCRCsDefined,
const CRecordVector<UINT32> &packCRCs)
{
if (packSizes.IsEmpty())
return S_OK;
RINOK(WriteByte2(NID::kPackInfo));
RINOK(WriteNumber(dataOffset));
RINOK(WriteNumber(packSizes.Size()));
RINOK(WriteByte2(NID::kSize));
for(int i = 0; i < packSizes.Size(); i++)
RINOK(WriteNumber(packSizes[i]));
RINOK(WriteHashDigests(packCRCsDefined, packCRCs));
return WriteByte2(NID::kEnd);
}
HRESULT COutArchive::WriteUnPackInfo(
bool externalFolders,
UINT64 externalFoldersStreamIndex,
const CObjectVector<CFolder> &folders)
{
if (folders.IsEmpty())
return S_OK;
RINOK(WriteByte2(NID::kUnPackInfo));
RINOK(WriteByte2(NID::kFolder));
RINOK(WriteNumber(folders.Size()));
if (externalFolders)
{
RINOK(WriteByte2(1));
RINOK(WriteNumber(externalFoldersStreamIndex));
}
else
{
RINOK(WriteByte2(0));
for(int i = 0; i < folders.Size(); i++)
RINOK(WriteFolderHeader(folders[i]));
}
RINOK(WriteByte2(NID::kCodersUnPackSize));
int i;
for(i = 0; i < folders.Size(); i++)
{
const CFolder &folder = folders[i];
for (int j = 0; j < folder.UnPackSizes.Size(); j++)
RINOK(WriteNumber(folder.UnPackSizes[j]));
}
CRecordVector<bool> unPackCRCsDefined;
CRecordVector<UINT32> unPackCRCs;
for(i = 0; i < folders.Size(); i++)
{
const CFolder &folder = folders[i];
unPackCRCsDefined.Add(folder.UnPackCRCDefined);
unPackCRCs.Add(folder.UnPackCRC);
}
RINOK(WriteHashDigests(unPackCRCsDefined, unPackCRCs));
return WriteByte2(NID::kEnd);
}
HRESULT COutArchive::WriteSubStreamsInfo(
const CObjectVector<CFolder> &folders,
const CRecordVector<UINT64> &numUnPackStreamsInFolders,
const CRecordVector<UINT64> &unPackSizes,
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UINT32> &digests)
{
RINOK(WriteByte2(NID::kSubStreamsInfo));
int i;
for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
{
if (numUnPackStreamsInFolders[i] != 1)
{
RINOK(WriteByte2(NID::kNumUnPackStream));
for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
RINOK(WriteNumber(numUnPackStreamsInFolders[i]));
break;
}
}
UINT32 needFlag = true;
UINT32 index = 0;
for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
for (UINT32 j = 0; j < numUnPackStreamsInFolders[i]; j++)
{
if (j + 1 != numUnPackStreamsInFolders[i])
{
if (needFlag)
RINOK(WriteByte2(NID::kSize));
needFlag = false;
RINOK(WriteNumber(unPackSizes[index]));
}
index++;
}
CRecordVector<bool> digestsDefined2;
CRecordVector<UINT32> digests2;
int digestIndex = 0;
for (i = 0; i < folders.Size(); i++)
{
int numSubStreams = (int)numUnPackStreamsInFolders[i];
if (numSubStreams == 1 && folders[i].UnPackCRCDefined)
digestIndex++;
else
for (int j = 0; j < numSubStreams; j++, digestIndex++)
{
digestsDefined2.Add(digestsDefined[digestIndex]);
digests2.Add(digests[digestIndex]);
}
}
RINOK(WriteHashDigests(digestsDefined2, digests2));
return WriteByte2(NID::kEnd);
}
HRESULT COutArchive::WriteTime(
const CObjectVector<CFileItem> &files, BYTE type,
bool isExternal, int externalDataIndex)
{
/////////////////////////////////////////////////
// CreationTime
CBoolVector boolVector;
boolVector.Reserve(files.Size());
bool thereAreDefined = false;
bool allDefined = true;
int i;
for(i = 0; i < files.Size(); i++)
{
const CFileItem &item = files[i];
bool defined;
switch(type)
{
case NID::kCreationTime:
defined = item.IsCreationTimeDefined;
break;
case NID::kLastWriteTime:
defined = item.IsLastWriteTimeDefined;
break;
case NID::kLastAccessTime:
defined = item.IsLastAccessTimeDefined;
break;
default:
throw 1;
}
boolVector.Add(defined);
thereAreDefined = (thereAreDefined || defined);
allDefined = (allDefined && defined);
}
if (!thereAreDefined)
return S_OK;
RINOK(WriteByte2(type));
UINT32 dataSize = 1 + 1;
if (isExternal)
dataSize += GetBigNumberSize(externalDataIndex);
else
dataSize += files.Size() * sizeof(CArchiveFileTime);
if (allDefined)
{
RINOK(WriteNumber(dataSize));
WriteByte2(1);
}
else
{
RINOK(WriteNumber(1 + (boolVector.Size() + 7) / 8 + dataSize));
WriteByte2(0);
RINOK(WriteBoolVector(boolVector));
}
if (isExternal)
{
RINOK(WriteByte2(1));
RINOK(WriteNumber(externalDataIndex));
return S_OK;
}
RINOK(WriteByte2(0));
for(i = 0; i < files.Size(); i++)
{
if (boolVector[i])
{
const CFileItem &item = files[i];
CArchiveFileTime timeValue;
switch(type)
{
case NID::kCreationTime:
timeValue = item.CreationTime;
break;
case NID::kLastWriteTime:
timeValue = item.LastWriteTime;
break;
case NID::kLastAccessTime:
timeValue = item.LastAccessTime;
break;
}
RINOK(WriteBytes2(&timeValue, sizeof(timeValue)));
}
}
return S_OK;
}
HRESULT COutArchive::EncodeStream(CEncoder &encoder, const BYTE *data, UINT32 dataSize,
CRecordVector<UINT64> &packSizes, CObjectVector<CFolder> &folders)
{
CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp;
CMyComPtr<ISequentialInStream> stream = streamSpec;
streamSpec->Init(data, dataSize);
CFolder folderItem;
folderItem.UnPackCRCDefined = true;
folderItem.UnPackCRC = CCRC::CalculateDigest(data, dataSize);
RINOK(encoder.Encode(stream, NULL,
folderItem, Stream,
packSizes, NULL));
folders.Add(folderItem);
return S_OK;
}
HRESULT COutArchive::EncodeStream(CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UINT64> &packSizes, CObjectVector<CFolder> &folders)
{
return EncodeStream(encoder, data, data.GetCapacity(), packSizes, folders);
}
HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
const CCompressionMethodMode *options, UINT64 &headerOffset)
{
CObjectVector<CFolder> folders;
bool compressHeaders = (options != NULL);
std::auto_ptr<CEncoder> encoder;
if (compressHeaders)
encoder = std::auto_ptr<CEncoder>(new CEncoder(*options));
CRecordVector<UINT64> packSizes;
UINT64 dataIndex = 0;
//////////////////////////
// Folders
UINT64 externalFoldersStreamIndex;
bool externalFolders = (compressHeaders && database.Folders.Size() > 8);
if (externalFolders)
{
_mainMode = false;
_countMode = true;
_countSize = 0;
int i;
for(i = 0; i < database.Folders.Size(); i++)
{
RINOK(WriteFolderHeader(database.Folders[i]));
}
_countMode = false;
CByteBuffer foldersData;
foldersData.SetCapacity(_countSize);
_outByte2.Init(foldersData, foldersData.GetCapacity());
for(i = 0; i < database.Folders.Size(); i++)
{
RINOK(WriteFolderHeader(database.Folders[i]));
}
{
externalFoldersStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, foldersData, packSizes, folders));
}
}
/////////////////////////////////
// Names
CByteBuffer namesData;
UINT64 externalNamesStreamIndex;
bool externalNames = (compressHeaders && database.Files.Size() > 8);
{
UINT64 namesDataSize = 0;
int i;
for(i = 0; i < database.Files.Size(); i++)
namesDataSize += (database.Files[i].Name.Length() + 1) * sizeof(wchar_t);
namesData.SetCapacity(namesDataSize);
UINT32 pos = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const UString &name = database.Files[i].Name;
int length = name.Length() * sizeof(wchar_t);
memmove(namesData + pos, name, length);
pos += length;
namesData[pos++] = 0;
namesData[pos++] = 0;
}
if (externalNames)
{
externalNamesStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, namesData, packSizes, folders));
}
}
/////////////////////////////////
// Write Attributes
CBoolVector attributesBoolVector;
attributesBoolVector.Reserve(database.Files.Size());
UINT32 numDefinedAttributes = 0;
int i;
for(i = 0; i < database.Files.Size(); i++)
{
bool defined = database.Files[i].AreAttributesDefined;
attributesBoolVector.Add(defined);
if (defined)
numDefinedAttributes++;
}
CByteBuffer attributesData;
UINT64 externalAttributesStreamIndex;
bool externalAttributes = (compressHeaders && numDefinedAttributes > 8);
if (numDefinedAttributes > 0)
{
attributesData.SetCapacity(numDefinedAttributes * sizeof(UINT32));
UINT32 pos = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (file.AreAttributesDefined)
{
memmove(attributesData + pos, &database.Files[i].Attributes, sizeof(UINT32));
pos += sizeof(UINT32);
}
}
if (externalAttributes)
{
externalAttributesStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, attributesData, packSizes, folders));
}
}
/////////////////////////////////
// Write Last Write Time
UINT64 externalLastWriteTimeStreamIndex;
bool externalLastWriteTime = false;
// /*
UINT32 numDefinedLastWriteTimes = 0;
for(i = 0; i < database.Files.Size(); i++)
if (database.Files[i].IsLastWriteTimeDefined)
numDefinedLastWriteTimes++;
externalLastWriteTime = (compressHeaders && numDefinedLastWriteTimes > 64);
if (numDefinedLastWriteTimes > 0)
{
CByteBuffer lastWriteTimeData;
lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * sizeof(CArchiveFileTime));
UINT32 pos = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (file.IsLastWriteTimeDefined)
{
memmove(lastWriteTimeData + pos, &database.Files[i].LastWriteTime, sizeof(CArchiveFileTime));
pos += sizeof(CArchiveFileTime);
}
}
if (externalLastWriteTime)
{
externalLastWriteTimeStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, lastWriteTimeData, packSizes, folders));
}
}
// */
UINT64 packedSize = 0;
for(i = 0; i < database.PackSizes.Size(); i++)
packedSize += database.PackSizes[i];
UINT64 headerPackSize = 0;
for (i = 0; i < packSizes.Size(); i++)
headerPackSize += packSizes[i];
headerOffset = packedSize + headerPackSize;
_mainMode = true;
_outByte.Init(Stream);
_crc.Init();
RINOK(WriteByte2(NID::kHeader));
// Archive Properties
if (folders.Size() > 0)
{
RINOK(WriteByte2(NID::kAdditionalStreamsInfo));
RINOK(WritePackInfo(packedSize, packSizes,
CRecordVector<bool>(), CRecordVector<UINT32>()));
RINOK(WriteUnPackInfo(false, 0, folders));
RINOK(WriteByte2(NID::kEnd));
}
////////////////////////////////////////////////////
if (database.Folders.Size() > 0)
{
RINOK(WriteByte2(NID::kMainStreamsInfo));
RINOK(WritePackInfo(0, database.PackSizes,
database.PackCRCsDefined,
database.PackCRCs));
RINOK(WriteUnPackInfo(
externalFolders, externalFoldersStreamIndex, database.Folders));
CRecordVector<UINT64> unPackSizes;
CRecordVector<bool> digestsDefined;
CRecordVector<UINT32> digests;
for (i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (!file.HasStream)
continue;
unPackSizes.Add(file.UnPackSize);
digestsDefined.Add(file.FileCRCIsDefined);
digests.Add(file.FileCRC);
}
RINOK(WriteSubStreamsInfo(
database.Folders,
database.NumUnPackStreamsVector,
unPackSizes,
digestsDefined,
digests));
RINOK(WriteByte2(NID::kEnd));
}
if (database.Files.IsEmpty())
{
RINOK(WriteByte2(NID::kEnd));
return _outByte.Flush();
}
RINOK(WriteByte2(NID::kFilesInfo));
RINOK(WriteNumber(database.Files.Size()));
CBoolVector emptyStreamVector;
emptyStreamVector.Reserve(database.Files.Size());
UINT64 numEmptyStreams = 0;
for(i = 0; i < database.Files.Size(); i++)
if (database.Files[i].HasStream)
emptyStreamVector.Add(false);
else
{
emptyStreamVector.Add(true);
numEmptyStreams++;
}
if (numEmptyStreams > 0)
{
RINOK(WriteByte2(NID::kEmptyStream));
RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8));
RINOK(WriteBoolVector(emptyStreamVector));
CBoolVector emptyFileVector, antiVector;
emptyFileVector.Reserve(numEmptyStreams);
antiVector.Reserve(numEmptyStreams);
UINT64 numEmptyFiles = 0, numAntiItems = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (!file.HasStream)
{
emptyFileVector.Add(!file.IsDirectory);
if (!file.IsDirectory)
numEmptyFiles++;
antiVector.Add(file.IsAnti);
if (file.IsAnti)
numAntiItems++;
}
}
if (numEmptyFiles > 0)
{
RINOK(WriteByte2(NID::kEmptyFile));
RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8));
RINOK(WriteBoolVector(emptyFileVector));
}
if (numAntiItems > 0)
{
RINOK(WriteByte2(NID::kAnti));
RINOK(WriteNumber((antiVector.Size() + 7) / 8));
RINOK(WriteBoolVector(antiVector));
}
}
{
/////////////////////////////////////////////////
RINOK(WriteByte2(NID::kName));
if (externalNames)
{
RINOK(WriteNumber(1 +
GetBigNumberSize(externalNamesStreamIndex)));
RINOK(WriteByte2(1));
RINOK(WriteNumber(externalNamesStreamIndex));
}
else
{
RINOK(WriteNumber(1 + namesData.GetCapacity()));
RINOK(WriteByte2(0));
RINOK(WriteBytes2(namesData));
}
}
RINOK(WriteTime(database.Files, NID::kCreationTime, false, 0));
RINOK(WriteTime(database.Files, NID::kLastAccessTime, false, 0));
RINOK(WriteTime(database.Files, NID::kLastWriteTime,
// false, 0));
externalLastWriteTime, externalLastWriteTimeStreamIndex));
if (numDefinedAttributes > 0)
{
/////////////////////////////////////////////////
RINOK(WriteByte2(NID::kWinAttributes));
UINT32 size = 2;
if (numDefinedAttributes != database.Files.Size())
size += (attributesBoolVector.Size() + 7) / 8 + 1;
if (externalAttributes)
size += GetBigNumberSize(externalAttributesStreamIndex);
else
size += attributesData.GetCapacity();
RINOK(WriteNumber(size));
if (numDefinedAttributes == database.Files.Size())
{
RINOK(WriteByte2(1));
}
else
{
RINOK(WriteByte2(0));
RINOK(WriteBoolVector(attributesBoolVector));
}
if (externalAttributes)
{
RINOK(WriteByte2(1));
RINOK(WriteNumber(externalAttributesStreamIndex));
}
else
{
RINOK(WriteByte2(0));
RINOK(WriteBytes2(attributesData));
}
}
RINOK(WriteByte2(NID::kEnd)); // for files
RINOK(WriteByte2(NID::kEnd)); // for headers
return _outByte.Flush();
}
HRESULT COutArchive::WriteDatabase(const CArchiveDatabase &database,
const CCompressionMethodMode *options,
bool useAdditionalStreams, bool compressMainHeader)
{
UINT64 headerOffset;
UINT32 headerCRC;
UINT64 headerSize;
if (database.IsEmpty())
{
headerSize = 0;
headerOffset = 0;
headerCRC = CCRC::CalculateDigest(0, 0);
}
else
{
_dynamicBuffer.Init();
_dynamicMode = false;
if (options != 0)
if (options->IsEmpty())
options = 0;
const CCompressionMethodMode *additionalStreamsOptions = options;
if (!useAdditionalStreams)
additionalStreamsOptions = 0;
/*
if (database.Files.Size() < 2)
compressMainHeader = false;
*/
if (options != 0)
if (options->PasswordIsDefined || compressMainHeader)
_dynamicMode = true;
RINOK(WriteHeader(database, additionalStreamsOptions, headerOffset));
if (_dynamicMode)
{
CCompressionMethodMode encryptOptions;
encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
encryptOptions.Password = options->Password;
CEncoder encoder(compressMainHeader ?
*options : encryptOptions);
CRecordVector<UINT64> packSizes;
CObjectVector<CFolder> folders;
RINOK(EncodeStream(encoder, _dynamicBuffer,
_dynamicBuffer.GetSize(), packSizes, folders));
_dynamicMode = false;
_mainMode = true;
_outByte.Init(Stream);
_crc.Init();
if (folders.Size() == 0)
throw 1;
RINOK(WriteID(NID::kEncodedHeader));
RINOK(WritePackInfo(headerOffset, packSizes,
CRecordVector<bool>(), CRecordVector<UINT32>()));
RINOK(WriteUnPackInfo(false, 0, folders));
RINOK(WriteByte2(NID::kEnd));
for (int i = 0; i < packSizes.Size(); i++)
headerOffset += packSizes[i];
RINOK(_outByte.Flush());
}
headerCRC = _crc.GetDigest();
headerSize = _outByte.GetProcessedSize();
}
RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
CStartHeader startHeader;
startHeader.NextHeaderOffset = headerOffset;
startHeader.NextHeaderSize = headerSize;
startHeader.NextHeaderCRC = headerCRC;
UINT32 crc = CCRC::CalculateDigest(&startHeader, sizeof(startHeader));
RINOK(WriteBytes(&crc, sizeof(crc)));
return WriteBytes(&startHeader, sizeof(startHeader));
}
}}

154
7zip/Archive/7z/7zOut.h Executable file
View File

@@ -0,0 +1,154 @@
// 7z/Out.h
#pragma once
#ifndef __7Z_OUT_H
#define __7Z_OUT_H
#include "7zHeader.h"
#include "7zItem.h"
#include "7zCompressionMode.h"
#include "7zEncode.h"
#include "../../Common/OutBuffer.h"
#include "../../../Common/DynamicBuffer.h"
#include "../../../Common/CRC.h"
namespace NArchive {
namespace N7z {
class CWriteBufferLoc
{
BYTE *_data;
UINT32 _size;
UINT32 _pos;
public:
CWriteBufferLoc(): _size(0), _pos(0) {}
void Init(BYTE *data, UINT32 size)
{
_pos = 0;
_data = data;
_size = size;
}
HRESULT Write(const void *data, UINT32 size)
{
if (_pos + size > _size)
return E_FAIL;
memmove(_data + _pos, data, size);
_pos += size;
return S_OK;
}
};
class CWriteDynamicBuffer
{
CByteDynamicBuffer _buffer;
UINT32 _pos;
public:
CWriteDynamicBuffer(): _pos(0) {}
void Init()
{
_pos = 0;
}
void Write(const void *data, UINT32 size)
{
if (_pos + size > _buffer.GetCapacity())
_buffer.EnsureCapacity(_pos + size);
memmove(((BYTE *)_buffer) +_pos, data, size);
_pos += size;
}
operator BYTE *() { return (BYTE *)_buffer; };
operator const BYTE *() const { return (const BYTE *)_buffer; };
UINT32 GetSize() const { return _pos; }
};
class COutArchive
{
UINT64 _prefixHeaderPos;
HRESULT WriteBytes(const void *data, UINT32 size);
HRESULT WriteBytes2(const void *data, UINT32 size);
HRESULT WriteBytes2(const CByteBuffer &data);
HRESULT WriteByte2(BYTE b);
HRESULT WriteNumber(UINT64 value);
HRESULT WriteID(UINT64 value)
{
return WriteNumber(value);
}
HRESULT WriteFolderHeader(const CFolder &itemInfo);
HRESULT WriteFileHeader(const CFileItem &itemInfo);
HRESULT WriteBoolVector(const CBoolVector &boolVector);
HRESULT WriteHashDigests(
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UINT32> &hashDigests);
HRESULT WritePackInfo(
UINT64 dataOffset,
const CRecordVector<UINT64> &packSizes,
const CRecordVector<bool> &packCRCsDefined,
const CRecordVector<UINT32> &packCRCs);
HRESULT WriteUnPackInfo(
bool externalFolders,
UINT64 externalFoldersStreamIndex,
const CObjectVector<CFolder> &folders);
HRESULT WriteSubStreamsInfo(
const CObjectVector<CFolder> &folders,
const CRecordVector<UINT64> &numUnPackStreamsInFolders,
const CRecordVector<UINT64> &unPackSizes,
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UINT32> &hashDigests);
HRESULT WriteStreamsInfo(
UINT64 dataOffset,
const CRecordVector<UINT64> &packSizes,
const CRecordVector<bool> &packCRCsDefined,
const CRecordVector<UINT32> &packCRCs,
bool externalFolders,
UINT64 externalFoldersStreamIndex,
const CObjectVector<CFolder> &folders,
const CRecordVector<UINT64> &numUnPackStreamsInFolders,
const CRecordVector<UINT64> &unPackSizes,
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UINT32> &hashDigests);
HRESULT WriteTime(const CObjectVector<CFileItem> &files, BYTE type,
bool isExternal, int externalDataIndex);
HRESULT EncodeStream(CEncoder &encoder, const BYTE *data, UINT32 dataSize,
CRecordVector<UINT64> &packSizes, CObjectVector<CFolder> &folders);
HRESULT EncodeStream(CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UINT64> &packSizes, CObjectVector<CFolder> &folders);
HRESULT WriteHeader(const CArchiveDatabase &database,
const CCompressionMethodMode *options,
UINT64 &headerOffset);
bool _mainMode;
bool _dynamicMode;
bool _countMode;
UINT32 _countSize;
COutBuffer _outByte;
CWriteBufferLoc _outByte2;
CWriteDynamicBuffer _dynamicBuffer;
CCRC _crc;
public:
CMyComPtr<IOutStream> Stream;
HRESULT Create(IOutStream *stream);
void Close();
HRESULT SkeepPrefixArchiveHeader();
HRESULT WriteDatabase(const CArchiveDatabase &database,
const CCompressionMethodMode *options,
bool useAdditionalHeaderStreams,
bool compressMainHeader);
};
}}
#endif

157
7zip/Archive/7z/7zProperties.cpp Executable file
View File

@@ -0,0 +1,157 @@
// 7zProperties.cpp
#include "StdAfx.h"
#include "7zProperties.h"
#include "7zHeader.h"
#include "7zHandler.h"
// #define _MULTI_PACK
namespace NArchive {
namespace N7z {
struct CPropMap
{
UINT64 FilePropID;
STATPROPSTG StatPROPSTG;
};
CPropMap kPropMap[] =
{
{ NID::kName, NULL, kpidPath, VT_BSTR},
{ NID::kSize, NULL, kpidSize, VT_UI8},
{ NID::kPackInfo, NULL, kpidPackedSize, VT_UI8},
#ifdef _MULTI_PACK
{ 100, L"Pack0", kpidPackedSize0, VT_UI8},
{ 101, L"Pack1", kpidPackedSize1, VT_UI8},
{ 102, L"Pack2", kpidPackedSize2, VT_UI8},
{ 103, L"Pack3", kpidPackedSize3, VT_UI8},
{ 104, L"Pack4", kpidPackedSize4, VT_UI8},
#endif
{ NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME},
{ NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME},
{ NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME},
{ NID::kWinAttributes, NULL, kpidAttributes, VT_UI4},
{ NID::kCRC, NULL, kpidCRC, VT_UI4},
{ NID::kAnti, L"Anti", kpidIsAnti, VT_BOOL},
// { 97, NULL, kpidSolid, VT_BOOL},
#ifndef _SFX
{ 98, NULL, kpidMethod, VT_BSTR},
{ 99, L"Block", kpidBlock, VT_UI4}
#endif
// { L"ID", kpidID, VT_BSTR},
// { L"UnPack Version", kpidUnPackVersion, VT_UI1},
// { L"Host OS", kpidHostOS, VT_BSTR}
};
static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);
static int FindPropInMap(UINT64 filePropID)
{
for (int i = 0; i < kPropMapSize; i++)
if (kPropMap[i].FilePropID == filePropID)
return i;
return -1;
}
static void CopyOneItem(CRecordVector<UINT64> &src,
CRecordVector<UINT64> &dest, UINT32 item)
{
for (int i = 0; i < src.Size(); i++)
if (src[i] == item)
{
dest.Add(item);
src.Delete(i);
return;
}
}
static void RemoveOneItem(CRecordVector<UINT64> &src, UINT32 item)
{
for (int i = 0; i < src.Size(); i++)
if (src[i] == item)
{
src.Delete(i);
return;
}
}
static void InsertToHead(CRecordVector<UINT64> &dest, UINT32 item)
{
for (int i = 0; i < dest.Size(); i++)
if (dest[i] == item)
{
dest.Delete(i);
break;
}
dest.Insert(0, item);
}
void CHandler::FillPopIDs()
{
_fileInfoPopIDs.Clear();
CRecordVector<UINT64> fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs;
RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);
_fileInfoPopIDs += fileInfoPopIDs;
#ifndef _SFX
_fileInfoPopIDs.Add(98);
_fileInfoPopIDs.Add(99);
#endif
#ifdef _MULTI_PACK
_fileInfoPopIDs.Add(100);
_fileInfoPopIDs.Add(101);
_fileInfoPopIDs.Add(102);
_fileInfoPopIDs.Add(103);
_fileInfoPopIDs.Add(104);
#endif
#ifndef _SFX
InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime);
InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
InsertToHead(_fileInfoPopIDs, NID::kSize);
InsertToHead(_fileInfoPopIDs, NID::kName);
#endif
}
STDMETHODIMP CHandler::GetNumberOfProperties(UINT32 *numProperties)
{
*numProperties = _fileInfoPopIDs.Size();
return S_OK;
}
STDMETHODIMP CHandler::GetPropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
if(index >= _fileInfoPopIDs.Size())
return E_INVALIDARG;
int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
if (indexInMap == -1)
return E_INVALIDARG;
const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
*propID = srcItem.propid;
*varType = srcItem.vt;
*name = 0;
return S_OK;
}
}}

51
7zip/Archive/7z/7zProperties.h Executable file
View File

@@ -0,0 +1,51 @@
// 7zProperties.h
#pragma once
#ifndef __7Z_PROPERTIES_H
#define __7Z_PROPERTIES_H
#include "../../PropID.h"
namespace NArchive {
namespace N7z {
enum // PropID
{
kpidPackedSize0 = kpidUserDefined,
kpidPackedSize1,
kpidPackedSize2,
kpidPackedSize3,
kpidPackedSize4,
};
/*
class CEnumArchiveItemProperty:
public IEnumSTATPROPSTG,
public CComObjectRoot
{
CRecordVector<UINT32> _fileInfoPopIDs;
int _index;
public:
BEGIN_COM_MAP(CEnumArchiveItemProperty)
COM_INTERFACE_ENTRY(IEnumSTATPROPSTG)
END_COM_MAP()
DECLARE_NOT_AGGREGATABLE(CEnumArchiveItemProperty)
DECLARE_NO_REGISTRY()
public:
CEnumArchiveItemProperty(): _index(0) {};
void Init(const CRecordVector<UINT32> &fileInfoPopIDs);
STDMETHOD(Next) (ULONG numItems, STATPROPSTG *items, ULONG *numFetched);
STDMETHOD(Skip) (ULONG numItems);
STDMETHOD(Reset) ();
STDMETHOD(Clone) (IEnumSTATPROPSTG **enumerator);
};
*/
}}
#endif

View File

@@ -0,0 +1,34 @@
// 7zSpecStream.cpp
#include "StdAfx.h"
#include "7zSpecStream.h"
STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UINT32 size, UINT32 *processedSize)
{
UINT32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
if (processedSize != 0)
*processedSize = realProcessedSize;
return result;
}
STDMETHODIMP CSequentialInStreamSizeCount2::ReadPart(void *data, UINT32 size, UINT32 *processedSize)
{
UINT32 realProcessedSize;
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
_size += realProcessedSize;
if (processedSize != 0)
*processedSize = realProcessedSize;
return result;
}
STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(
UINT64 subStream, UINT64 *value)
{
if (_getSubStreamSize == NULL)
return E_NOTIMPL;
return _getSubStreamSize->GetSubStreamSize(subStream, value);
}

38
7zip/Archive/7z/7zSpecStream.h Executable file
View File

@@ -0,0 +1,38 @@
// 7zSpecStream.h
#pragma once
#ifndef __7Z_SPEC_STREAM_H
#define __7Z_SPEC_STREAM_H
#include "../../IStream.h"
#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
class CSequentialInStreamSizeCount2:
public ISequentialInStream,
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
CMyComPtr<ISequentialInStream> _stream;
CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
UINT64 _size;
public:
void Init(ISequentialInStream *stream)
{
_stream = stream;
_getSubStreamSize = 0;
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
_size = 0;
}
UINT64 GetSize() const { return _size; }
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(GetSubStreamSize)(UINT64 subStream, UINT64 *value);
};
#endif

737
7zip/Archive/7z/7zUpdate.cpp Executable file
View File

@@ -0,0 +1,737 @@
// UpdateMain.cpp
#include "StdAfx.h"
#include "7zUpdate.h"
#include "7zFolderInStream.h"
#include "7zEncode.h"
#include "7zHandler.h"
#include "7zOut.h"
#ifndef EXCLUDE_COM
#include "7zMethods.h"
#endif
#include "../../Compress/Copy/CopyCoder.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/LimitedStreams.h"
#include "../Common/ItemNameUtils.h"
namespace NArchive {
namespace N7z {
static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
static const UINT32 kDictionaryForBCJ2_LZMA = 1 << 20;
const UINT32 kAlgorithmForBCJ2_LZMA = 2;
const UINT32 kNumFastBytesForBCJ2_LZMA = 64;
static HRESULT CopyBlock(ISequentialInStream *inStream,
ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
}
static HRESULT WriteRange(IInStream *inStream,
ISequentialOutStream *outStream,
const CUpdateRange &range,
IProgress *progress,
UINT64 &currentComplexity)
{
UINT64 position;
inStream->Seek(range.Position, STREAM_SEEK_SET, &position);
CLimitedSequentialInStream *streamSpec = new
CLimitedSequentialInStream;
CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
streamSpec->Init(inStream, range.Size);
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
localProgressSpec->Init(progress, true);
CLocalCompressProgressInfo *localCompressProgressSpec =
new CLocalCompressProgressInfo;
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
localCompressProgressSpec->Init(localProgress, &currentComplexity, &currentComplexity);
HRESULT result = CopyBlock(inStreamLimited, outStream, compressProgress);
currentComplexity += range.Size;
return result;
}
int CUpdateItem::GetExtensionPos() const
{
int slash1Pos = Name.ReverseFind(L'\\');
int slash2Pos = Name.ReverseFind(L'/');
int slashPos = MyMax(slash1Pos, slash2Pos);
int dotPos = Name.ReverseFind(L'.');
if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
return Name.Length();
return dotPos + 1;
}
UString CUpdateItem::GetExtension() const
{
return Name.Mid(GetExtensionPos());
}
struct CFolderRef
{
const CArchiveDatabaseEx *Database;
int FolderIndex;
};
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
static int CompareMethodIDs(const CMethodID &a1, const CMethodID &a2)
{
for (int i = 0; i < a1.IDSize && i < a2.IDSize; i++)
RINOZ(MyCompare(a1.ID[i], a2.ID[i]));
return MyCompare(a1.IDSize, a2.IDSize);
}
static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
{
int c1 = a1.GetCapacity();
int c2 = a2.GetCapacity();
RINOZ(MyCompare(c1, c2));
for (int i = 0; i < c1; i++)
RINOZ(MyCompare(a1[i], a2[i]));
return 0;
}
static int CompareAltCoders(const CAltCoderInfo &a1, const CAltCoderInfo &a2)
{
RINOZ(CompareMethodIDs(a1.MethodID, a2.MethodID));
return CompareBuffers(a1.Properties, a2.Properties);
}
static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
{
RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams));
RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams));
int s1 = c1.AltCoders.Size();
int s2 = c2.AltCoders.Size();
RINOZ(MyCompare(s1, s2));
for (int i = 0; i < s1; i++)
RINOZ(CompareAltCoders(c1.AltCoders[i], c2.AltCoders[i]));
return 0;
}
static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
{
RINOZ(MyCompare(b1.InIndex, b2.InIndex));
return MyCompare(b1.OutIndex, b2.OutIndex);
}
static int CompareFolders(const CFolder &f1, const CFolder &f2)
{
int s1 = f1.Coders.Size();
int s2 = f2.Coders.Size();
RINOZ(MyCompare(s1, s2));
int i;
for (i = 0; i < s1; i++)
RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
s1 = f1.BindPairs.Size();
s2 = f2.BindPairs.Size();
RINOZ(MyCompare(s1, s2));
for (i = 0; i < s1; i++)
RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
return 0;
}
static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
{
return MyStringCollateNoCase(f1.Name, f2.Name);
}
static int __cdecl CompareFolderRefs(const void *p1, const void *p2)
{
const CFolderRef &a1 = *((const CFolderRef *)p1);
const CFolderRef &a2 = *((const CFolderRef *)p2);
const CArchiveDatabaseEx &d1 = *a1.Database;
const CArchiveDatabaseEx &d2 = *a2.Database;
RINOZ(CompareFolders(
d1.Folders[a1.FolderIndex],
d2.Folders[a2.FolderIndex]));
RINOZ(MyCompare(
d1.NumUnPackStreamsVector[a1.FolderIndex],
d2.NumUnPackStreamsVector[a2.FolderIndex]));
if (d1.NumUnPackStreamsVector[a1.FolderIndex] == 0)
return 0;
return CompareFiles(
d1.Files[d1.FolderStartFileIndex[a1.FolderIndex]],
d2.Files[d2.FolderStartFileIndex[a2.FolderIndex]]);
}
////////////////////////////////////////////////////////////
static int __cdecl CompareEmptyItems(const void *p1, const void *p2)
{
const CUpdateItem &u1 = **((CUpdateItem **)p1);
const CUpdateItem &u2 = **((CUpdateItem **)p2);
if (u1.IsDirectory != u2.IsDirectory)
{
if (u1.IsDirectory)
return u1.IsAnti ? 1: -1;
return u2.IsAnti ? -1: 1;
}
if (u1.IsDirectory)
{
if (u1.IsAnti != u2.IsAnti)
return (u1.IsAnti ? 1 : -1);
int n = MyStringCollateNoCase(u1.Name, u2.Name);
return (u1.IsAnti ? (-n) : n);
}
if (u1.IsAnti != u2.IsAnti)
return (u1.IsAnti ? 1 : -1);
return MyStringCollateNoCase(u1.Name, u2.Name);
}
struct CRefItem
{
UINT32 Index;
const CUpdateItem *UpdateItem;
UINT32 ExtensionPos;
UINT32 NamePos;
bool SortByType;
CRefItem(UINT32 index, const CUpdateItem &updateItem, bool sortByType):
SortByType(sortByType),
Index(index),
UpdateItem(&updateItem),
ExtensionPos(0),
NamePos(0)
{
if (sortByType)
{
int slash1Pos = updateItem.Name.ReverseFind(L'\\');
int slash2Pos = updateItem.Name.ReverseFind(L'/');
int slashPos = MyMax(slash1Pos, slash2Pos);
if (slashPos >= 0)
NamePos = slashPos + 1;
else
NamePos = 0;
int dotPos = updateItem.Name.ReverseFind(L'.');
if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
ExtensionPos = updateItem.Name.Length();
else
ExtensionPos = dotPos + 1;
}
}
};
static int __cdecl CompareUpdateItems(const void *p1, const void *p2)
{
const CRefItem &a1 = *((CRefItem *)p1);
const CRefItem &a2 = *((CRefItem *)p2);
const CUpdateItem &u1 = *a1.UpdateItem;
const CUpdateItem &u2 = *a2.UpdateItem;
int n;
if (u1.IsDirectory != u2.IsDirectory)
{
if (u1.IsDirectory)
return u1.IsAnti ? 1: -1;
return u2.IsAnti ? -1: 1;
}
if (u1.IsDirectory)
{
if (u1.IsAnti != u2.IsAnti)
return (u1.IsAnti ? 1 : -1);
n = MyStringCollateNoCase(u1.Name, u2.Name);
return (u1.IsAnti ? (-n) : n);
}
if (a1.SortByType)
{
RINOZ(MyStringCollateNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));
RINOZ(MyStringCollateNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
if (u1.LastWriteTimeIsDefined && u2.LastWriteTimeIsDefined)
RINOZ(CompareFileTime(&u1.LastWriteTime, &u2.LastWriteTime));
RINOZ(MyCompare(u1.Size, u2.Size))
}
return MyStringCollateNoCase(u1.Name, u2.Name);
}
struct CSolidGroup
{
CCompressionMethodMode Method;
CRecordVector<UINT32> Indices;
};
static wchar_t *g_ExeExts[] =
{
L"dll",
L"exe",
L"ocx",
L"sfx",
L"sys"
};
static bool IsExeFile(const UString &ext)
{
for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)
if (ext.CompareNoCase(g_ExeExts[i]) == 0)
return true;
return false;
}
static CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
static bool GetMethodFull(const CMethodID &methodID,
UINT32 numInStreams, CMethodFull &methodResult)
{
methodResult.MethodID = methodID;
methodResult.NumInStreams = numInStreams;
methodResult.NumOutStreams = 1;
#ifndef EXCLUDE_COM
CMethodInfo methodInfo;
if (!GetMethodInfo(methodID, methodInfo))
return false;
if (!methodInfo.EncoderIsAssigned)
return false;
methodResult.EncoderClassID = methodInfo.Encoder;
methodResult.FilePath = methodInfo.FilePath;
if (methodInfo.NumOutStreams != 1 || methodInfo.NumInStreams != numInStreams)
return false;
#endif
return true;
}
static bool MakeExeMethod(const CCompressionMethodMode &method,
bool bcj2Filter, CCompressionMethodMode &exeMethod)
{
exeMethod = method;
if (bcj2Filter)
{
CMethodFull methodFull;
if (!GetMethodFull(k_BCJ2, 4, methodFull))
return false;
exeMethod.Methods.Insert(0, methodFull);
if (!GetMethodFull(k_LZMA, 1, methodFull))
return false;
{
CProperty property;
property.PropID = NCoderPropID::kAlgorithm;
property.Value = kAlgorithmForBCJ2_LZMA;
methodFull.CoderProperties.Add(property);
}
{
CProperty property;
property.PropID = NCoderPropID::kMatchFinder;
property.Value = kMatchFinderForBCJ2_LZMA;
methodFull.CoderProperties.Add(property);
}
{
CProperty property;
property.PropID = NCoderPropID::kDictionarySize;
property.Value = kDictionaryForBCJ2_LZMA;
methodFull.CoderProperties.Add(property);
}
{
CProperty property;
property.PropID = NCoderPropID::kNumFastBytes;
property.Value = kNumFastBytesForBCJ2_LZMA;
methodFull.CoderProperties.Add(property);
}
exeMethod.Methods.Add(methodFull);
exeMethod.Methods.Add(methodFull);
CBind bind;
bind.OutCoder = 0;
bind.InStream = 0;
bind.InCoder = 1;
bind.OutStream = 0;
exeMethod.Binds.Add(bind);
bind.InCoder = 2;
bind.OutStream = 1;
exeMethod.Binds.Add(bind);
bind.InCoder = 3;
bind.OutStream = 2;
exeMethod.Binds.Add(bind);
}
else
{
CMethodFull methodFull;
if (!GetMethodFull(k_BCJ_X86, 1, methodFull))
return false;
exeMethod.Methods.Insert(0, methodFull);
CBind bind;
bind.OutCoder = 0;
bind.InStream = 0;
bind.InCoder = 1;
bind.OutStream = 0;
exeMethod.Binds.Add(bind);
}
return true;
}
static void SplitFilesToGroups(
const CCompressionMethodMode &method,
bool useFilters, bool maxFilter,
const CObjectVector<CUpdateItem> &updateItems,
CObjectVector<CSolidGroup> &groups)
{
if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
useFilters = false;
groups.Clear();
groups.Add(CSolidGroup());
groups.Add(CSolidGroup());
CSolidGroup &generalGroup = groups[0];
CSolidGroup &exeGroup = groups[1];
generalGroup.Method = method;
int i;
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &updateItem = updateItems[i];
if (!updateItem.NewData)
continue;
if (!updateItem.HasStream())
continue;
if (useFilters)
{
const UString name = updateItem.Name;
int dotPos = name.ReverseFind(L'.');
if (dotPos >= 0)
{
UString ext = name.Mid(dotPos + 1);
if (IsExeFile(ext))
{
exeGroup.Indices.Add(i);
continue;
}
}
}
generalGroup.Indices.Add(i);
}
if (exeGroup.Indices.Size() > 0)
if (!MakeExeMethod(method, maxFilter, exeGroup.Method))
exeGroup.Method = method;
for (i = 0; i < groups.Size();)
if (groups[i].Indices.Size() == 0)
groups.Delete(i);
else
i++;
}
static void FromUpdateItemToFileItem(const CUpdateItem &updateItem,
CFileItem &file)
{
file.Name = NItemName::MakeLegalName(updateItem.Name);
if (updateItem.AttributesAreDefined)
file.SetAttributes(updateItem.Attributes);
// if (updateItem.CreationTimeIsDefined)
// file.SetCreationTime(updateItem.ItemInfo.CreationTime);
if (updateItem.LastWriteTimeIsDefined)
file.SetLastWriteTime(updateItem.LastWriteTime);
file.UnPackSize = updateItem.Size;
file.IsDirectory = updateItem.IsDirectory;
file.IsAnti = updateItem.IsAnti;
file.HasStream = updateItem.HasStream();
}
HRESULT Update(const NArchive::N7z::CArchiveDatabaseEx &database,
CObjectVector<CUpdateItem> &updateItems,
IOutStream *outStream,
IInStream *inStream,
NArchive::N7z::CInArchiveInfo *inArchiveInfo,
const CCompressionMethodMode &method,
const CCompressionMethodMode *headerMethod,
bool useFilters,
bool maxFilter,
bool useAdditionalHeaderStreams,
bool compressMainHeader,
IArchiveUpdateCallback *updateCallback,
UINT64 numSolidFiles, UINT64 numSolidBytes, bool solidExtension,
bool removeSfxBlock)
{
if (numSolidFiles == 0)
numSolidFiles = 1;
UINT64 startBlockSize = inArchiveInfo != 0 ?
inArchiveInfo->StartPosition: 0;
if (startBlockSize > 0 && !removeSfxBlock)
{
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> limitedStream(streamSpec);
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
streamSpec->Init(inStream, startBlockSize);
RINOK(CopyBlock(limitedStream, outStream, NULL));
}
CRecordVector<int> fileIndexToUpdateIndexMap;
fileIndexToUpdateIndexMap.Reserve(database.Files.Size());
int i;
for (i = 0; i < database.Files.Size(); i++)
fileIndexToUpdateIndexMap.Add(-1);
for(i = 0; i < updateItems.Size(); i++)
{
int index = updateItems[i].IndexInArchive;
if (index != -1)
fileIndexToUpdateIndexMap[index] = i;
}
CRecordVector<CFolderRef> folderRefs;
for(i = 0; i < database.Folders.Size(); i++)
{
UINT64 indexInFolder = 0;
UINT64 numCopyItems = 0;
UINT64 numUnPackStreams = database.NumUnPackStreamsVector[i];
for (int fileIndex = database.FolderStartFileIndex[i];
indexInFolder < numUnPackStreams; fileIndex++)
{
if (database.Files[fileIndex].HasStream)
{
indexInFolder++;
int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
if (updateIndex >= 0)
if (!updateItems[updateIndex].NewData)
numCopyItems++;
}
}
if (numCopyItems != numUnPackStreams && numCopyItems != 0)
return E_NOTIMPL; // It needs repacking !!!
if (numCopyItems > 0)
{
CFolderRef folderRef;
folderRef.Database = &database;
folderRef.FolderIndex = i;
folderRefs.Add(folderRef);
}
}
qsort(&folderRefs.Front(), folderRefs.Size(), sizeof(folderRefs[0]),
CompareFolderRefs);
CArchiveDatabase newDatabase;
/////////////////////////////////////////
// Write Empty Files & Folders
CRecordVector<const CUpdateItem *> emptyRefs;
for(i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &updateItem = updateItems[i];
if (updateItem.NewData)
{
if (updateItem.HasStream())
continue;
}
else
if (updateItem.IndexInArchive != -1)
if (database.Files[updateItem.IndexInArchive].HasStream)
continue;
emptyRefs.Add(&updateItem);
}
qsort(&emptyRefs.Front(), emptyRefs.Size(), sizeof(emptyRefs[0]),
CompareEmptyItems);
for(i = 0; i < emptyRefs.Size(); i++)
{
const CUpdateItem &updateItem = *emptyRefs[i];
CFileItem file;
if (updateItem.NewProperties)
FromUpdateItemToFileItem(updateItem, file);
else
file = database.Files[updateItem.IndexInArchive];
newDatabase.Files.Add(file);
}
////////////////////////////
COutArchive archive;
archive.Create(outStream);
RINOK(archive.SkeepPrefixArchiveHeader());
UINT64 complexity = 0;
for(i = 0; i < folderRefs.Size(); i++)
complexity += database.GetFolderFullPackSize(folderRefs[i].FolderIndex);
for(i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &updateItem = updateItems[i];
if (updateItem.NewData)
complexity += updateItem.Size;
}
RINOK(updateCallback->SetTotal(complexity));
complexity = 0;
RINOK(updateCallback->SetCompleted(&complexity));
/////////////////////////////////////////
// Write Copy Items
for(i = 0; i < folderRefs.Size(); i++)
{
int folderIndex = folderRefs[i].FolderIndex;
RINOK(WriteRange(inStream, archive.Stream,
CUpdateRange(database.GetFolderStreamPos(folderIndex, 0),
database.GetFolderFullPackSize(folderIndex)),
updateCallback, complexity));
const CFolder &folder = database.Folders[folderIndex];
UINT32 startIndex = database.FolderStartPackStreamIndex[folderIndex];
int j;
for (j = 0; j < folder.PackStreams.Size(); j++)
{
newDatabase.PackSizes.Add(database.PackSizes[startIndex + j]);
// newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]);
// newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]);
}
newDatabase.Folders.Add(folder);
UINT64 numUnPackStreams = database.NumUnPackStreamsVector[folderIndex];
newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
UINT64 indexInFolder = 0;
for (j = database.FolderStartFileIndex[folderIndex];
indexInFolder < numUnPackStreams; j++)
{
CFileItem file = database.Files[j];
if (file.HasStream)
{
indexInFolder++;
int updateIndex = fileIndexToUpdateIndexMap[j];
if (updateIndex >= 0)
{
const CUpdateItem &updateItem = updateItems[updateIndex];
if (updateItem.NewProperties)
{
CFileItem file2;
FromUpdateItemToFileItem(updateItem, file2);
file2.UnPackSize = file.UnPackSize;
file2.FileCRC = file.FileCRC;
file2.FileCRCIsDefined = file.FileCRCIsDefined;
file2.HasStream = file.HasStream;
file = file2;
}
}
newDatabase.Files.Add(file);
}
}
}
/////////////////////////////////////////
// Compress New Files
CObjectVector<CSolidGroup> groups;
SplitFilesToGroups(method, useFilters, maxFilter, updateItems, groups);
for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++)
{
const CSolidGroup &group = groups[groupIndex];
int numFiles = group.Indices.Size();
if (numFiles == 0)
continue;
CRecordVector<CRefItem> refItems;
refItems.Reserve(numFiles);
for (i = 0; i < numFiles; i++)
refItems.Add(CRefItem(group.Indices[i],
updateItems[group.Indices[i]], numSolidFiles > 1));
qsort(&refItems.Front(), refItems.Size(), sizeof(refItems[0]), CompareUpdateItems);
CRecordVector<UINT32> indices;
indices.Reserve(numFiles);
int startFileIndexInDatabase = newDatabase.Files.Size();
for (i = 0; i < numFiles; i++)
{
UINT32 index = refItems[i].Index;
indices.Add(index);
const CUpdateItem &updateItem = updateItems[index];
CFileItem file;
if (updateItem.NewProperties)
FromUpdateItemToFileItem(updateItem, file);
else
file = database.Files[updateItem.IndexInArchive];
if (file.IsAnti || file.IsDirectory)
return E_FAIL;
newDatabase.Files.Add(file);
}
CEncoder encoder(group.Method);
for (i = 0; i < numFiles;)
{
UINT64 totalSize = 0;
int numSubFiles;
UString prevExtension;
for (numSubFiles = 0; i + numSubFiles < numFiles &&
numSubFiles < numSolidFiles; numSubFiles++)
{
const CUpdateItem &updateItem = updateItems[indices[i + numSubFiles]];
totalSize += updateItem.Size;
if (totalSize > numSolidBytes)
break;
if (solidExtension)
{
UString ext = updateItem.GetExtension();
if (numSubFiles == 0)
prevExtension = ext;
else
if (ext.CollateNoCase(prevExtension) != 0)
break;
}
}
if (numSubFiles < 1)
numSubFiles = 1;
CFolderInStream *inStreamSpec = new CFolderInStream;
CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
CFolder folderItem;
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
localProgressSpec->Init(updateCallback, true);
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
localCompressProgressSpec->Init(localProgress, &complexity, NULL);
RINOK(encoder.Encode(solidInStream, NULL, folderItem,
archive.Stream, newDatabase.PackSizes, compressProgress));
// for()
// newDatabase.PackCRCsDefined.Add(false);
// newDatabase.PackCRCs.Add(0);
newDatabase.Folders.Add(folderItem);
UINT32 numUnPackStreams = 0;
for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
{
CFileItem &file = newDatabase.Files[
startFileIndexInDatabase + i + subIndex];
file.FileCRC = inStreamSpec->CRCs[subIndex];
file.UnPackSize = inStreamSpec->Sizes[subIndex];
if (file.UnPackSize != 0)
{
file.FileCRCIsDefined = true;
file.HasStream = true;
numUnPackStreams++;
complexity += file.UnPackSize;
}
else
{
file.FileCRCIsDefined = false;
file.HasStream = false;
}
}
newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
i += numSubFiles;
}
}
if (newDatabase.Files.Size() != updateItems.Size())
return E_FAIL;
return archive.WriteDatabase(newDatabase, headerMethod,
useAdditionalHeaderStreams, compressMainHeader);
}
}}

72
7zip/Archive/7z/7zUpdate.h Executable file
View File

@@ -0,0 +1,72 @@
// 7zUpdate.h
#pragma once
#ifndef __7Z_UPDATE_H
#define __7Z_UPDATE_H
#include "7zIn.h"
#include "7zCompressionMode.h"
#include "../IArchive.h"
namespace NArchive {
namespace N7z {
struct CUpdateRange
{
UINT64 Position;
UINT64 Size;
CUpdateRange() {};
CUpdateRange(UINT64 position, UINT64 size): Position(position), Size(size) {};
};
struct CUpdateItem
{
bool NewData;
bool NewProperties;
int IndexInArchive;
int IndexInClient;
UINT32 Attributes;
FILETIME CreationTime;
FILETIME LastWriteTime;
UINT64 Size;
UString Name;
bool IsAnti;
bool IsDirectory;
bool CreationTimeIsDefined;
bool LastWriteTimeIsDefined;
bool AttributesAreDefined;
const bool HasStream() const
{ return !IsDirectory && !IsAnti && Size != 0; }
CUpdateItem(): IsAnti(false) {}
void SetDirectoryStatusFromAttributes()
{ IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); };
int GetExtensionPos() const;
UString GetExtension() const;
};
HRESULT Update(const NArchive::N7z::CArchiveDatabaseEx &database,
CObjectVector<CUpdateItem> &updateItems,
IOutStream *outStream,
IInStream *inStream,
CInArchiveInfo *inArchiveInfo,
const CCompressionMethodMode &method,
const CCompressionMethodMode *headerMethod,
bool useFilters,
bool maxFilter,
bool useAdditionalHeaderStreams,
bool compressMainHeader,
IArchiveUpdateCallback *updateCallback,
UINT64 numSolidFiles, UINT64 numSolidBytes, bool solidExtension,
bool removeSfxBlock);
}}
#endif

90
7zip/Archive/7z/DllExports.cpp Executable file
View File

@@ -0,0 +1,90 @@
// DLLExports.cpp
#include "StdAfx.h"
#include <initguid.h>
#include "7zHandler.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
#include "../../../Common/NewHandler.h"
#include "../../../Common/ComTry.h"
#ifndef EXCLUDE_COM
// {23170F69-40C1-278B-06F1-070100000100}
DEFINE_GUID(CLSID_CCrypto7zAESEncoder,
0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x07, 0x01, 0x00, 0x00, 0x01, 0x00);
#else
#include "../../Compress/LZ/IMatchFinder.h"
#endif
HINSTANCE g_hInstance;
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
g_hInstance = hInstance;
return TRUE;
}
STDAPI CreateObject(
const GUID *classID,
const GUID *interfaceID,
void **outObject)
{
COM_TRY_BEGIN
*outObject = 0;
if (*classID != NArchive::N7z::CLSID_CFormat7z)
return CLASS_E_CLASSNOTAVAILABLE;
int needIn = *interfaceID == IID_IInArchive;
int needOut = *interfaceID == IID_IOutArchive;
if (needIn || needOut)
{
NArchive::N7z::CHandler *temp = new NArchive::N7z::CHandler;
if (needIn)
{
CMyComPtr<IInArchive> inArchive = (IInArchive *)temp;
*outObject = inArchive.Detach();
}
else
{
CMyComPtr<IOutArchive> outArchive = (IOutArchive *)temp;
*outObject = outArchive.Detach();
}
}
else
return E_NOINTERFACE;
COM_TRY_END
return S_OK;
}
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant propVariant;
switch(propID)
{
case NArchive::kName:
propVariant = L"7z";
break;
case NArchive::kClassID:
{
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&NArchive::N7z::CLSID_CFormat7z, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NArchive::kExtension:
propVariant = L"7z";
break;
case NArchive::kUpdate:
propVariant = true;
break;
case NArchive::kKeepName:
propVariant = false;
break;
}
propVariant.Detach(value);
return S_OK;
}

3
7zip/Archive/7z/StdAfx.cpp Executable file
View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "stdafx.h"

23
7zip/Archive/7z/StdAfx.h Executable file
View File

@@ -0,0 +1,23 @@
// stdafx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
/*
#include <stdio.h>
#include <tchar.h>
#include <atlcom.h>
#include <shlobj.h>
#include <shlguid.h>
#include <memory>
#include <new.h>
#include <time.h>
*/
#include <vector>
#include <memory>
#endif

16
7zip/Archive/7z/resource.h Executable file
View File

@@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resource.rc
//
#define IDI_ICON1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

130
7zip/Archive/7z/resource.rc Executable file
View File

@@ -0,0 +1,130 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Russian resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
#ifdef _WIN32
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Russian resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "7z.ico"
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,12,0,0
PRODUCTVERSION 3,12,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Igor Pavlov\0"
VALUE "FileDescription", "7z Plugin for 7-Zip\0"
VALUE "FileVersion", "3, 12, 0, 0\0"
VALUE "InternalName", "7z\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "7z.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 12, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED