mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-09 06:07:05 -06:00
Initialer Commit
This commit is contained in:
642
CPP/7zip/Archive/7z/7z.dsp
Normal file
642
CPP/7zip/Archive/7z/7z.dsp
Normal file
@@ -0,0 +1,642 @@
|
||||
# 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 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "EXTERNAL_CODECS" /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 /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "EXTERNAL_CODECS" /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=..\Archive.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\ArchiveExports.cpp
|
||||
# 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=.\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=.\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=.\7zRegister.cpp
|
||||
# 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=..\..\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\DynamicBuffer.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\MyString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyString.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyVector.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyVector.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.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\Wildcard.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Wildcard.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Archive Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# 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\HandlerOut.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\HandlerOut.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\MultiStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\MultiStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\OutStreamWithCRC.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\OutStreamWithCRC.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ParseProperties.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ParseProperties.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "7-Zip Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\CreateCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\CreateCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FilterCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FilterCoder.h
|
||||
# End Source File
|
||||
# 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\LockedStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\LockedStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MethodId.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MethodId.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MethodProps.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MethodProps.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\PropId.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\RegisterArc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\RegisterCodec.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
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\VirtThread.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\VirtThread.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.cpp
|
||||
# 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\System.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.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\CopyCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\CopyCoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "C"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\7zCrc.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\7zCrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\7zCrcOpt.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Alloc.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\CpuArch.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Threads.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Threads.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
29
CPP/7zip/Archive/7z/7z.dsw
Normal file
29
CPP/7zip/Archive/7z/7z.dsw
Normal 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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
3
CPP/7zip/Archive/7z/7zCompressionMode.cpp
Normal file
3
CPP/7zip/Archive/7z/7zCompressionMode.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
// CompressionMethod.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
74
CPP/7zip/Archive/7z/7zCompressionMode.h
Normal file
74
CPP/7zip/Archive/7z/7zCompressionMode.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// 7zCompressionMode.h
|
||||
|
||||
#ifndef __7Z_COMPRESSION_MODE_H
|
||||
#define __7Z_COMPRESSION_MODE_H
|
||||
|
||||
#include "../../Common/MethodId.h"
|
||||
#include "../../Common/MethodProps.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CMethodFull: public CMethodProps
|
||||
{
|
||||
CMethodId Id;
|
||||
UInt32 NumStreams;
|
||||
|
||||
bool IsSimpleCoder() const { return NumStreams == 1; }
|
||||
};
|
||||
|
||||
struct CBond2
|
||||
{
|
||||
UInt32 OutCoder;
|
||||
UInt32 OutStream;
|
||||
UInt32 InCoder;
|
||||
};
|
||||
|
||||
struct CCompressionMethodMode
|
||||
{
|
||||
/*
|
||||
if (Bonds.Empty()), then default bonds must be created
|
||||
if (Filter_was_Inserted)
|
||||
{
|
||||
Methods[0] is filter method
|
||||
Bonds don't contain bonds for filter (these bonds must be created)
|
||||
}
|
||||
*/
|
||||
|
||||
CObjectVector<CMethodFull> Methods;
|
||||
CRecordVector<CBond2> Bonds;
|
||||
|
||||
bool IsThereBond_to_Coder(unsigned coderIndex) const
|
||||
{
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].InCoder == coderIndex)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DefaultMethod_was_Inserted;
|
||||
bool Filter_was_Inserted;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 NumThreads;
|
||||
bool MultiThreadMixer;
|
||||
#endif
|
||||
|
||||
bool PasswordIsDefined;
|
||||
UString Password;
|
||||
|
||||
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
|
||||
CCompressionMethodMode():
|
||||
DefaultMethod_was_Inserted(false),
|
||||
Filter_was_Inserted(false),
|
||||
PasswordIsDefined(false)
|
||||
#ifndef _7ZIP_ST
|
||||
, NumThreads(1)
|
||||
, MultiThreadMixer(true)
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
543
CPP/7zip/Archive/7z/7zDecode.cpp
Normal file
543
CPP/7zip/Archive/7z/7zDecode.cpp
Normal file
@@ -0,0 +1,543 @@
|
||||
// 7zDecode.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
#include "7zDecode.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
class CDecProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
public:
|
||||
CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressProgressInfo)
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)
|
||||
{
|
||||
return _progress->SetRatioInfo(NULL, outSize);
|
||||
}
|
||||
|
||||
static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
|
||||
{
|
||||
bi.Clear();
|
||||
|
||||
bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
|
||||
unsigned i;
|
||||
for (i = 0; i < folder.Bonds.Size(); i++)
|
||||
{
|
||||
NCoderMixer2::CBond &bond = bi.Bonds[i];
|
||||
const N7z::CBond &folderBond = folder.Bonds[i];
|
||||
bond.PackIndex = folderBond.PackIndex;
|
||||
bond.UnpackIndex = folderBond.UnpackIndex;
|
||||
}
|
||||
|
||||
bi.Coders.ClearAndSetSize(folder.Coders.Size());
|
||||
bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
|
||||
for (i = 0; i < folder.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folder.Coders[i];
|
||||
bi.Coders[i].NumStreams = coderInfo.NumStreams;
|
||||
bi.CoderMethodIDs[i] = coderInfo.MethodID;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!bi.SetUnpackCoder())
|
||||
throw 1112;
|
||||
*/
|
||||
bi.UnpackCoder = folder.UnpackCoder;
|
||||
bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
|
||||
for (i = 0; i < folder.PackStreams.Size(); i++)
|
||||
bi.PackStreams[i] = folder.PackStreams[i];
|
||||
}
|
||||
|
||||
static inline bool AreCodersEqual(
|
||||
const NCoderMixer2::CCoderStreamsInfo &a1,
|
||||
const NCoderMixer2::CCoderStreamsInfo &a2)
|
||||
{
|
||||
return (a1.NumStreams == a2.NumStreams);
|
||||
}
|
||||
|
||||
static inline bool AreBondsEqual(
|
||||
const NCoderMixer2::CBond &a1,
|
||||
const NCoderMixer2::CBond &a2)
|
||||
{
|
||||
return
|
||||
(a1.PackIndex == a2.PackIndex) &&
|
||||
(a1.UnpackIndex == a2.UnpackIndex);
|
||||
}
|
||||
|
||||
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
|
||||
{
|
||||
if (a1.Coders.Size() != a2.Coders.Size())
|
||||
return false;
|
||||
unsigned i;
|
||||
for (i = 0; i < a1.Coders.Size(); i++)
|
||||
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
|
||||
return false;
|
||||
|
||||
if (a1.Bonds.Size() != a2.Bonds.Size())
|
||||
return false;
|
||||
for (i = 0; i < a1.Bonds.Size(); i++)
|
||||
if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
|
||||
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
|
||||
return false;
|
||||
|
||||
if (a1.PackStreams.Size() != a2.PackStreams.Size())
|
||||
return false;
|
||||
for (i = 0; i < a1.PackStreams.Size(); i++)
|
||||
if (a1.PackStreams[i] != a2.PackStreams[i])
|
||||
return false;
|
||||
|
||||
/*
|
||||
if (a1.UnpackCoder != a2.UnpackCoder)
|
||||
return false;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
CDecoder::CDecoder(bool useMixerMT):
|
||||
_bindInfoPrev_Defined(false),
|
||||
_useMixerMT(useMixerMT)
|
||||
{}
|
||||
|
||||
|
||||
struct CLockedInStream:
|
||||
public IUnknown,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Pos;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
|
||||
class CLockedSequentialInStreamMT:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLockedInStream *_glob;
|
||||
UInt64 _pos;
|
||||
CMyComPtr<IUnknown> _globRef;
|
||||
public:
|
||||
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
|
||||
{
|
||||
_globRef = lockedInStream;
|
||||
_glob = lockedInStream;
|
||||
_pos = startPos;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
|
||||
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
UInt32 realProcessedSize = 0;
|
||||
HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
|
||||
_pos += realProcessedSize;
|
||||
_glob->Pos = _pos;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
|
||||
class CLockedSequentialInStreamST:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLockedInStream *_glob;
|
||||
UInt64 _pos;
|
||||
CMyComPtr<IUnknown> _globRef;
|
||||
public:
|
||||
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
|
||||
{
|
||||
_globRef = lockedInStream;
|
||||
_glob = lockedInStream;
|
||||
_pos = startPos;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
UInt32 realProcessedSize = 0;
|
||||
HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
|
||||
_pos += realProcessedSize;
|
||||
_glob->Pos = _pos;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
HRESULT CDecoder::Decode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
UInt64 startPos,
|
||||
const CFolders &folders, unsigned folderIndex,
|
||||
const UInt64 *unpackSize
|
||||
|
||||
, ISequentialOutStream *outStream
|
||||
, ICompressProgressInfo *compressProgress
|
||||
, ISequentialInStream **
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
inStreamMainRes
|
||||
#endif
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
|
||||
CFolderEx folderInfo;
|
||||
folders.ParseFolderEx(folderIndex, folderInfo);
|
||||
|
||||
if (!folderInfo.IsDecodingSupported())
|
||||
return E_NOTIMPL;
|
||||
|
||||
CBindInfoEx bindInfo;
|
||||
Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
|
||||
if (!bindInfo.CalcMapsAndCheck())
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
|
||||
bool fullUnpack = true;
|
||||
if (unpackSize)
|
||||
{
|
||||
if (*unpackSize > folderUnpackSize)
|
||||
return E_FAIL;
|
||||
fullUnpack = (*unpackSize == folderUnpackSize);
|
||||
}
|
||||
|
||||
/*
|
||||
We don't need to init isEncrypted and passwordIsDefined
|
||||
We must upgrade them only
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
isEncrypted = false;
|
||||
passwordIsDefined = false;
|
||||
#endif
|
||||
*/
|
||||
|
||||
if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
|
||||
{
|
||||
_mixerRef.Release();
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_useMixerMT)
|
||||
#endif
|
||||
{
|
||||
_mixerMT = new NCoderMixer2::CMixerMT(false);
|
||||
_mixerRef = _mixerMT;
|
||||
_mixer = _mixerMT;
|
||||
}
|
||||
#ifdef USE_MIXER_ST
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_MIXER_ST
|
||||
_mixerST = new NCoderMixer2::CMixerST(false);
|
||||
_mixerRef = _mixerST;
|
||||
_mixer = _mixerST;
|
||||
#endif
|
||||
}
|
||||
|
||||
RINOK(_mixer->SetBindInfo(bindInfo));
|
||||
|
||||
FOR_VECTOR(i, folderInfo.Coders)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
|
||||
#ifndef _SFX
|
||||
// we don't support RAR codecs here
|
||||
if ((coderInfo.MethodID >> 8) == 0x403)
|
||||
return E_NOTIMPL;
|
||||
#endif
|
||||
|
||||
CCreatedCoder cod;
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
coderInfo.MethodID, false, cod));
|
||||
|
||||
if (coderInfo.IsSimpleCoder())
|
||||
{
|
||||
if (!cod.Coder)
|
||||
return E_NOTIMPL;
|
||||
// CMethodId m = coderInfo.MethodID;
|
||||
// isFilter = (IsFilterMethod(m) || m == k_AES);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
_mixer->AddCoder(cod);
|
||||
|
||||
// now there is no codec that uses another external codec
|
||||
/*
|
||||
#ifdef EXTERNAL_CODECS
|
||||
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
|
||||
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
// we must use g_ExternalCodecs also
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
_bindInfoPrev = bindInfo;
|
||||
_bindInfoPrev_Defined = true;
|
||||
}
|
||||
|
||||
_mixer->ReInit();
|
||||
|
||||
UInt32 packStreamIndex = 0;
|
||||
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < folderInfo.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
const CByteBuffer &props = coderInfo.Props;
|
||||
size_t size = props.Size();
|
||||
if (size > 0xFFFFFFFF)
|
||||
return E_NOTIMPL;
|
||||
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
|
||||
if (res == E_INVALIDARG)
|
||||
res = E_NOTIMPL;
|
||||
RINOK(res);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
if (mtMode)
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
isEncrypted = true;
|
||||
if (!getTextPassword)
|
||||
return E_NOTIMPL;
|
||||
CMyComBSTR passwordBSTR;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
|
||||
passwordIsDefined = true;
|
||||
password.Empty();
|
||||
size_t len = 0;
|
||||
if (passwordBSTR)
|
||||
{
|
||||
password = passwordBSTR;
|
||||
len = password.Len();
|
||||
}
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (size_t k = 0; k < len; k++)
|
||||
{
|
||||
wchar_t c = passwordBSTR[k];
|
||||
((Byte *)buffer)[k * 2] = (Byte)c;
|
||||
((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetFinishMode> setFinishMode;
|
||||
decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
|
||||
if (setFinishMode)
|
||||
{
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 numStreams = (UInt32)coderInfo.NumStreams;
|
||||
|
||||
CObjArray<UInt64> packSizes(numStreams);
|
||||
CObjArray<const UInt64 *> packSizesPointers(numStreams);
|
||||
|
||||
for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
|
||||
{
|
||||
int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
|
||||
|
||||
if (bond >= 0)
|
||||
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
|
||||
else
|
||||
{
|
||||
int index = folderInfo.Find_in_PackStreams(packStreamIndex);
|
||||
if (index < 0)
|
||||
return E_NOTIMPL;
|
||||
packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
|
||||
packSizesPointers[j] = &packSizes[j];
|
||||
}
|
||||
}
|
||||
|
||||
const UInt64 *unpackSizesPointer =
|
||||
(unpackSize && i == bindInfo.UnpackCoder) ?
|
||||
unpackSize :
|
||||
&folders.CoderUnpackSizes[unpackStreamIndexStart + i];
|
||||
|
||||
_mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
|
||||
}
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
_mixer->SelectMainCoder(!fullUnpack);
|
||||
}
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
|
||||
|
||||
CLockedInStream *lockedInStreamSpec = new CLockedInStream;
|
||||
CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
|
||||
|
||||
bool needMtLock = false;
|
||||
|
||||
if (folderInfo.PackStreams.Size() > 1)
|
||||
{
|
||||
// lockedInStream.Pos = (UInt64)(Int64)-1;
|
||||
// RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
|
||||
RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
|
||||
lockedInStreamSpec->Stream = inStream;
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
|
||||
#endif
|
||||
needMtLock = true;
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> packStream;
|
||||
UInt64 packPos = startPos + packPositions[j];
|
||||
|
||||
if (folderInfo.PackStreams.Size() == 1)
|
||||
{
|
||||
RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
|
||||
packStream = inStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_useMixerMT || needMtLock)
|
||||
#endif
|
||||
{
|
||||
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
|
||||
packStream = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
|
||||
}
|
||||
#ifdef USE_MIXER_ST
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_MIXER_ST
|
||||
CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
|
||||
packStream = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
inStreams.AddNew() = streamSpec;
|
||||
streamSpec->SetStream(packStream);
|
||||
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
|
||||
}
|
||||
|
||||
unsigned num = inStreams.Size();
|
||||
CObjArray<ISequentialInStream *> inStreamPointers(num);
|
||||
for (i = 0; i < num; i++)
|
||||
inStreamPointers[i] = inStreams[i];
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> progress2;
|
||||
if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
|
||||
progress2 = new CDecProgress(compressProgress);
|
||||
|
||||
ISequentialOutStream *outStreamPointer = outStream;
|
||||
return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
|
||||
}
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
|
||||
#else
|
||||
return E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}
|
||||
68
CPP/7zip/Archive/7z/7zDecode.h
Normal file
68
CPP/7zip/Archive/7z/7zDecode.h
Normal file
@@ -0,0 +1,68 @@
|
||||
// 7zDecode.h
|
||||
|
||||
#ifndef __7Z_DECODE_H
|
||||
#define __7Z_DECODE_H
|
||||
|
||||
#include "../Common/CoderMixer2.h"
|
||||
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CBindInfoEx: public NCoderMixer2::CBindInfo
|
||||
{
|
||||
CRecordVector<CMethodId> CoderMethodIDs;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CBindInfo::Clear();
|
||||
CoderMethodIDs.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
class CDecoder
|
||||
{
|
||||
bool _bindInfoPrev_Defined;
|
||||
CBindInfoEx _bindInfoPrev;
|
||||
|
||||
bool _useMixerMT;
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
NCoderMixer2::CMixerST *_mixerST;
|
||||
#endif
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
NCoderMixer2::CMixerMT *_mixerMT;
|
||||
#endif
|
||||
|
||||
NCoderMixer2::CMixer *_mixer;
|
||||
CMyComPtr<IUnknown> _mixerRef;
|
||||
|
||||
public:
|
||||
|
||||
CDecoder(bool useMixerMT);
|
||||
|
||||
HRESULT Decode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
UInt64 startPos,
|
||||
const CFolders &folders, unsigned folderIndex,
|
||||
const UInt64 *unpackSize // if (!unpackSize), then full folder is required
|
||||
// if (unpackSize), then only *unpackSize bytes from folder are required
|
||||
|
||||
, ISequentialOutStream *outStream
|
||||
, ICompressProgressInfo *compressProgress
|
||||
, ISequentialInStream **inStreamMainRes
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#endif
|
||||
);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
656
CPP/7zip/Archive/7z/7zEncode.cpp
Normal file
656
CPP/7zip/Archive/7z/7zEncode.cpp
Normal file
@@ -0,0 +1,656 @@
|
||||
// 7zEncode.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/FilterCoder.h"
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/InOutTempBuffer.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
#include "7zEncode.h"
|
||||
#include "7zSpecStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
void CEncoder::InitBindConv()
|
||||
{
|
||||
unsigned numIn = _bindInfo.Coders.Size();
|
||||
|
||||
_SrcIn_to_DestOut.ClearAndSetSize(numIn);
|
||||
_DestOut_to_SrcIn.ClearAndSetSize(numIn);
|
||||
|
||||
unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
|
||||
_SrcOut_to_DestIn.ClearAndSetSize(numOut);
|
||||
// _DestIn_to_SrcOut.ClearAndSetSize(numOut);
|
||||
|
||||
UInt32 destIn = 0;
|
||||
UInt32 destOut = 0;
|
||||
|
||||
for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
|
||||
{
|
||||
i--;
|
||||
|
||||
const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
|
||||
|
||||
numIn--;
|
||||
numOut -= coder.NumStreams;
|
||||
|
||||
_SrcIn_to_DestOut[numIn] = destOut;
|
||||
_DestOut_to_SrcIn[destOut] = numIn;
|
||||
|
||||
destOut++;
|
||||
|
||||
for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
|
||||
{
|
||||
UInt32 index = numOut + j;
|
||||
_SrcOut_to_DestIn[index] = destIn;
|
||||
// _DestIn_to_SrcOut[destIn] = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEncoder::SetFolder(CFolder &folder)
|
||||
{
|
||||
folder.Bonds.SetSize(_bindInfo.Bonds.Size());
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _bindInfo.Bonds.Size(); i++)
|
||||
{
|
||||
CBond &fb = folder.Bonds[i];
|
||||
const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
|
||||
fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex];
|
||||
fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex];
|
||||
}
|
||||
|
||||
folder.Coders.SetSize(_bindInfo.Coders.Size());
|
||||
|
||||
for (i = 0; i < _bindInfo.Coders.Size(); i++)
|
||||
{
|
||||
CCoderInfo &coderInfo = folder.Coders[i];
|
||||
const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
|
||||
|
||||
coderInfo.NumStreams = coderStreamsInfo.NumStreams;
|
||||
coderInfo.MethodID = _decompressionMethods[i];
|
||||
// we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
|
||||
}
|
||||
|
||||
folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
|
||||
|
||||
for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
|
||||
folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
|
||||
coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
|
||||
if (setCoderProperties)
|
||||
return props.SetCoderProps(setCoderProperties, dataSizeReduce);
|
||||
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
|
||||
{
|
||||
_progress = progress;
|
||||
OutSize = 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
|
||||
{
|
||||
UInt64 outSize2;
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
#endif
|
||||
outSize2 = OutSize;
|
||||
}
|
||||
|
||||
if (_progress)
|
||||
return _progress->SetRatioInfo(inSize, &outSize2);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CEncoder::CreateMixerCoder(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const UInt64 *inSizeForReduce)
|
||||
{
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_options.MultiThreadMixer)
|
||||
#endif
|
||||
{
|
||||
_mixerMT = new NCoderMixer2::CMixerMT(true);
|
||||
_mixerRef = _mixerMT;
|
||||
_mixer = _mixerMT;
|
||||
}
|
||||
#ifdef USE_MIXER_ST
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_MIXER_ST
|
||||
_mixerST = new NCoderMixer2::CMixerST(true);
|
||||
_mixerRef = _mixerST;
|
||||
_mixer = _mixerST;
|
||||
#endif
|
||||
}
|
||||
|
||||
RINOK(_mixer->SetBindInfo(_bindInfo));
|
||||
|
||||
FOR_VECTOR (m, _options.Methods)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[m];
|
||||
|
||||
CCreatedCoder cod;
|
||||
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodFull.Id, true, cod));
|
||||
|
||||
if (cod.NumStreams != methodFull.NumStreams)
|
||||
return E_FAIL;
|
||||
if (!cod.Coder && !cod.Coder2)
|
||||
return E_FAIL;
|
||||
|
||||
CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon));
|
||||
|
||||
/*
|
||||
CMyComPtr<ICryptoResetSalt> resetSalt;
|
||||
encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
|
||||
if (resetSalt)
|
||||
{
|
||||
resetSalt->ResetSalt();
|
||||
}
|
||||
*/
|
||||
|
||||
// now there is no codec that uses another external codec
|
||||
/*
|
||||
#ifdef EXTERNAL_CODECS
|
||||
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
|
||||
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
// we must use g_ExternalCodecs also
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
|
||||
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
const unsigned sizeInBytes = _options.Password.Len() * 2;
|
||||
CByteBuffer buffer(sizeInBytes);
|
||||
for (unsigned i = 0; i < _options.Password.Len(); i++)
|
||||
{
|
||||
wchar_t c = _options.Password[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));
|
||||
}
|
||||
|
||||
_mixer->AddCoder(cod);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CSequentialOutTempBufferImp2:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CInOutTempBuffer *_buf;
|
||||
public:
|
||||
CMtEncMultiProgress *_mtProgresSpec;
|
||||
|
||||
CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {}
|
||||
void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)
|
||||
{
|
||||
if (!_buf->Write(data, size))
|
||||
{
|
||||
if (processed)
|
||||
*processed = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
if (processed)
|
||||
*processed = size;
|
||||
if (_mtProgresSpec)
|
||||
_mtProgresSpec->AddOutSize(size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
class CSequentialOutMtNotify:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
CMtEncMultiProgress *_mtProgresSpec;
|
||||
|
||||
CSequentialOutMtNotify(): _mtProgresSpec(NULL) {}
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)
|
||||
{
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT res = _stream->Write(data, size, &realProcessed);
|
||||
if (processed)
|
||||
*processed = realProcessed;
|
||||
if (_mtProgresSpec)
|
||||
_mtProgresSpec->AddOutSize(size);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CEncoder::Encode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream,
|
||||
// const UInt64 *inStreamSize,
|
||||
const UInt64 *inSizeForReduce,
|
||||
CFolder &folderItem,
|
||||
CRecordVector<UInt64> &coderUnpackSizes,
|
||||
UInt64 &unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
CRecordVector<UInt64> &packSizes,
|
||||
ICompressProgressInfo *compressProgress)
|
||||
{
|
||||
RINOK(EncoderConstr());
|
||||
|
||||
if (!_mixerRef)
|
||||
{
|
||||
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
|
||||
}
|
||||
|
||||
_mixer->ReInit();
|
||||
|
||||
CMtEncMultiProgress *mtProgressSpec = NULL;
|
||||
CMyComPtr<ICompressProgressInfo> mtProgress;
|
||||
|
||||
CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
|
||||
CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
|
||||
|
||||
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
|
||||
CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
|
||||
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
|
||||
|
||||
unsigned numMethods = _bindInfo.Coders.Size();
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
|
||||
iotb.Create();
|
||||
iotb.InitWriting();
|
||||
}
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
|
||||
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
|
||||
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
|
||||
tempBuffers.Add(tempBuffer);
|
||||
tempBufferSpecs.Add(tempBufferSpec);
|
||||
}
|
||||
|
||||
for (i = 0; i < numMethods; i++)
|
||||
_mixer->SetCoderInfo(i, NULL, NULL);
|
||||
|
||||
|
||||
/* inStreamSize can be used by BCJ2 to set optimal range of conversion.
|
||||
But current BCJ2 encoder uses also another way to check exact size of current file.
|
||||
So inStreamSize is not required. */
|
||||
|
||||
/*
|
||||
if (inStreamSize)
|
||||
_mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
|
||||
*/
|
||||
|
||||
|
||||
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
|
||||
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
|
||||
|
||||
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
|
||||
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
|
||||
|
||||
inStreamSizeCountSpec->Init(inStream);
|
||||
|
||||
ISequentialInStream *inStreamPointer = inStreamSizeCount;
|
||||
CRecordVector<ISequentialOutStream *> outStreamPointers;
|
||||
|
||||
SetFolder(folderItem);
|
||||
|
||||
for (i = 0; i < numMethods; i++)
|
||||
{
|
||||
IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
|
||||
|
||||
CMyComPtr<ICryptoResetInitVector> resetInitVector;
|
||||
coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
|
||||
if (resetInitVector)
|
||||
{
|
||||
resetInitVector->ResetInitVector();
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
|
||||
coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
|
||||
|
||||
CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
|
||||
|
||||
if (writeCoderProperties)
|
||||
{
|
||||
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
|
||||
outStreamSpec->Init();
|
||||
writeCoderProperties->WriteCoderProperties(dynOutStream);
|
||||
outStreamSpec->CopyToBuffer(props);
|
||||
}
|
||||
else
|
||||
props.Free();
|
||||
}
|
||||
|
||||
_mixer->SelectMainCoder(false);
|
||||
UInt32 mainCoder = _mixer->MainCoderIndex;
|
||||
|
||||
bool useMtProgress = false;
|
||||
if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
|
||||
{
|
||||
#ifdef _7ZIP_ST
|
||||
if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
|
||||
#endif
|
||||
useMtProgress = true;
|
||||
}
|
||||
|
||||
if (useMtProgress)
|
||||
{
|
||||
mtProgressSpec = new CMtEncMultiProgress;
|
||||
mtProgress = mtProgressSpec;
|
||||
mtProgressSpec->Init(compressProgress);
|
||||
|
||||
mtOutStreamNotifySpec = new CSequentialOutMtNotify;
|
||||
mtOutStreamNotify = mtOutStreamNotifySpec;
|
||||
mtOutStreamNotifySpec->_stream = outStream;
|
||||
mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
|
||||
|
||||
FOR_VECTOR(t, tempBufferSpecs)
|
||||
{
|
||||
tempBufferSpecs[t]->_mtProgresSpec = mtProgressSpec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_bindInfo.PackStreams.Size() != 0)
|
||||
{
|
||||
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
outStreamSizeCount = outStreamSizeCountSpec;
|
||||
outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
outStreamPointers.Add(outStreamSizeCount);
|
||||
}
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
outStreamPointers.Add(tempBuffers[i - 1]);
|
||||
|
||||
RINOK(_mixer->Code(
|
||||
&inStreamPointer,
|
||||
&outStreamPointers.Front(),
|
||||
mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
|
||||
|
||||
if (_bindInfo.PackStreams.Size() != 0)
|
||||
packSizes.Add(outStreamSizeCountSpec->GetSize());
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
|
||||
RINOK(inOutTempBuffer.WriteToStream(outStream));
|
||||
packSizes.Add(inOutTempBuffer.GetDataSize());
|
||||
}
|
||||
|
||||
unpackSize = 0;
|
||||
|
||||
for (i = 0; i < _bindInfo.Coders.Size(); i++)
|
||||
{
|
||||
int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
|
||||
UInt64 streamSize;
|
||||
if (bond < 0)
|
||||
{
|
||||
streamSize = inStreamSizeCountSpec->GetSize();
|
||||
unpackSize = streamSize;
|
||||
}
|
||||
else
|
||||
streamSize = _mixer->GetBondStreamSize(bond);
|
||||
coderUnpackSizes.Add(streamSize);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
CEncoder::CEncoder(const CCompressionMethodMode &options):
|
||||
_constructed(false)
|
||||
{
|
||||
if (options.IsEmpty())
|
||||
throw 1;
|
||||
|
||||
_options = options;
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
_mixerST = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
_mixerMT = NULL;
|
||||
#endif
|
||||
|
||||
_mixer = NULL;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CEncoder::EncoderConstr()
|
||||
{
|
||||
if (_constructed)
|
||||
return S_OK;
|
||||
if (_options.Methods.IsEmpty())
|
||||
{
|
||||
// it has only password method;
|
||||
if (!_options.PasswordIsDefined)
|
||||
throw 1;
|
||||
if (!_options.Bonds.IsEmpty())
|
||||
throw 1;
|
||||
|
||||
CMethodFull method;
|
||||
method.Id = k_AES;
|
||||
method.NumStreams = 1;
|
||||
_options.Methods.Add(method);
|
||||
|
||||
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
|
||||
coderStreamsInfo.NumStreams = 1;
|
||||
_bindInfo.Coders.Add(coderStreamsInfo);
|
||||
|
||||
_bindInfo.PackStreams.Add(0);
|
||||
_bindInfo.UnpackCoder = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
UInt32 numOutStreams = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _options.Methods.Size(); i++)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[i];
|
||||
NCoderMixer2::CCoderStreamsInfo cod;
|
||||
|
||||
cod.NumStreams = methodFull.NumStreams;
|
||||
|
||||
if (_options.Bonds.IsEmpty())
|
||||
{
|
||||
// if there are no bonds in options, we create bonds via first streams of coders
|
||||
if (i != _options.Methods.Size() - 1)
|
||||
{
|
||||
NCoderMixer2::CBond bond;
|
||||
bond.PackIndex = numOutStreams;
|
||||
bond.UnpackIndex = i + 1; // it's next coder
|
||||
_bindInfo.Bonds.Add(bond);
|
||||
}
|
||||
else if (cod.NumStreams != 0)
|
||||
_bindInfo.PackStreams.Insert(0, numOutStreams);
|
||||
|
||||
for (UInt32 j = 1; j < cod.NumStreams; j++)
|
||||
_bindInfo.PackStreams.Add(numOutStreams + j);
|
||||
}
|
||||
|
||||
numOutStreams += cod.NumStreams;
|
||||
|
||||
_bindInfo.Coders.Add(cod);
|
||||
}
|
||||
|
||||
if (!_options.Bonds.IsEmpty())
|
||||
{
|
||||
for (i = 0; i < _options.Bonds.Size(); i++)
|
||||
{
|
||||
NCoderMixer2::CBond mixerBond;
|
||||
const CBond2 &bond = _options.Bonds[i];
|
||||
if (bond.InCoder >= _bindInfo.Coders.Size()
|
||||
|| bond.OutCoder >= _bindInfo.Coders.Size()
|
||||
|| bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
|
||||
return E_INVALIDARG;
|
||||
mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
|
||||
mixerBond.UnpackIndex = bond.InCoder;
|
||||
_bindInfo.Bonds.Add(mixerBond);
|
||||
}
|
||||
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
if (_bindInfo.FindBond_for_PackStream(i) == -1)
|
||||
_bindInfo.PackStreams.Add(i);
|
||||
}
|
||||
|
||||
if (!_bindInfo.SetUnpackCoder())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!_bindInfo.CalcMapsAndCheck())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_bindInfo.PackStreams.Size() != 1)
|
||||
{
|
||||
/* main_PackStream is pack stream of main path of coders tree.
|
||||
We find main_PackStream, and place to start of list of out streams.
|
||||
It allows to use more optimal memory usage for temp buffers,
|
||||
if main_PackStream is largest stream. */
|
||||
|
||||
UInt32 ci = _bindInfo.UnpackCoder;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (_bindInfo.Coders[ci].NumStreams == 0)
|
||||
break;
|
||||
|
||||
UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
|
||||
int bond = _bindInfo.FindBond_for_PackStream(outIndex);
|
||||
if (bond >= 0)
|
||||
{
|
||||
ci = _bindInfo.Bonds[bond].UnpackIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
int si = _bindInfo.FindStream_in_PackStreams(outIndex);
|
||||
if (si >= 0)
|
||||
_bindInfo.PackStreams.MoveToFront(si);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
|
||||
|
||||
unsigned numInStreams = _bindInfo.Coders.Size();
|
||||
|
||||
for (i = 0; i < numCryptoStreams; i++)
|
||||
{
|
||||
NCoderMixer2::CBond bond;
|
||||
bond.UnpackIndex = numInStreams + i;
|
||||
bond.PackIndex = _bindInfo.PackStreams[i];
|
||||
_bindInfo.Bonds.Add(bond);
|
||||
}
|
||||
_bindInfo.PackStreams.Clear();
|
||||
|
||||
/*
|
||||
if (numCryptoStreams == 0)
|
||||
numCryptoStreams = 1;
|
||||
*/
|
||||
|
||||
for (i = 0; i < numCryptoStreams; i++)
|
||||
{
|
||||
CMethodFull method;
|
||||
method.NumStreams = 1;
|
||||
method.Id = k_AES;
|
||||
_options.Methods.Add(method);
|
||||
|
||||
NCoderMixer2::CCoderStreamsInfo cod;
|
||||
cod.NumStreams = 1;
|
||||
_bindInfo.Coders.Add(cod);
|
||||
|
||||
_bindInfo.PackStreams.Add(numOutStreams++);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (unsigned i = _options.Methods.Size(); i != 0;)
|
||||
_decompressionMethods.Add(_options.Methods[--i].Id);
|
||||
|
||||
if (_bindInfo.Coders.Size() > 16)
|
||||
return E_INVALIDARG;
|
||||
if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!_bindInfo.CalcMapsAndCheck())
|
||||
return E_INVALIDARG;
|
||||
|
||||
InitBindConv();
|
||||
_constructed = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CEncoder::~CEncoder() {}
|
||||
|
||||
}}
|
||||
92
CPP/7zip/Archive/7z/7zEncode.h
Normal file
92
CPP/7zip/Archive/7z/7zEncode.h
Normal file
@@ -0,0 +1,92 @@
|
||||
// 7zEncode.h
|
||||
|
||||
#ifndef __7Z_ENCODE_H
|
||||
#define __7Z_ENCODE_H
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
|
||||
#include "../Common/CoderMixer2.h"
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
class CMtEncMultiProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
#ifndef _7ZIP_ST
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
#endif
|
||||
|
||||
public:
|
||||
UInt64 OutSize;
|
||||
|
||||
CMtEncMultiProgress(): OutSize(0) {}
|
||||
|
||||
void Init(ICompressProgressInfo *progress);
|
||||
|
||||
void AddOutSize(UInt64 addOutSize)
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
#endif
|
||||
OutSize += addOutSize;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressProgressInfo)
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
class CEncoder
|
||||
{
|
||||
#ifdef USE_MIXER_ST
|
||||
NCoderMixer2::CMixerST *_mixerST;
|
||||
#endif
|
||||
#ifdef USE_MIXER_MT
|
||||
NCoderMixer2::CMixerMT *_mixerMT;
|
||||
#endif
|
||||
|
||||
NCoderMixer2::CMixer *_mixer;
|
||||
CMyComPtr<IUnknown> _mixerRef;
|
||||
|
||||
CCompressionMethodMode _options;
|
||||
NCoderMixer2::CBindInfo _bindInfo;
|
||||
CRecordVector<CMethodId> _decompressionMethods;
|
||||
|
||||
CRecordVector<UInt32> _SrcIn_to_DestOut;
|
||||
CRecordVector<UInt32> _SrcOut_to_DestIn;
|
||||
// CRecordVector<UInt32> _DestIn_to_SrcOut;
|
||||
CRecordVector<UInt32> _DestOut_to_SrcIn;
|
||||
|
||||
void InitBindConv();
|
||||
void SetFolder(CFolder &folder);
|
||||
|
||||
HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const UInt64 *inSizeForReduce);
|
||||
|
||||
bool _constructed;
|
||||
public:
|
||||
|
||||
CEncoder(const CCompressionMethodMode &options);
|
||||
~CEncoder();
|
||||
HRESULT EncoderConstr();
|
||||
HRESULT Encode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream,
|
||||
// const UInt64 *inStreamSize,
|
||||
const UInt64 *inSizeForReduce,
|
||||
CFolder &folderItem,
|
||||
CRecordVector<UInt64> &coderUnpackSizes,
|
||||
UInt64 &unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
CRecordVector<UInt64> &packSizes,
|
||||
ICompressProgressInfo *compressProgress);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
408
CPP/7zip/Archive/7z/7zExtract.cpp
Normal file
408
CPP/7zip/Archive/7z/7zExtract.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
// 7zExtract.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
|
||||
#include "7zDecode.h"
|
||||
#include "7zHandler.h"
|
||||
|
||||
// EXTERN_g_ExternalCodecs
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
class CFolderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
public:
|
||||
bool TestMode;
|
||||
bool CheckCrc;
|
||||
private:
|
||||
bool _fileIsOpen;
|
||||
bool _calcCrc;
|
||||
UInt32 _crc;
|
||||
UInt64 _rem;
|
||||
|
||||
const UInt32 *_indexes;
|
||||
unsigned _numFiles;
|
||||
unsigned _fileIndex;
|
||||
|
||||
HRESULT OpenFile(bool isCorrupted = false);
|
||||
HRESULT CloseFile_and_SetResult(Int32 res);
|
||||
HRESULT CloseFile();
|
||||
HRESULT ProcessEmptyFiles();
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
|
||||
const CDbEx *_db;
|
||||
CMyComPtr<IArchiveExtractCallback> ExtractCallback;
|
||||
|
||||
bool ExtraWriteWasCut;
|
||||
|
||||
CFolderOutStream():
|
||||
TestMode(false),
|
||||
CheckCrc(true)
|
||||
{}
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);
|
||||
HRESULT FlushCorrupted(Int32 callbackOperationResult);
|
||||
|
||||
bool WasWritingFinished() const { return _numFiles == 0; }
|
||||
};
|
||||
|
||||
|
||||
HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)
|
||||
{
|
||||
_fileIndex = startIndex;
|
||||
_indexes = indexes;
|
||||
_numFiles = numFiles;
|
||||
|
||||
_fileIsOpen = false;
|
||||
ExtraWriteWasCut = false;
|
||||
|
||||
return ProcessEmptyFiles();
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
|
||||
{
|
||||
const CFileItem &fi = _db->Files[_fileIndex];
|
||||
UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);
|
||||
Int32 askMode = (_fileIndex == nextFileIndex) ?
|
||||
(TestMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract) :
|
||||
NExtract::NAskMode::kSkip;
|
||||
|
||||
if (isCorrupted
|
||||
&& askMode == NExtract::NAskMode::kExtract
|
||||
&& !_db->IsItemAnti(_fileIndex)
|
||||
&& !fi.IsDir)
|
||||
askMode = NExtract::NAskMode::kTest;
|
||||
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode));
|
||||
|
||||
_stream = realOutStream;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);
|
||||
|
||||
_fileIsOpen = true;
|
||||
_rem = fi.Size;
|
||||
|
||||
if (askMode == NExtract::NAskMode::kExtract
|
||||
&& !realOutStream
|
||||
&& !_db->IsItemAnti(_fileIndex)
|
||||
&& !fi.IsDir)
|
||||
askMode = NExtract::NAskMode::kSkip;
|
||||
return ExtractCallback->PrepareOperation(askMode);
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)
|
||||
{
|
||||
_stream.Release();
|
||||
_fileIsOpen = false;
|
||||
|
||||
if (!_indexes)
|
||||
_numFiles--;
|
||||
else if (*_indexes == _fileIndex)
|
||||
{
|
||||
_indexes++;
|
||||
_numFiles--;
|
||||
}
|
||||
|
||||
_fileIndex++;
|
||||
return ExtractCallback->SetOperationResult(res);
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::CloseFile()
|
||||
{
|
||||
const CFileItem &fi = _db->Files[_fileIndex];
|
||||
return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?
|
||||
NExtract::NOperationResult::kOK :
|
||||
NExtract::NOperationResult::kCRCError);
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::ProcessEmptyFiles()
|
||||
{
|
||||
while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)
|
||||
{
|
||||
RINOK(OpenFile());
|
||||
RINOK(CloseFile());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
UInt32 cur = (size < _rem ? size : (UInt32)_rem);
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Write(data, cur, &cur);
|
||||
if (_calcCrc)
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
if (processedSize)
|
||||
*processedSize += cur;
|
||||
data = (const Byte *)data + cur;
|
||||
size -= cur;
|
||||
_rem -= cur;
|
||||
if (_rem == 0)
|
||||
{
|
||||
RINOK(CloseFile());
|
||||
RINOK(ProcessEmptyFiles());
|
||||
}
|
||||
RINOK(result);
|
||||
if (cur == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
RINOK(ProcessEmptyFiles());
|
||||
if (_numFiles == 0)
|
||||
{
|
||||
// we support partial extracting
|
||||
/*
|
||||
if (processedSize)
|
||||
*processedSize += size;
|
||||
break;
|
||||
*/
|
||||
ExtraWriteWasCut = true;
|
||||
// return S_FALSE;
|
||||
return k_My_HRESULT_WritingWasCut;
|
||||
}
|
||||
RINOK(OpenFile());
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)
|
||||
{
|
||||
while (_numFiles != 0)
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
RINOK(CloseFile_and_SetResult(callbackOperationResult));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(OpenFile(true));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
|
||||
|
||||
UInt64 importantTotalUnpacked = 0;
|
||||
|
||||
// numItems = (UInt32)(Int32)-1;
|
||||
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _db.Files.Size();
|
||||
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
CNum prevFolder = kNumNoIndex;
|
||||
UInt32 nextFile = 0;
|
||||
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
UInt32 fileIndex = allFilesMode ? i : indices[i];
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
|
||||
if (folderIndex == kNumNoIndex)
|
||||
continue;
|
||||
if (folderIndex != prevFolder || fileIndex < nextFile)
|
||||
nextFile = _db.FolderStartFileIndex[folderIndex];
|
||||
for (CNum index = nextFile; index <= fileIndex; index++)
|
||||
importantTotalUnpacked += _db.Files[index].Size;
|
||||
nextFile = fileIndex + 1;
|
||||
prevFolder = folderIndex;
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(extractCallback->SetTotal(importantTotalUnpacked));
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
CDecoder decoder(
|
||||
#if !defined(USE_MIXER_MT)
|
||||
false
|
||||
#elif !defined(USE_MIXER_ST)
|
||||
true
|
||||
#elif !defined(__7Z_SET_PROPERTIES)
|
||||
#ifdef _7ZIP_ST
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
#else
|
||||
_useMultiThreadMixer
|
||||
#endif
|
||||
);
|
||||
|
||||
UInt64 curPacked, curUnpacked;
|
||||
|
||||
CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
|
||||
extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
|
||||
|
||||
CFolderOutStream *folderOutStream = new CFolderOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
|
||||
|
||||
folderOutStream->_db = &_db;
|
||||
folderOutStream->ExtractCallback = extractCallback;
|
||||
folderOutStream->TestMode = (testModeSpec != 0);
|
||||
folderOutStream->CheckCrc = (_crcSize != 0);
|
||||
|
||||
for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)
|
||||
{
|
||||
RINOK(lps->SetCur());
|
||||
|
||||
if (i >= numItems)
|
||||
break;
|
||||
|
||||
curUnpacked = 0;
|
||||
curPacked = 0;
|
||||
|
||||
UInt32 fileIndex = allFilesMode ? i : indices[i];
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
|
||||
|
||||
UInt32 numSolidFiles = 1;
|
||||
|
||||
if (folderIndex != kNumNoIndex)
|
||||
{
|
||||
curPacked = _db.GetFolderFullPackSize(folderIndex);
|
||||
UInt32 nextFile = fileIndex + 1;
|
||||
fileIndex = _db.FolderStartFileIndex[folderIndex];
|
||||
UInt32 k;
|
||||
|
||||
for (k = i + 1; k < numItems; k++)
|
||||
{
|
||||
UInt32 fileIndex2 = allFilesMode ? k : indices[k];
|
||||
if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex
|
||||
|| fileIndex2 < nextFile)
|
||||
break;
|
||||
nextFile = fileIndex2 + 1;
|
||||
}
|
||||
|
||||
numSolidFiles = k - i;
|
||||
|
||||
for (k = fileIndex; k < nextFile; k++)
|
||||
curUnpacked += _db.Files[k].Size;
|
||||
}
|
||||
|
||||
{
|
||||
HRESULT result = folderOutStream->Init(fileIndex,
|
||||
allFilesMode ? NULL : indices + i,
|
||||
numSolidFiles);
|
||||
|
||||
i += numSolidFiles;
|
||||
|
||||
RINOK(result);
|
||||
}
|
||||
|
||||
// to test solid block with zero unpacked size we disable that code
|
||||
if (folderOutStream->WasWritingFinished())
|
||||
continue;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (extractCallback)
|
||||
extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
#ifndef _NO_CRYPTO
|
||||
bool isEncrypted = false;
|
||||
bool passwordIsDefined = false;
|
||||
UString password;
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT result = decoder.Decode(
|
||||
EXTERNAL_CODECS_VARS
|
||||
_inStream,
|
||||
_db.ArcInfo.DataStartPosition,
|
||||
_db, folderIndex,
|
||||
&curUnpacked,
|
||||
|
||||
outStream,
|
||||
progress,
|
||||
NULL // *inStreamMainRes
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, true, _numThreads
|
||||
#endif
|
||||
);
|
||||
|
||||
if (result == S_FALSE || result == E_NOTIMPL)
|
||||
{
|
||||
bool wasFinished = folderOutStream->WasWritingFinished();
|
||||
|
||||
int resOp = (result == S_FALSE ?
|
||||
NExtract::NOperationResult::kDataError :
|
||||
NExtract::NOperationResult::kUnsupportedMethod);
|
||||
|
||||
RINOK(folderOutStream->FlushCorrupted(resOp));
|
||||
|
||||
if (wasFinished)
|
||||
{
|
||||
// we don't show error, if it's after required files
|
||||
if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)
|
||||
{
|
||||
RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
|
||||
// continue;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
136
CPP/7zip/Archive/7z/7zFolderInStream.cpp
Normal file
136
CPP/7zip/Archive/7z/7zFolderInStream.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
// 7zFolderInStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "7zFolderInStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
|
||||
const UInt32 *indexes, unsigned numFiles)
|
||||
{
|
||||
_updateCallback = updateCallback;
|
||||
_indexes = indexes;
|
||||
_numFiles = numFiles;
|
||||
_index = 0;
|
||||
|
||||
Processed.ClearAndReserve(numFiles);
|
||||
CRCs.ClearAndReserve(numFiles);
|
||||
Sizes.ClearAndReserve(numFiles);
|
||||
|
||||
_pos = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_size_Defined = false;
|
||||
_size = 0;
|
||||
|
||||
_stream.Release();
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::OpenStream()
|
||||
{
|
||||
_pos = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_size_Defined = false;
|
||||
_size = 0;
|
||||
|
||||
while (_index < _numFiles)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> stream;
|
||||
HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != S_FALSE)
|
||||
return result;
|
||||
}
|
||||
|
||||
_stream = stream;
|
||||
|
||||
if (stream)
|
||||
{
|
||||
CMyComPtr<IStreamGetSize> streamGetSize;
|
||||
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
|
||||
if (streamGetSize)
|
||||
{
|
||||
if (streamGetSize->GetSize(&_size) == S_OK)
|
||||
_size_Defined = true;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_index++;
|
||||
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
AddFileInfo(result == S_OK);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CFolderInStream::AddFileInfo(bool isProcessed)
|
||||
{
|
||||
Processed.Add(isProcessed);
|
||||
Sizes.Add(_pos);
|
||||
CRCs.Add(CRC_GET_DIGEST(_crc));
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
if (_stream)
|
||||
{
|
||||
UInt32 processed2;
|
||||
RINOK(_stream->Read(data, size, &processed2));
|
||||
if (processed2 != 0)
|
||||
{
|
||||
_crc = CrcUpdate(_crc, data, processed2);
|
||||
_pos += processed2;
|
||||
if (processedSize)
|
||||
*processedSize = processed2;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_stream.Release();
|
||||
_index++;
|
||||
AddFileInfo(true);
|
||||
|
||||
_pos = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_size_Defined = false;
|
||||
_size = 0;
|
||||
|
||||
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
|
||||
if (_index >= _numFiles)
|
||||
break;
|
||||
RINOK(OpenStream());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
*value = 0;
|
||||
if (subStream > Sizes.Size())
|
||||
return S_FALSE; // E_FAIL;
|
||||
|
||||
unsigned index = (unsigned)subStream;
|
||||
if (index < Sizes.Size())
|
||||
{
|
||||
*value = Sizes[index];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!_size_Defined)
|
||||
{
|
||||
*value = _pos;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
*value = (_pos > _size ? _pos : _size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
61
CPP/7zip/Archive/7z/7zFolderInStream.h
Normal file
61
CPP/7zip/Archive/7z/7zFolderInStream.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// 7zFolderInStream.h
|
||||
|
||||
#ifndef __7Z_FOLDER_IN_STREAM_H
|
||||
#define __7Z_FOLDER_IN_STREAM_H
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../IArchive.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
class CFolderInStream:
|
||||
public ISequentialInStream,
|
||||
public ICompressGetSubStreamSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _pos;
|
||||
UInt32 _crc;
|
||||
bool _size_Defined;
|
||||
UInt64 _size;
|
||||
|
||||
const UInt32 *_indexes;
|
||||
unsigned _numFiles;
|
||||
unsigned _index;
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
|
||||
|
||||
HRESULT OpenStream();
|
||||
void AddFileInfo(bool isProcessed);
|
||||
|
||||
public:
|
||||
CRecordVector<bool> Processed;
|
||||
CRecordVector<UInt32> CRCs;
|
||||
CRecordVector<UInt64> Sizes;
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
|
||||
|
||||
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
|
||||
|
||||
bool WasFinished() const { return _index == _numFiles; }
|
||||
|
||||
UInt64 GetFullSize() const
|
||||
{
|
||||
UInt64 size = 0;
|
||||
FOR_VECTOR (i, Sizes)
|
||||
size += Sizes[i];
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
755
CPP/7zip/Archive/7z/7zHandler.cpp
Normal file
755
CPP/7zip/Archive/7z/7zHandler.cpp
Normal file
@@ -0,0 +1,755 @@
|
||||
// 7zHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
#ifndef __7Z_SET_PROPERTIES
|
||||
#include "../../../Windows/System.h"
|
||||
#endif
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
#include "7zHandler.h"
|
||||
#include "7zProperties.h"
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
#ifdef EXTRACT_ONLY
|
||||
#include "../Common/ParseProperties.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
CHandler::CHandler()
|
||||
{
|
||||
#ifndef _NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
#endif
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
_crcSize = 4;
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
_numThreads = NSystem::GetNumberOfProcessors();
|
||||
_useMultiThreadMixer = true;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = _db.Files.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef _SFX
|
||||
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
|
||||
{
|
||||
*numProps = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidHeadersSize,
|
||||
kpidMethod,
|
||||
kpidSolid,
|
||||
kpidNumBlocks
|
||||
// , kpidIsTree
|
||||
};
|
||||
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
static inline char GetHex(unsigned value)
|
||||
{
|
||||
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
|
||||
static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)
|
||||
{
|
||||
int len = 0;
|
||||
do
|
||||
{
|
||||
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
|
||||
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
|
||||
}
|
||||
while (id != 0);
|
||||
return (unsigned)-len;
|
||||
}
|
||||
|
||||
static void ConvertMethodIdToString(AString &res, UInt64 id)
|
||||
{
|
||||
const unsigned kLen = 32;
|
||||
char s[kLen];
|
||||
unsigned len = kLen - 1;
|
||||
s[len] = 0;
|
||||
res += s + len - ConvertMethodIdToString_Back(s + len, id);
|
||||
}
|
||||
|
||||
static unsigned GetStringForSizeValue(char *s, UInt32 val)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i <= 31; i++)
|
||||
if (((UInt32)1 << i) == val)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
s[0] = (char)('0' + i);
|
||||
s[1] = 0;
|
||||
return 1;
|
||||
}
|
||||
if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }
|
||||
else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }
|
||||
else { s[0] = '3'; s[1] = (char)('0' + i - 30); }
|
||||
s[2] = 0;
|
||||
return 2;
|
||||
}
|
||||
char c = 'b';
|
||||
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
|
||||
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
|
||||
::ConvertUInt32ToString(val, s);
|
||||
unsigned pos = MyStringLen(s);
|
||||
s[pos++] = c;
|
||||
s[pos] = 0;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/*
|
||||
static inline void AddHexToString(UString &res, Byte value)
|
||||
{
|
||||
res += GetHex((Byte)(value >> 4));
|
||||
res += GetHex((Byte)(value & 0xF));
|
||||
}
|
||||
*/
|
||||
|
||||
static char *AddProp32(char *s, const char *name, UInt32 v)
|
||||
{
|
||||
*s++ = ':';
|
||||
s = MyStpCpy(s, name);
|
||||
::ConvertUInt32ToString(v, s);
|
||||
return s + MyStringLen(s);
|
||||
}
|
||||
|
||||
void CHandler::AddMethodName(AString &s, UInt64 id)
|
||||
{
|
||||
AString name;
|
||||
FindMethod(EXTERNAL_CODECS_VARS id, name);
|
||||
if (name.IsEmpty())
|
||||
ConvertMethodIdToString(s, id);
|
||||
else
|
||||
s += name;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
#ifndef _SFX
|
||||
COM_TRY_BEGIN
|
||||
#endif
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
#ifndef _SFX
|
||||
case kpidMethod:
|
||||
{
|
||||
AString s;
|
||||
const CParsedMethods &pm = _db.ParsedMethods;
|
||||
FOR_VECTOR (i, pm.IDs)
|
||||
{
|
||||
UInt64 id = pm.IDs[i];
|
||||
s.Add_Space_if_NotEmpty();
|
||||
char temp[16];
|
||||
if (id == k_LZMA2)
|
||||
{
|
||||
s += "LZMA2:";
|
||||
if ((pm.Lzma2Prop & 1) == 0)
|
||||
ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);
|
||||
else
|
||||
GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));
|
||||
s += temp;
|
||||
}
|
||||
else if (id == k_LZMA)
|
||||
{
|
||||
s += "LZMA:";
|
||||
GetStringForSizeValue(temp, pm.LzmaDic);
|
||||
s += temp;
|
||||
}
|
||||
else
|
||||
AddMethodName(s, id);
|
||||
}
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
case kpidSolid: prop = _db.IsSolid(); break;
|
||||
case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;
|
||||
case kpidHeadersSize: prop = _db.HeadersSize; break;
|
||||
case kpidPhySize: prop = _db.PhySize; break;
|
||||
case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;
|
||||
/*
|
||||
case kpidIsTree: if (_db.IsTree) prop = true; break;
|
||||
case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;
|
||||
case kpidIsAux: if (_db.IsTree) prop = true; break;
|
||||
*/
|
||||
// case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;
|
||||
#endif
|
||||
|
||||
case kpidWarningFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;
|
||||
if (v != 0)
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
// if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;
|
||||
if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
#ifndef _SFX
|
||||
COM_TRY_END
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
|
||||
{
|
||||
UInt64 value;
|
||||
if (v.GetItem(index, value))
|
||||
PropVarEm_Set_FileTime64(prop, value);
|
||||
}
|
||||
|
||||
bool CHandler::IsFolderEncrypted(CNum folderIndex) const
|
||||
{
|
||||
if (folderIndex == kNumNoIndex)
|
||||
return false;
|
||||
size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
||||
const Byte *p = _db.CodersData + startPos;
|
||||
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
|
||||
CInByte2 inByte;
|
||||
inByte.Init(p, size);
|
||||
|
||||
CNum numCoders = inByte.ReadNum();
|
||||
for (; numCoders != 0; numCoders--)
|
||||
{
|
||||
Byte mainByte = inByte.ReadByte();
|
||||
unsigned idSize = (mainByte & 0xF);
|
||||
const Byte *longID = inByte.GetPtr();
|
||||
UInt64 id64 = 0;
|
||||
for (unsigned j = 0; j < idSize; j++)
|
||||
id64 = ((id64 << 8) | longID[j]);
|
||||
inByte.SkipDataNoCheck(idSize);
|
||||
if (id64 == k_AES)
|
||||
return true;
|
||||
if ((mainByte & 0x20) != 0)
|
||||
inByte.SkipDataNoCheck(inByte.ReadNum());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
|
||||
{
|
||||
*numProps = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
|
||||
{
|
||||
*name = NULL;
|
||||
*propID = kpidNtSecure;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
|
||||
{
|
||||
/*
|
||||
const CFileItem &file = _db.Files[index];
|
||||
*parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
|
||||
*parent = (UInt32)(Int32)file.Parent;
|
||||
*/
|
||||
*parentType = NParentType::kDir;
|
||||
*parent = (UInt32)(Int32)-1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
|
||||
{
|
||||
*data = NULL;
|
||||
*dataSize = 0;
|
||||
*propType = 0;
|
||||
|
||||
if (/* _db.IsTree && propID == kpidName ||
|
||||
!_db.IsTree && */ propID == kpidPath)
|
||||
{
|
||||
if (_db.NameOffsets && _db.NamesBuf)
|
||||
{
|
||||
size_t offset = _db.NameOffsets[index];
|
||||
size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
|
||||
if (size < ((UInt32)1 << 31))
|
||||
{
|
||||
*data = (const void *)(_db.NamesBuf + offset * 2);
|
||||
*dataSize = (UInt32)size;
|
||||
*propType = NPropDataType::kUtf16z;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
/*
|
||||
if (propID == kpidNtSecure)
|
||||
{
|
||||
if (index < (UInt32)_db.SecureIDs.Size())
|
||||
{
|
||||
int id = _db.SecureIDs[index];
|
||||
size_t offs = _db.SecureOffsets[id];
|
||||
size_t size = _db.SecureOffsets[id + 1] - offs;
|
||||
if (size >= 0)
|
||||
{
|
||||
*data = _db.SecureBuf + offs;
|
||||
*dataSize = (UInt32)size;
|
||||
*propType = NPropDataType::kRaw;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
{
|
||||
PropVariant_Clear(prop);
|
||||
if (folderIndex == kNumNoIndex)
|
||||
return S_OK;
|
||||
// for (int ttt = 0; ttt < 1; ttt++) {
|
||||
const unsigned kTempSize = 256;
|
||||
char temp[kTempSize];
|
||||
unsigned pos = kTempSize;
|
||||
temp[--pos] = 0;
|
||||
|
||||
size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
||||
const Byte *p = _db.CodersData + startPos;
|
||||
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
|
||||
CInByte2 inByte;
|
||||
inByte.Init(p, size);
|
||||
|
||||
// numCoders == 0 ???
|
||||
CNum numCoders = inByte.ReadNum();
|
||||
bool needSpace = false;
|
||||
|
||||
for (; numCoders != 0; numCoders--, needSpace = true)
|
||||
{
|
||||
if (pos < 32) // max size of property
|
||||
break;
|
||||
Byte mainByte = inByte.ReadByte();
|
||||
unsigned idSize = (mainByte & 0xF);
|
||||
const Byte *longID = inByte.GetPtr();
|
||||
UInt64 id64 = 0;
|
||||
for (unsigned j = 0; j < idSize; j++)
|
||||
id64 = ((id64 << 8) | longID[j]);
|
||||
inByte.SkipDataNoCheck(idSize);
|
||||
|
||||
if ((mainByte & 0x10) != 0)
|
||||
{
|
||||
inByte.ReadNum(); // NumInStreams
|
||||
inByte.ReadNum(); // NumOutStreams
|
||||
}
|
||||
|
||||
CNum propsSize = 0;
|
||||
const Byte *props = NULL;
|
||||
if ((mainByte & 0x20) != 0)
|
||||
{
|
||||
propsSize = inByte.ReadNum();
|
||||
props = inByte.GetPtr();
|
||||
inByte.SkipDataNoCheck(propsSize);
|
||||
}
|
||||
|
||||
const char *name = NULL;
|
||||
char s[32];
|
||||
s[0] = 0;
|
||||
|
||||
if (id64 <= (UInt32)0xFFFFFFFF)
|
||||
{
|
||||
UInt32 id = (UInt32)id64;
|
||||
if (id == k_LZMA)
|
||||
{
|
||||
name = "LZMA";
|
||||
if (propsSize == 5)
|
||||
{
|
||||
UInt32 dicSize = GetUi32((const Byte *)props + 1);
|
||||
char *dest = s + GetStringForSizeValue(s, dicSize);
|
||||
UInt32 d = props[0];
|
||||
if (d != 0x5D)
|
||||
{
|
||||
UInt32 lc = d % 9;
|
||||
d /= 9;
|
||||
UInt32 pb = d / 5;
|
||||
UInt32 lp = d % 5;
|
||||
if (lc != 3) dest = AddProp32(dest, "lc", lc);
|
||||
if (lp != 0) dest = AddProp32(dest, "lp", lp);
|
||||
if (pb != 2) dest = AddProp32(dest, "pb", pb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (id == k_LZMA2)
|
||||
{
|
||||
name = "LZMA2";
|
||||
if (propsSize == 1)
|
||||
{
|
||||
Byte d = props[0];
|
||||
if ((d & 1) == 0)
|
||||
ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
|
||||
else
|
||||
GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
|
||||
}
|
||||
}
|
||||
else if (id == k_PPMD)
|
||||
{
|
||||
name = "PPMD";
|
||||
if (propsSize == 5)
|
||||
{
|
||||
Byte order = *props;
|
||||
char *dest = s;
|
||||
*dest++ = 'o';
|
||||
ConvertUInt32ToString(order, dest);
|
||||
dest += MyStringLen(dest);
|
||||
dest = MyStpCpy(dest, ":mem");
|
||||
GetStringForSizeValue(dest, GetUi32(props + 1));
|
||||
}
|
||||
}
|
||||
else if (id == k_Delta)
|
||||
{
|
||||
name = "Delta";
|
||||
if (propsSize == 1)
|
||||
ConvertUInt32ToString((UInt32)props[0] + 1, s);
|
||||
}
|
||||
else if (id == k_BCJ2) name = "BCJ2";
|
||||
else if (id == k_BCJ) name = "BCJ";
|
||||
else if (id == k_AES)
|
||||
{
|
||||
name = "7zAES";
|
||||
if (propsSize >= 1)
|
||||
{
|
||||
Byte firstByte = props[0];
|
||||
UInt32 numCyclesPower = firstByte & 0x3F;
|
||||
ConvertUInt32ToString(numCyclesPower, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name)
|
||||
{
|
||||
unsigned nameLen = MyStringLen(name);
|
||||
unsigned propsLen = MyStringLen(s);
|
||||
unsigned totalLen = nameLen + propsLen;
|
||||
if (propsLen != 0)
|
||||
totalLen++;
|
||||
if (needSpace)
|
||||
totalLen++;
|
||||
if (totalLen + 5 >= pos)
|
||||
break;
|
||||
pos -= totalLen;
|
||||
MyStringCopy(temp + pos, name);
|
||||
if (propsLen != 0)
|
||||
{
|
||||
char *dest = temp + pos + nameLen;
|
||||
*dest++ = ':';
|
||||
MyStringCopy(dest, s);
|
||||
}
|
||||
if (needSpace)
|
||||
temp[pos + totalLen - 1] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
AString methodName;
|
||||
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
|
||||
if (needSpace)
|
||||
temp[--pos] = ' ';
|
||||
if (methodName.IsEmpty())
|
||||
pos -= ConvertMethodIdToString_Back(temp + pos, id64);
|
||||
else
|
||||
{
|
||||
unsigned len = methodName.Len();
|
||||
if (len + 5 > pos)
|
||||
break;
|
||||
pos -= len;
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
temp[pos + i] = methodName[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numCoders != 0 && pos >= 4)
|
||||
{
|
||||
temp[--pos] = ' ';
|
||||
temp[--pos] = '.';
|
||||
temp[--pos] = '.';
|
||||
temp[--pos] = '.';
|
||||
}
|
||||
|
||||
return PropVarEm_Set_Str(prop, temp + pos);
|
||||
// }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
PropVariant_Clear(value);
|
||||
// COM_TRY_BEGIN
|
||||
// NCOM::CPropVariant prop;
|
||||
|
||||
/*
|
||||
const CRef2 &ref2 = _refs[index];
|
||||
if (ref2.Refs.IsEmpty())
|
||||
return E_FAIL;
|
||||
const CRef &ref = ref2.Refs.Front();
|
||||
*/
|
||||
|
||||
const CFileItem &item = _db.Files[index];
|
||||
UInt32 index2 = index;
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
|
||||
case kpidSize:
|
||||
{
|
||||
PropVarEm_Set_UInt64(value, item.Size);
|
||||
// prop = ref2.Size;
|
||||
break;
|
||||
}
|
||||
case kpidPackSize:
|
||||
{
|
||||
// prop = ref2.PackSize;
|
||||
{
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
{
|
||||
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
|
||||
PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
|
||||
/*
|
||||
else
|
||||
PropVarEm_Set_UInt64(value, 0);
|
||||
*/
|
||||
}
|
||||
else
|
||||
PropVarEm_Set_UInt64(value, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// case kpidIsAux: prop = _db.IsItemAux(index2); break;
|
||||
case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
|
||||
case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
|
||||
case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
|
||||
case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
|
||||
case kpidAttrib: if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break;
|
||||
case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
|
||||
case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
|
||||
case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
|
||||
/*
|
||||
case kpidIsAltStream: prop = item.IsAltStream; break;
|
||||
case kpidNtSecure:
|
||||
{
|
||||
int id = _db.SecureIDs[index];
|
||||
size_t offs = _db.SecureOffsets[id];
|
||||
size_t size = _db.SecureOffsets[id + 1] - offs;
|
||||
if (size >= 0)
|
||||
{
|
||||
prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case kpidPath: return _db.GetPath_Prop(index, value);
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
|
||||
case kpidBlock:
|
||||
{
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case kpidPackedSize0:
|
||||
case kpidPackedSize1:
|
||||
case kpidPackedSize2:
|
||||
case kpidPackedSize3:
|
||||
case kpidPackedSize4:
|
||||
{
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
{
|
||||
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
|
||||
_db.FoStartPackStreamIndex[folderIndex + 1] -
|
||||
_db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
|
||||
{
|
||||
PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
|
||||
}
|
||||
}
|
||||
else
|
||||
PropVarEm_Set_UInt64(value, 0);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
#endif
|
||||
}
|
||||
// prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
#ifndef _SFX
|
||||
_fileInfoPopIDs.Clear();
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (openArchiveCallback)
|
||||
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
#endif
|
||||
|
||||
CInArchive archive(
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
_useMultiThreadMixer
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
_db.IsArc = false;
|
||||
RINOK(archive.Open(stream, maxCheckStartPosition));
|
||||
_db.IsArc = true;
|
||||
|
||||
HRESULT result = archive.ReadDatabase(
|
||||
EXTERNAL_CODECS_VARS
|
||||
_db
|
||||
#ifndef _NO_CRYPTO
|
||||
, getTextPassword, _isEncrypted, _passwordIsDefined, _password
|
||||
#endif
|
||||
);
|
||||
RINOK(result);
|
||||
|
||||
_inStream = stream;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Close();
|
||||
// return E_INVALIDARG;
|
||||
// return S_FALSE;
|
||||
// we must return out_of_memory here
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
// _inStream = stream;
|
||||
#ifndef _SFX
|
||||
FillPopIDs();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
_inStream.Release();
|
||||
_db.Clear();
|
||||
#ifndef _NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
_password.Empty();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
|
||||
_numThreads = numProcessors;
|
||||
_useMultiThreadMixer = true;
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
const PROPVARIANT &value = values[i];
|
||||
UInt32 number;
|
||||
unsigned index = ParseStringToUInt32(name, number);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsEqualTo("mtf"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
|
||||
continue;
|
||||
}
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
IMPL_ISetCompressCodecsInfo
|
||||
|
||||
}}
|
||||
173
CPP/7zip/Archive/7z/7zHandler.h
Normal file
173
CPP/7zip/Archive/7z/7zHandler.h
Normal file
@@ -0,0 +1,173 @@
|
||||
// 7z/Handler.h
|
||||
|
||||
#ifndef __7Z_HANDLER_H
|
||||
#define __7Z_HANDLER_H
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
#include "../Common/HandlerOut.h"
|
||||
#endif
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
#ifndef __7Z_SET_PROPERTIES
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
#define __7Z_SET_PROPERTIES
|
||||
#endif
|
||||
#else
|
||||
#define __7Z_SET_PROPERTIES
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
class COutHandler: public CMultiMethodProps
|
||||
{
|
||||
HRESULT SetSolidFromString(const UString &s);
|
||||
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
|
||||
public:
|
||||
bool _removeSfxBlock;
|
||||
|
||||
UInt64 _numSolidFiles;
|
||||
UInt64 _numSolidBytes;
|
||||
bool _numSolidBytesDefined;
|
||||
bool _solidExtension;
|
||||
bool _useTypeSorting;
|
||||
|
||||
bool _compressHeaders;
|
||||
bool _encryptHeadersSpecified;
|
||||
bool _encryptHeaders;
|
||||
// bool _useParents; 9.26
|
||||
|
||||
CBoolPair Write_CTime;
|
||||
CBoolPair Write_ATime;
|
||||
CBoolPair Write_MTime;
|
||||
|
||||
bool _useMultiThreadMixer;
|
||||
|
||||
// bool _volumeMode;
|
||||
|
||||
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
|
||||
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
|
||||
void InitSolid()
|
||||
{
|
||||
InitSolidFiles();
|
||||
InitSolidSize();
|
||||
_solidExtension = false;
|
||||
_numSolidBytesDefined = false;
|
||||
}
|
||||
|
||||
void InitProps();
|
||||
|
||||
COutHandler() { InitProps(); }
|
||||
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveGetRawProps,
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
public ISetProperties,
|
||||
#endif
|
||||
#ifndef EXTRACT_ONLY
|
||||
public IOutArchive,
|
||||
#endif
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
#ifndef EXTRACT_ONLY
|
||||
, public COutHandler
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
#endif
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY(IOutArchive)
|
||||
#endif
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IArchiveGetRawProps(;)
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
INTERFACE_IOutArchive(;)
|
||||
#endif
|
||||
|
||||
DECL_ISetCompressCodecsInfo
|
||||
|
||||
CHandler();
|
||||
|
||||
private:
|
||||
CMyComPtr<IInStream> _inStream;
|
||||
NArchive::N7z::CDbEx _db;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
bool _isEncrypted;
|
||||
bool _passwordIsDefined;
|
||||
UString _password;
|
||||
#endif
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
UInt32 _numThreads;
|
||||
bool _useMultiThreadMixer;
|
||||
#endif
|
||||
|
||||
UInt32 _crcSize;
|
||||
|
||||
#else
|
||||
|
||||
CRecordVector<CBond2> _bonds;
|
||||
|
||||
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
|
||||
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
|
||||
HRESULT SetMainMethod(CCompressionMethodMode &method
|
||||
#ifndef _7ZIP_ST
|
||||
, UInt32 numThreads
|
||||
#endif
|
||||
);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
bool IsFolderEncrypted(CNum folderIndex) const;
|
||||
#ifndef _SFX
|
||||
|
||||
CRecordVector<UInt64> _fileInfoPopIDs;
|
||||
void FillPopIDs();
|
||||
void AddMethodName(AString &s, UInt64 id);
|
||||
HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;
|
||||
|
||||
#endif
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
914
CPP/7zip/Archive/7z/7zHandlerOut.cpp
Normal file
914
CPP/7zip/Archive/7z/7zHandlerOut.cpp
Normal file
@@ -0,0 +1,914 @@
|
||||
// 7zHandlerOut.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/ParseProperties.h"
|
||||
|
||||
#include "7zHandler.h"
|
||||
#include "7zOut.h"
|
||||
#include "7zUpdate.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static const char *k_LZMA_Name = "LZMA";
|
||||
static const char *kDefaultMethodName = "LZMA2";
|
||||
static const char *k_Copy_Name = "Copy";
|
||||
|
||||
static const char *k_MatchFinder_ForHeaders = "BT2";
|
||||
static const UInt32 k_NumFastBytes_ForHeaders = 273;
|
||||
static const UInt32 k_Level_ForHeaders = 5;
|
||||
static const UInt32 k_Dictionary_ForHeaders =
|
||||
#ifdef UNDER_CE
|
||||
1 << 18;
|
||||
#else
|
||||
1 << 20;
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||
{
|
||||
*type = NFileTimeType::kWindows;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
|
||||
{
|
||||
if (!FindMethod(
|
||||
EXTERNAL_CODECS_VARS
|
||||
m.MethodName, dest.Id, dest.NumStreams))
|
||||
return E_INVALIDARG;
|
||||
(CProps &)dest = (CProps &)m;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
|
||||
{
|
||||
if (!_compressHeaders)
|
||||
return S_OK;
|
||||
COneMethodInfo m;
|
||||
m.MethodName = k_LZMA_Name;
|
||||
m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
|
||||
m.AddProp_Level(k_Level_ForHeaders);
|
||||
m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
|
||||
m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
|
||||
m.AddProp_NumThreads(1);
|
||||
|
||||
CMethodFull &methodFull = headerMethod.Methods.AddNew();
|
||||
return PropsMethod_To_FullMethod(methodFull, m);
|
||||
}
|
||||
|
||||
HRESULT CHandler::SetMainMethod(
|
||||
CCompressionMethodMode &methodMode
|
||||
#ifndef _7ZIP_ST
|
||||
, UInt32 numThreads
|
||||
#endif
|
||||
)
|
||||
{
|
||||
methodMode.Bonds = _bonds;
|
||||
|
||||
CObjectVector<COneMethodInfo> methods = _methods;
|
||||
|
||||
{
|
||||
FOR_VECTOR (i, methods)
|
||||
{
|
||||
AString &methodName = methods[i].MethodName;
|
||||
if (methodName.IsEmpty())
|
||||
methodName = kDefaultMethodName;
|
||||
}
|
||||
if (methods.IsEmpty())
|
||||
{
|
||||
COneMethodInfo &m = methods.AddNew();
|
||||
m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
|
||||
methodMode.DefaultMethod_was_Inserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_filterMethod.MethodName.IsEmpty())
|
||||
{
|
||||
// if (methodMode.Bonds.IsEmpty())
|
||||
{
|
||||
FOR_VECTOR (k, methodMode.Bonds)
|
||||
{
|
||||
CBond2 &bond = methodMode.Bonds[k];
|
||||
bond.InCoder++;
|
||||
bond.OutCoder++;
|
||||
}
|
||||
methods.Insert(0, _filterMethod);
|
||||
methodMode.Filter_was_Inserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
const UInt64 kSolidBytes_Min = (1 << 24);
|
||||
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
|
||||
|
||||
bool needSolid = false;
|
||||
|
||||
FOR_VECTOR (i, methods)
|
||||
{
|
||||
COneMethodInfo &oneMethodInfo = methods[i];
|
||||
SetGlobalLevelAndThreads(oneMethodInfo
|
||||
#ifndef _7ZIP_ST
|
||||
, numThreads
|
||||
#endif
|
||||
);
|
||||
|
||||
CMethodFull &methodFull = methodMode.Methods.AddNew();
|
||||
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
|
||||
|
||||
if (methodFull.Id != k_Copy)
|
||||
needSolid = true;
|
||||
|
||||
if (_numSolidBytesDefined)
|
||||
continue;
|
||||
|
||||
UInt32 dicSize;
|
||||
switch (methodFull.Id)
|
||||
{
|
||||
case k_LZMA:
|
||||
case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;
|
||||
case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;
|
||||
case k_Deflate: dicSize = (UInt32)1 << 15; break;
|
||||
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
_numSolidBytes = (UInt64)dicSize << 7;
|
||||
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
|
||||
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
|
||||
_numSolidBytesDefined = true;
|
||||
}
|
||||
|
||||
if (!_numSolidBytesDefined)
|
||||
if (needSolid)
|
||||
_numSolidBytes = kSolidBytes_Max;
|
||||
else
|
||||
_numSolidBytes = 0;
|
||||
_numSolidBytesDefined = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined)
|
||||
{
|
||||
// ft = 0;
|
||||
// ftDefined = false;
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(index, propID, &prop));
|
||||
if (prop.vt == VT_FILETIME)
|
||||
{
|
||||
ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32);
|
||||
ftDefined = true;
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
ft = 0;
|
||||
ftDefined = false;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
#ifdef _WIN32
|
||||
static const wchar_t kDirDelimiter1 = L'\\';
|
||||
#endif
|
||||
static const wchar_t kDirDelimiter2 = L'/';
|
||||
|
||||
static inline bool IsCharDirLimiter(wchar_t c)
|
||||
{
|
||||
return (
|
||||
#ifdef _WIN32
|
||||
c == kDirDelimiter1 ||
|
||||
#endif
|
||||
c == kDirDelimiter2);
|
||||
}
|
||||
|
||||
static int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex)
|
||||
{
|
||||
CTreeFolder &tf = treeFolders[cur];
|
||||
tf.SortIndex = curSortIndex++;
|
||||
for (int i = 0; i < tf.SubFolders.Size(); i++)
|
||||
curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);
|
||||
tf.SortIndexEnd = curSortIndex;
|
||||
return curSortIndex;
|
||||
}
|
||||
|
||||
static int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)
|
||||
{
|
||||
const CIntVector &subFolders = treeFolders[cur].SubFolders;
|
||||
int left = 0, right = subFolders.Size();
|
||||
insertPos = -1;
|
||||
for (;;)
|
||||
{
|
||||
if (left == right)
|
||||
{
|
||||
insertPos = left;
|
||||
return -1;
|
||||
}
|
||||
int mid = (left + right) / 2;
|
||||
int midFolder = subFolders[mid];
|
||||
int compare = CompareFileNames(name, treeFolders[midFolder].Name);
|
||||
if (compare == 0)
|
||||
return midFolder;
|
||||
if (compare < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)
|
||||
{
|
||||
int insertPos;
|
||||
int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);
|
||||
if (folderIndex < 0)
|
||||
{
|
||||
folderIndex = treeFolders.Size();
|
||||
CTreeFolder &newFolder = treeFolders.AddNew();
|
||||
newFolder.Parent = cur;
|
||||
newFolder.Name = name;
|
||||
treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);
|
||||
}
|
||||
// else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;
|
||||
return folderIndex;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
const CDbEx *db = 0;
|
||||
#ifdef _7Z_VOL
|
||||
if (_volumes.Size() > 1)
|
||||
return E_FAIL;
|
||||
const CVolume *volume = 0;
|
||||
if (_volumes.Size() == 1)
|
||||
{
|
||||
volume = &_volumes.Front();
|
||||
db = &volume->Database;
|
||||
}
|
||||
#else
|
||||
if (_inStream != 0)
|
||||
db = &_db;
|
||||
#endif
|
||||
|
||||
/*
|
||||
CMyComPtr<IArchiveGetRawProps> getRawProps;
|
||||
updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);
|
||||
|
||||
CUniqBlocks secureBlocks;
|
||||
secureBlocks.AddUniq(NULL, 0);
|
||||
|
||||
CObjectVector<CTreeFolder> treeFolders;
|
||||
{
|
||||
CTreeFolder folder;
|
||||
folder.Parent = -1;
|
||||
treeFolders.Add(folder);
|
||||
}
|
||||
*/
|
||||
|
||||
CObjectVector<CUpdateItem> updateItems;
|
||||
|
||||
bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
|
||||
bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
|
||||
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
|
||||
|
||||
if (db && !db->Files.IsEmpty())
|
||||
{
|
||||
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
|
||||
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
|
||||
if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();
|
||||
}
|
||||
|
||||
UString s;
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
Int32 newData, newProps;
|
||||
UInt32 indexInArchive;
|
||||
if (!updateCallback)
|
||||
return E_FAIL;
|
||||
RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
|
||||
CUpdateItem ui;
|
||||
ui.NewProps = IntToBool(newProps);
|
||||
ui.NewData = IntToBool(newData);
|
||||
ui.IndexInArchive = indexInArchive;
|
||||
ui.IndexInClient = i;
|
||||
ui.IsAnti = false;
|
||||
ui.Size = 0;
|
||||
|
||||
UString name;
|
||||
// bool isAltStream = false;
|
||||
if (ui.IndexInArchive != -1)
|
||||
{
|
||||
if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size())
|
||||
return E_INVALIDARG;
|
||||
const CFileItem &fi = db->Files[ui.IndexInArchive];
|
||||
if (!ui.NewProps)
|
||||
{
|
||||
_db.GetPath(ui.IndexInArchive, name);
|
||||
}
|
||||
ui.IsDir = fi.IsDir;
|
||||
ui.Size = fi.Size;
|
||||
// isAltStream = fi.IsAltStream;
|
||||
ui.IsAnti = db->IsItemAnti(ui.IndexInArchive);
|
||||
|
||||
if (!ui.NewProps)
|
||||
{
|
||||
ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);
|
||||
ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);
|
||||
ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (ui.NewProps)
|
||||
{
|
||||
bool folderStatusIsDefined;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
ui.AttribDefined = false;
|
||||
else if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
ui.Attrib = prop.ulVal;
|
||||
ui.AttribDefined = true;
|
||||
}
|
||||
}
|
||||
|
||||
// we need MTime to sort files.
|
||||
if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined));
|
||||
if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined));
|
||||
if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined));
|
||||
|
||||
/*
|
||||
if (getRawProps)
|
||||
{
|
||||
const void *data;
|
||||
UInt32 dataSize;
|
||||
UInt32 propType;
|
||||
|
||||
getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);
|
||||
if (dataSize != 0 && propType != NPropDataType::kRaw)
|
||||
return E_FAIL;
|
||||
ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize);
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidPath, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
{
|
||||
}
|
||||
else if (prop.vt != VT_BSTR)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
name = NItemName::MakeLegalName(prop.bstrVal);
|
||||
}
|
||||
}
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
folderStatusIsDefined = false;
|
||||
else if (prop.vt != VT_BOOL)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
|
||||
folderStatusIsDefined = true;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
ui.IsAnti = false;
|
||||
else if (prop.vt != VT_BOOL)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
ui.IsAnti = (prop.boolVal != VARIANT_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
isAltStream = false;
|
||||
else if (prop.vt != VT_BOOL)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
isAltStream = (prop.boolVal != VARIANT_FALSE);
|
||||
}
|
||||
*/
|
||||
|
||||
if (ui.IsAnti)
|
||||
{
|
||||
ui.AttribDefined = false;
|
||||
|
||||
ui.CTimeDefined = false;
|
||||
ui.ATimeDefined = false;
|
||||
ui.MTimeDefined = false;
|
||||
|
||||
ui.Size = 0;
|
||||
}
|
||||
|
||||
if (!folderStatusIsDefined && ui.AttribDefined)
|
||||
ui.SetDirStatusFromAttrib();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (_db.SecureIDs.IsEmpty())
|
||||
ui.SecureIndex = secureBlocks.AddUniq(NULL, 0);
|
||||
else
|
||||
{
|
||||
int id = _db.SecureIDs[ui.IndexInArchive];
|
||||
size_t offs = _db.SecureOffsets[id];
|
||||
size_t size = _db.SecureOffsets[id + 1] - offs;
|
||||
ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
int folderIndex = 0;
|
||||
if (_useParents)
|
||||
{
|
||||
int j;
|
||||
s.Empty();
|
||||
for (j = 0; j < name.Len(); j++)
|
||||
{
|
||||
wchar_t c = name[j];
|
||||
if (IsCharDirLimiter(c))
|
||||
{
|
||||
folderIndex = AddFolder(treeFolders, folderIndex, s);
|
||||
s.Empty();
|
||||
continue;
|
||||
}
|
||||
s += c;
|
||||
}
|
||||
if (isAltStream)
|
||||
{
|
||||
int colonPos = s.Find(':');
|
||||
if (colonPos < 0)
|
||||
{
|
||||
// isAltStream = false;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
UString mainName = s.Left(colonPos);
|
||||
int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName);
|
||||
if (treeFolders[newFolderIndex].UpdateItemIndex < 0)
|
||||
{
|
||||
for (int j = updateItems.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
CUpdateItem &ui2 = updateItems[j];
|
||||
if (ui2.ParentFolderIndex == folderIndex
|
||||
&& ui2.Name == mainName)
|
||||
{
|
||||
ui2.TreeFolderIndex = newFolderIndex;
|
||||
treeFolders[newFolderIndex].UpdateItemIndex = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
folderIndex = newFolderIndex;
|
||||
s.Delete(0, colonPos + 1);
|
||||
}
|
||||
ui.Name = s;
|
||||
}
|
||||
else
|
||||
ui.Name = name;
|
||||
ui.IsAltStream = isAltStream;
|
||||
ui.ParentFolderIndex = folderIndex;
|
||||
ui.TreeFolderIndex = -1;
|
||||
if (ui.IsDir && !s.IsEmpty())
|
||||
{
|
||||
ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s);
|
||||
treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size();
|
||||
}
|
||||
}
|
||||
*/
|
||||
ui.Name = name;
|
||||
|
||||
if (ui.NewData)
|
||||
{
|
||||
ui.Size = 0;
|
||||
if (!ui.IsDir)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
ui.Size = (UInt64)prop.uhVal.QuadPart;
|
||||
if (ui.Size != 0 && ui.IsAnti)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
updateItems.Add(ui);
|
||||
}
|
||||
|
||||
/*
|
||||
FillSortIndex(treeFolders, 0, 0);
|
||||
for (i = 0; i < (UInt32)updateItems.Size(); i++)
|
||||
{
|
||||
CUpdateItem &ui = updateItems[i];
|
||||
ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex;
|
||||
ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd;
|
||||
}
|
||||
*/
|
||||
|
||||
CCompressionMethodMode methodMode, headerMethod;
|
||||
|
||||
HRESULT res = SetMainMethod(methodMode
|
||||
#ifndef _7ZIP_ST
|
||||
, _numThreads
|
||||
#endif
|
||||
);
|
||||
RINOK(res);
|
||||
|
||||
RINOK(SetHeaderMethod(headerMethod));
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
methodMode.NumThreads = _numThreads;
|
||||
methodMode.MultiThreadMixer = _useMultiThreadMixer;
|
||||
headerMethod.NumThreads = 1;
|
||||
headerMethod.MultiThreadMixer = _useMultiThreadMixer;
|
||||
#endif
|
||||
|
||||
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
|
||||
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
|
||||
|
||||
methodMode.PasswordIsDefined = false;
|
||||
methodMode.Password.Empty();
|
||||
if (getPassword2)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
if (methodMode.PasswordIsDefined && password)
|
||||
methodMode.Password = password;
|
||||
}
|
||||
|
||||
bool compressMainHeader = _compressHeaders; // check it
|
||||
|
||||
bool encryptHeaders = false;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
if (!methodMode.PasswordIsDefined && _passwordIsDefined)
|
||||
{
|
||||
// if header is compressed, we use that password for updated archive
|
||||
methodMode.PasswordIsDefined = true;
|
||||
methodMode.Password = _password;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (methodMode.PasswordIsDefined)
|
||||
{
|
||||
if (_encryptHeadersSpecified)
|
||||
encryptHeaders = _encryptHeaders;
|
||||
#ifndef _NO_CRYPTO
|
||||
else
|
||||
encryptHeaders = _passwordIsDefined;
|
||||
#endif
|
||||
compressMainHeader = true;
|
||||
if (encryptHeaders)
|
||||
{
|
||||
headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;
|
||||
headerMethod.Password = methodMode.Password;
|
||||
}
|
||||
}
|
||||
|
||||
if (numItems < 2)
|
||||
compressMainHeader = false;
|
||||
|
||||
int level = GetLevel();
|
||||
|
||||
CUpdateOptions options;
|
||||
options.Method = &methodMode;
|
||||
options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;
|
||||
options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);
|
||||
// use BCJ for all levels, BCJ2 uses LZMA2! /TR 2016-03-03
|
||||
// options.MaxFilter = (level >= 8);
|
||||
options.AnalysisLevel = GetAnalysisLevel();
|
||||
|
||||
options.HeaderOptions.CompressMainHeader = compressMainHeader;
|
||||
/*
|
||||
options.HeaderOptions.WriteCTime = Write_CTime;
|
||||
options.HeaderOptions.WriteATime = Write_ATime;
|
||||
options.HeaderOptions.WriteMTime = Write_MTime;
|
||||
*/
|
||||
|
||||
options.NumSolidFiles = _numSolidFiles;
|
||||
options.NumSolidBytes = _numSolidBytes;
|
||||
options.SolidExtension = _solidExtension;
|
||||
options.UseTypeSorting = _useTypeSorting;
|
||||
|
||||
options.RemoveSfxBlock = _removeSfxBlock;
|
||||
// options.VolumeMode = _volumeMode;
|
||||
|
||||
options.MultiThreadMixer = _useMultiThreadMixer;
|
||||
|
||||
COutArchive archive;
|
||||
CArchiveDatabaseOut newDatabase;
|
||||
|
||||
CMyComPtr<ICryptoGetTextPassword> getPassword;
|
||||
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
|
||||
|
||||
/*
|
||||
if (secureBlocks.Sorted.Size() > 1)
|
||||
{
|
||||
secureBlocks.GetReverseMap();
|
||||
for (int i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
int &secureIndex = updateItems[i].SecureIndex;
|
||||
secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
res = Update(
|
||||
EXTERNAL_CODECS_VARS
|
||||
#ifdef _7Z_VOL
|
||||
volume ? volume->Stream: 0,
|
||||
volume ? db : 0,
|
||||
#else
|
||||
_inStream,
|
||||
db,
|
||||
#endif
|
||||
updateItems,
|
||||
// treeFolders,
|
||||
// secureBlocks,
|
||||
archive, newDatabase, outStream, updateCallback, options
|
||||
#ifndef _NO_CRYPTO
|
||||
, getPassword
|
||||
#endif
|
||||
);
|
||||
|
||||
RINOK(res);
|
||||
|
||||
updateItems.ClearAndFree();
|
||||
|
||||
return archive.WriteDatabase(EXTERNAL_CODECS_VARS
|
||||
newDatabase, options.HeaderMethod, options.HeaderOptions);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
|
||||
{
|
||||
stream = 0;
|
||||
{
|
||||
unsigned index = ParseStringToUInt32(srcString, coder);
|
||||
if (index == 0)
|
||||
return E_INVALIDARG;
|
||||
srcString.DeleteFrontal(index);
|
||||
}
|
||||
if (srcString[0] == 's')
|
||||
{
|
||||
srcString.Delete(0);
|
||||
unsigned index = ParseStringToUInt32(srcString, stream);
|
||||
if (index == 0)
|
||||
return E_INVALIDARG;
|
||||
srcString.DeleteFrontal(index);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutHandler::InitProps()
|
||||
{
|
||||
CMultiMethodProps::Init();
|
||||
|
||||
_removeSfxBlock = false;
|
||||
_compressHeaders = true;
|
||||
_encryptHeadersSpecified = false;
|
||||
_encryptHeaders = false;
|
||||
// _useParents = false;
|
||||
|
||||
Write_CTime.Init();
|
||||
Write_ATime.Init();
|
||||
Write_MTime.Init();
|
||||
|
||||
_useMultiThreadMixer = true;
|
||||
|
||||
// _volumeMode = false;
|
||||
|
||||
InitSolid();
|
||||
_useTypeSorting = false;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetSolidFromString(const UString &s)
|
||||
{
|
||||
UString s2 = s;
|
||||
s2.MakeLower_Ascii();
|
||||
for (unsigned i = 0; i < s2.Len();)
|
||||
{
|
||||
const wchar_t *start = ((const wchar_t *)s2) + i;
|
||||
const wchar_t *end;
|
||||
UInt64 v = ConvertStringToUInt64(start, &end);
|
||||
if (start == end)
|
||||
{
|
||||
if (s2[i++] != 'e')
|
||||
return E_INVALIDARG;
|
||||
_solidExtension = true;
|
||||
continue;
|
||||
}
|
||||
i += (int)(end - start);
|
||||
if (i == s2.Len())
|
||||
return E_INVALIDARG;
|
||||
wchar_t c = s2[i++];
|
||||
if (c == 'f')
|
||||
{
|
||||
if (v < 1)
|
||||
v = 1;
|
||||
_numSolidFiles = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned numBits;
|
||||
switch (c)
|
||||
{
|
||||
case 'b': numBits = 0; break;
|
||||
case 'k': numBits = 10; break;
|
||||
case 'm': numBits = 20; break;
|
||||
case 'g': numBits = 30; break;
|
||||
case 't': numBits = 40; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
_numSolidBytes = (v << numBits);
|
||||
_numSolidBytesDefined = true;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
|
||||
{
|
||||
bool isSolid;
|
||||
switch (value.vt)
|
||||
{
|
||||
case VT_EMPTY: isSolid = true; break;
|
||||
case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
|
||||
case VT_BSTR:
|
||||
if (StringToBool(value.bstrVal, isSolid))
|
||||
break;
|
||||
return SetSolidFromString(value.bstrVal);
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
if (isSolid)
|
||||
InitSolid();
|
||||
else
|
||||
_numSolidFiles = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, dest.Val));
|
||||
dest.Def = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
{
|
||||
UString name = nameSpec;
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (name[0] == L's')
|
||||
{
|
||||
name.Delete(0);
|
||||
if (name.IsEmpty())
|
||||
return SetSolidFromPROPVARIANT(value);
|
||||
if (value.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
return SetSolidFromString(name);
|
||||
}
|
||||
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
// UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
|
||||
if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders);
|
||||
// if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents);
|
||||
|
||||
if (name.IsEqualTo("hcf"))
|
||||
{
|
||||
bool compressHeadersFull = true;
|
||||
RINOK(PROPVARIANT_to_bool(value, compressHeadersFull));
|
||||
return compressHeadersFull ? S_OK: E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (name.IsEqualTo("he"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(value, _encryptHeaders));
|
||||
_encryptHeadersSpecified = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime);
|
||||
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
|
||||
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
|
||||
|
||||
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
|
||||
|
||||
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
|
||||
|
||||
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
|
||||
}
|
||||
return CMultiMethodProps::SetProperty(name, value);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
_bonds.Clear();
|
||||
InitProps();
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
const PROPVARIANT &value = values[i];
|
||||
|
||||
if (name[0] == 'b')
|
||||
{
|
||||
if (value.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
name.Delete(0);
|
||||
|
||||
CBond2 bond;
|
||||
RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
|
||||
if (name[0] != ':')
|
||||
return E_INVALIDARG;
|
||||
name.Delete(0);
|
||||
UInt32 inStream = 0;
|
||||
RINOK(ParseBond(name, bond.InCoder, inStream));
|
||||
if (inStream != 0)
|
||||
return E_INVALIDARG;
|
||||
if (!name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
_bonds.Add(bond);
|
||||
continue;
|
||||
}
|
||||
|
||||
RINOK(SetProperty(name, value));
|
||||
}
|
||||
|
||||
unsigned numEmptyMethods = GetNumEmptyMethods();
|
||||
if (numEmptyMethods > 0)
|
||||
{
|
||||
unsigned k;
|
||||
for (k = 0; k < _bonds.Size(); k++)
|
||||
{
|
||||
const CBond2 &bond = _bonds[k];
|
||||
if (bond.InCoder < (UInt32)numEmptyMethods ||
|
||||
bond.OutCoder < (UInt32)numEmptyMethods)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
for (k = 0; k < _bonds.Size(); k++)
|
||||
{
|
||||
CBond2 &bond = _bonds[k];
|
||||
bond.InCoder -= (UInt32)numEmptyMethods;
|
||||
bond.OutCoder -= (UInt32)numEmptyMethods;
|
||||
}
|
||||
_methods.DeleteFrontal(numEmptyMethods);
|
||||
}
|
||||
|
||||
FOR_VECTOR (k, _bonds)
|
||||
{
|
||||
const CBond2 &bond = _bonds[k];
|
||||
if (bond.InCoder >= (UInt32)_methods.Size() ||
|
||||
bond.OutCoder >= (UInt32)_methods.Size())
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
19
CPP/7zip/Archive/7z/7zHeader.cpp
Normal file
19
CPP/7zip/Archive/7z/7zHeader.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// 7zHeader.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "7zHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
#ifdef _7Z_VOL
|
||||
Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
|
||||
#endif
|
||||
|
||||
// We can change signature. So file doesn't contain correct signature.
|
||||
// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } };
|
||||
// static SignatureInitializer g_SignatureInitializer;
|
||||
|
||||
}}
|
||||
150
CPP/7zip/Archive/7z/7zHeader.h
Normal file
150
CPP/7zip/Archive/7z/7zHeader.h
Normal file
@@ -0,0 +1,150 @@
|
||||
// 7z/7zHeader.h
|
||||
|
||||
#ifndef __7Z_HEADER_H
|
||||
#define __7Z_HEADER_H
|
||||
|
||||
#include "../../../Common/MyTypes.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
const unsigned kSignatureSize = 6;
|
||||
extern Byte kSignature[kSignatureSize];
|
||||
|
||||
// #define _7Z_VOL
|
||||
// 7z-MultiVolume is not finished yet.
|
||||
// It can work already, but I still do not like some
|
||||
// things of that new multivolume format.
|
||||
// So please keep it commented.
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
extern Byte kFinishSignature[kSignatureSize];
|
||||
#endif
|
||||
|
||||
struct CArchiveVersion
|
||||
{
|
||||
Byte Major;
|
||||
Byte Minor;
|
||||
};
|
||||
|
||||
const Byte kMajorVersion = 0;
|
||||
|
||||
struct CStartHeader
|
||||
{
|
||||
UInt64 NextHeaderOffset;
|
||||
UInt64 NextHeaderSize;
|
||||
UInt32 NextHeaderCRC;
|
||||
};
|
||||
|
||||
const UInt32 kStartHeaderSize = 20;
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
struct CFinishHeader: public CStartHeader
|
||||
{
|
||||
UInt64 ArchiveStartOffset; // data offset from end if that struct
|
||||
UInt64 AdditionalStartBlockSize; // start signature & start header size
|
||||
};
|
||||
|
||||
const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;
|
||||
#endif
|
||||
|
||||
namespace NID
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kEnd,
|
||||
|
||||
kHeader,
|
||||
|
||||
kArchiveProperties,
|
||||
|
||||
kAdditionalStreamsInfo,
|
||||
kMainStreamsInfo,
|
||||
kFilesInfo,
|
||||
|
||||
kPackInfo,
|
||||
kUnpackInfo,
|
||||
kSubStreamsInfo,
|
||||
|
||||
kSize,
|
||||
kCRC,
|
||||
|
||||
kFolder,
|
||||
|
||||
kCodersUnpackSize,
|
||||
kNumUnpackStream,
|
||||
|
||||
kEmptyStream,
|
||||
kEmptyFile,
|
||||
kAnti,
|
||||
|
||||
kName,
|
||||
kCTime,
|
||||
kATime,
|
||||
kMTime,
|
||||
kWinAttrib,
|
||||
kComment,
|
||||
|
||||
kEncodedHeader,
|
||||
|
||||
kStartPos,
|
||||
kDummy
|
||||
|
||||
// kNtSecure,
|
||||
// kParent,
|
||||
// kIsAux
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const UInt32 k_Copy = 0;
|
||||
const UInt32 k_Delta = 3;
|
||||
|
||||
const UInt32 k_LZMA2 = 0x21;
|
||||
|
||||
const UInt32 k_SWAP2 = 0x20302;
|
||||
const UInt32 k_SWAP4 = 0x20304;
|
||||
|
||||
const UInt32 k_LZMA = 0x30101;
|
||||
const UInt32 k_PPMD = 0x30401;
|
||||
|
||||
const UInt32 k_Deflate = 0x40108;
|
||||
const UInt32 k_BZip2 = 0x40202;
|
||||
|
||||
const UInt32 k_BCJ = 0x3030103;
|
||||
const UInt32 k_BCJ2 = 0x303011B;
|
||||
const UInt32 k_PPC = 0x3030205;
|
||||
const UInt32 k_IA64 = 0x3030401;
|
||||
const UInt32 k_ARM = 0x3030501;
|
||||
const UInt32 k_ARMT = 0x3030701;
|
||||
const UInt32 k_SPARC = 0x3030805;
|
||||
|
||||
const UInt32 k_ZStd = 0x4F71101;
|
||||
|
||||
const UInt32 k_AES = 0x6F10701;
|
||||
|
||||
|
||||
static inline bool IsFilterMethod(UInt64 m)
|
||||
{
|
||||
if (m > (UInt64)0xFFFFFFFF)
|
||||
return false;
|
||||
switch ((UInt32)m)
|
||||
{
|
||||
case k_Delta:
|
||||
case k_BCJ:
|
||||
case k_BCJ2:
|
||||
case k_PPC:
|
||||
case k_IA64:
|
||||
case k_ARM:
|
||||
case k_ARMT:
|
||||
case k_SPARC:
|
||||
case k_SWAP2:
|
||||
case k_SWAP4:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
1640
CPP/7zip/Archive/7z/7zIn.cpp
Normal file
1640
CPP/7zip/Archive/7z/7zIn.cpp
Normal file
File diff suppressed because it is too large
Load Diff
431
CPP/7zip/Archive/7z/7zIn.h
Normal file
431
CPP/7zip/Archive/7z/7zIn.h
Normal file
@@ -0,0 +1,431 @@
|
||||
// 7zIn.h
|
||||
|
||||
#ifndef __7Z_IN_H
|
||||
#define __7Z_IN_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
/*
|
||||
We don't need to init isEncrypted and passwordIsDefined
|
||||
We must upgrade them only */
|
||||
|
||||
#ifdef _NO_CRYPTO
|
||||
#define _7Z_DECODER_CRYPRO_VARS_DECL
|
||||
#define _7Z_DECODER_CRYPRO_VARS
|
||||
#else
|
||||
#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
|
||||
#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password
|
||||
#endif
|
||||
|
||||
struct CParsedMethods
|
||||
{
|
||||
Byte Lzma2Prop;
|
||||
UInt32 LzmaDic;
|
||||
CRecordVector<UInt64> IDs;
|
||||
|
||||
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
|
||||
};
|
||||
|
||||
struct CFolderEx: public CFolder
|
||||
{
|
||||
unsigned UnpackCoder;
|
||||
};
|
||||
|
||||
struct CFolders
|
||||
{
|
||||
CNum NumPackStreams;
|
||||
CNum NumFolders;
|
||||
|
||||
CObjArray<UInt64> PackPositions; // NumPackStreams + 1
|
||||
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now
|
||||
|
||||
CUInt32DefVector FolderCRCs; // NumFolders
|
||||
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
|
||||
|
||||
CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
|
||||
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
|
||||
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
|
||||
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
|
||||
|
||||
CObjArray<size_t> FoCodersDataOffset; // NumFolders + 1
|
||||
CByteBuffer CodersData;
|
||||
|
||||
CParsedMethods ParsedMethods;
|
||||
|
||||
void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
|
||||
void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
|
||||
{
|
||||
ParseFolderInfo(folderIndex, folder);
|
||||
folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
|
||||
}
|
||||
|
||||
unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
|
||||
{
|
||||
return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
|
||||
}
|
||||
|
||||
UInt64 GetFolderUnpackSize(unsigned folderIndex) const
|
||||
{
|
||||
return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];
|
||||
}
|
||||
|
||||
UInt64 GetStreamPackSize(unsigned index) const
|
||||
{
|
||||
return PackPositions[index + 1] - PackPositions[index];
|
||||
}
|
||||
|
||||
CFolders(): NumPackStreams(0), NumFolders(0) {}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
NumPackStreams = 0;
|
||||
PackPositions.Free();
|
||||
// PackCRCs.Clear();
|
||||
|
||||
NumFolders = 0;
|
||||
FolderCRCs.Clear();
|
||||
NumUnpackStreamsVector.Free();
|
||||
CoderUnpackSizes.Free();
|
||||
FoToCoderUnpackSizes.Free();
|
||||
FoStartPackStreamIndex.Free();
|
||||
FoToMainUnpackSizeIndex.Free();
|
||||
FoCodersDataOffset.Free();
|
||||
CodersData.Free();
|
||||
}
|
||||
};
|
||||
|
||||
struct CDatabase: public CFolders
|
||||
{
|
||||
CRecordVector<CFileItem> Files;
|
||||
|
||||
CUInt64DefVector CTime;
|
||||
CUInt64DefVector ATime;
|
||||
CUInt64DefVector MTime;
|
||||
CUInt64DefVector StartPos;
|
||||
CBoolVector IsAnti;
|
||||
/*
|
||||
CBoolVector IsAux;
|
||||
CByteBuffer SecureBuf;
|
||||
CRecordVector<UInt32> SecureIDs;
|
||||
*/
|
||||
|
||||
CByteBuffer NamesBuf;
|
||||
CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols
|
||||
|
||||
/*
|
||||
void ClearSecure()
|
||||
{
|
||||
SecureBuf.Free();
|
||||
SecureIDs.Clear();
|
||||
}
|
||||
*/
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CFolders::Clear();
|
||||
// ClearSecure();
|
||||
|
||||
NamesBuf.Free();
|
||||
NameOffsets.Free();
|
||||
|
||||
Files.Clear();
|
||||
CTime.Clear();
|
||||
ATime.Clear();
|
||||
MTime.Clear();
|
||||
StartPos.Clear();
|
||||
IsAnti.Clear();
|
||||
// IsAux.Clear();
|
||||
}
|
||||
|
||||
bool IsSolid() const
|
||||
{
|
||||
for (CNum i = 0; i < NumFolders; i++)
|
||||
if (NumUnpackStreamsVector[i] > 1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
|
||||
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
|
||||
|
||||
/*
|
||||
const void* GetName(unsigned index) const
|
||||
{
|
||||
if (!NameOffsets || !NamesBuf)
|
||||
return NULL;
|
||||
return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
|
||||
};
|
||||
*/
|
||||
void GetPath(unsigned index, UString &path) const;
|
||||
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
|
||||
};
|
||||
|
||||
struct CInArchiveInfo
|
||||
{
|
||||
CArchiveVersion Version;
|
||||
UInt64 StartPosition;
|
||||
UInt64 StartPositionAfterHeader;
|
||||
UInt64 DataStartPosition;
|
||||
UInt64 DataStartPosition2;
|
||||
CRecordVector<UInt64> FileInfoPopIDs;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
StartPosition = 0;
|
||||
StartPositionAfterHeader = 0;
|
||||
DataStartPosition = 0;
|
||||
DataStartPosition2 = 0;
|
||||
FileInfoPopIDs.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct CDbEx: public CDatabase
|
||||
{
|
||||
CInArchiveInfo ArcInfo;
|
||||
|
||||
CObjArray<CNum> FolderStartFileIndex;
|
||||
CObjArray<CNum> FileIndexToFolderIndexMap;
|
||||
|
||||
UInt64 HeadersSize;
|
||||
UInt64 PhySize;
|
||||
|
||||
/*
|
||||
CRecordVector<size_t> SecureOffsets;
|
||||
bool IsTree;
|
||||
bool ThereAreAltStreams;
|
||||
*/
|
||||
|
||||
bool IsArc;
|
||||
bool PhySizeWasConfirmed;
|
||||
|
||||
bool ThereIsHeaderError;
|
||||
bool UnexpectedEnd;
|
||||
// bool UnsupportedVersion;
|
||||
|
||||
bool StartHeaderWasRecovered;
|
||||
bool UnsupportedFeatureWarning;
|
||||
bool UnsupportedFeatureError;
|
||||
|
||||
/*
|
||||
void ClearSecureEx()
|
||||
{
|
||||
ClearSecure();
|
||||
SecureOffsets.Clear();
|
||||
}
|
||||
*/
|
||||
|
||||
void Clear()
|
||||
{
|
||||
IsArc = false;
|
||||
PhySizeWasConfirmed = false;
|
||||
|
||||
ThereIsHeaderError = false;
|
||||
UnexpectedEnd = false;
|
||||
// UnsupportedVersion = false;
|
||||
|
||||
StartHeaderWasRecovered = false;
|
||||
UnsupportedFeatureError = false;
|
||||
UnsupportedFeatureWarning = false;
|
||||
|
||||
/*
|
||||
IsTree = false;
|
||||
ThereAreAltStreams = false;
|
||||
*/
|
||||
|
||||
CDatabase::Clear();
|
||||
|
||||
// SecureOffsets.Clear();
|
||||
ArcInfo.Clear();
|
||||
FolderStartFileIndex.Free();
|
||||
FileIndexToFolderIndexMap.Free();
|
||||
|
||||
HeadersSize = 0;
|
||||
PhySize = 0;
|
||||
}
|
||||
|
||||
void FillLinks();
|
||||
|
||||
UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
|
||||
{
|
||||
return ArcInfo.DataStartPosition +
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
|
||||
}
|
||||
|
||||
UInt64 GetFolderFullPackSize(CNum folderIndex) const
|
||||
{
|
||||
return
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex]];
|
||||
}
|
||||
|
||||
UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
|
||||
{
|
||||
size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
|
||||
return PackPositions[i + 1] - PackPositions[i];
|
||||
}
|
||||
|
||||
UInt64 GetFilePackSize(CNum fileIndex) const
|
||||
{
|
||||
CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
if (FolderStartFileIndex[folderIndex] == fileIndex)
|
||||
return GetFolderFullPackSize(folderIndex);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
const unsigned kNumBufLevelsMax = 4;
|
||||
|
||||
struct CInByte2
|
||||
{
|
||||
const Byte *_buffer;
|
||||
public:
|
||||
size_t _size;
|
||||
size_t _pos;
|
||||
|
||||
size_t GetRem() const { return _size - _pos; }
|
||||
const Byte *GetPtr() const { return _buffer + _pos; }
|
||||
void Init(const Byte *buffer, size_t size)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
}
|
||||
Byte ReadByte();
|
||||
void ReadBytes(Byte *data, size_t size);
|
||||
void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
|
||||
void SkipData(UInt64 size);
|
||||
|
||||
void SkipData();
|
||||
void SkipRem() { _pos = _size; }
|
||||
UInt64 ReadNumber();
|
||||
CNum ReadNum();
|
||||
UInt32 ReadUInt32();
|
||||
UInt64 ReadUInt64();
|
||||
|
||||
void ParseFolder(CFolder &folder);
|
||||
};
|
||||
|
||||
class CStreamSwitch;
|
||||
|
||||
const UInt32 kHeaderSize = 32;
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
friend class CStreamSwitch;
|
||||
|
||||
CMyComPtr<IInStream> _stream;
|
||||
|
||||
unsigned _numInByteBufs;
|
||||
CInByte2 _inByteVector[kNumBufLevelsMax];
|
||||
|
||||
CInByte2 *_inByteBack;
|
||||
bool ThereIsHeaderError;
|
||||
|
||||
UInt64 _arhiveBeginStreamPosition;
|
||||
UInt64 _fileEndPosition;
|
||||
|
||||
Byte _header[kHeaderSize];
|
||||
|
||||
UInt64 HeadersSize;
|
||||
|
||||
bool _useMixerMT;
|
||||
|
||||
void AddByteStream(const Byte *buffer, size_t size);
|
||||
|
||||
void DeleteByteStream(bool needUpdatePos)
|
||||
{
|
||||
_numInByteBufs--;
|
||||
if (_numInByteBufs > 0)
|
||||
{
|
||||
_inByteBack = &_inByteVector[_numInByteBufs - 1];
|
||||
if (needUpdatePos)
|
||||
_inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
|
||||
|
||||
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
|
||||
Byte ReadByte() { return _inByteBack->ReadByte(); }
|
||||
UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
|
||||
CNum ReadNum() { return _inByteBack->ReadNum(); }
|
||||
UInt64 ReadID() { return _inByteBack->ReadNumber(); }
|
||||
UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
|
||||
UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
|
||||
void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
|
||||
void SkipData() { _inByteBack->SkipData(); }
|
||||
void WaitId(UInt64 id);
|
||||
|
||||
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
|
||||
void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
|
||||
|
||||
void ReadPackInfo(CFolders &f);
|
||||
|
||||
void ReadUnpackInfo(
|
||||
const CObjectVector<CByteBuffer> *dataVector,
|
||||
CFolders &folders);
|
||||
|
||||
void ReadSubStreamsInfo(
|
||||
CFolders &folders,
|
||||
CRecordVector<UInt64> &unpackSizes,
|
||||
CUInt32DefVector &digests);
|
||||
|
||||
void ReadStreamsInfo(
|
||||
const CObjectVector<CByteBuffer> *dataVector,
|
||||
UInt64 &dataOffset,
|
||||
CFolders &folders,
|
||||
CRecordVector<UInt64> &unpackSizes,
|
||||
CUInt32DefVector &digests);
|
||||
|
||||
void ReadBoolVector(unsigned numItems, CBoolVector &v);
|
||||
void ReadBoolVector2(unsigned numItems, CBoolVector &v);
|
||||
void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
|
||||
CUInt64DefVector &v, unsigned numItems);
|
||||
HRESULT ReadAndDecodePackedStreams(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
UInt64 baseOffset, UInt64 &dataOffset,
|
||||
CObjectVector<CByteBuffer> &dataVector
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
HRESULT ReadHeader(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CDbEx &db
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
HRESULT ReadDatabase2(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CDbEx &db
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
public:
|
||||
CInArchive(bool useMixerMT):
|
||||
_numInByteBufs(0),
|
||||
_useMixerMT(useMixerMT)
|
||||
{}
|
||||
|
||||
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
|
||||
void Close();
|
||||
|
||||
HRESULT ReadDatabase(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CDbEx &db
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
183
CPP/7zip/Archive/7z/7zItem.h
Normal file
183
CPP/7zip/Archive/7z/7zItem.h
Normal file
@@ -0,0 +1,183 @@
|
||||
// 7zItem.h
|
||||
|
||||
#ifndef __7Z_ITEM_H
|
||||
#define __7Z_ITEM_H
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../Common/MethodId.h"
|
||||
|
||||
#include "7zHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
typedef UInt32 CNum;
|
||||
const CNum kNumMax = 0x7FFFFFFF;
|
||||
const CNum kNumNoIndex = 0xFFFFFFFF;
|
||||
|
||||
struct CCoderInfo
|
||||
{
|
||||
CMethodId MethodID;
|
||||
CByteBuffer Props;
|
||||
UInt32 NumStreams;
|
||||
|
||||
bool IsSimpleCoder() const { return NumStreams == 1; }
|
||||
};
|
||||
|
||||
struct CBond
|
||||
{
|
||||
UInt32 PackIndex;
|
||||
UInt32 UnpackIndex;
|
||||
};
|
||||
|
||||
struct CFolder
|
||||
{
|
||||
CLASS_NO_COPY(CFolder)
|
||||
public:
|
||||
CObjArray2<CCoderInfo> Coders;
|
||||
CObjArray2<CBond> Bonds;
|
||||
CObjArray2<UInt32> PackStreams;
|
||||
|
||||
CFolder() {}
|
||||
|
||||
bool IsDecodingSupported() const { return Coders.Size() <= 32; }
|
||||
|
||||
int Find_in_PackStreams(UInt32 packStream) const
|
||||
{
|
||||
FOR_VECTOR(i, PackStreams)
|
||||
if (PackStreams[i] == packStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindBond_for_PackStream(UInt32 packStream) const
|
||||
{
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].PackIndex == packStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
int FindBond_for_UnpackStream(UInt32 unpackStream) const
|
||||
{
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].UnpackIndex == unpackStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindOutCoder() const
|
||||
{
|
||||
for (int i = (int)Coders.Size() - 1; i >= 0; i--)
|
||||
if (FindBond_for_UnpackStream(i) < 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
FOR_VECTOR(i, Coders)
|
||||
if (Coders[i].MethodID == k_AES)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct CUInt32DefVector
|
||||
{
|
||||
CBoolVector Defs;
|
||||
CRecordVector<UInt32> Vals;
|
||||
|
||||
void ClearAndSetSize(unsigned newSize)
|
||||
{
|
||||
Defs.ClearAndSetSize(newSize);
|
||||
Vals.ClearAndSetSize(newSize);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Defs.Clear();
|
||||
Vals.Clear();
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
Defs.ReserveDown();
|
||||
Vals.ReserveDown();
|
||||
}
|
||||
|
||||
bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
|
||||
};
|
||||
|
||||
struct CUInt64DefVector
|
||||
{
|
||||
CBoolVector Defs;
|
||||
CRecordVector<UInt64> Vals;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Defs.Clear();
|
||||
Vals.Clear();
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
Defs.ReserveDown();
|
||||
Vals.ReserveDown();
|
||||
}
|
||||
|
||||
bool GetItem(unsigned index, UInt64 &value) const
|
||||
{
|
||||
if (index < Defs.Size() && Defs[index])
|
||||
{
|
||||
value = Vals[index];
|
||||
return true;
|
||||
}
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetItem(unsigned index, bool defined, UInt64 value);
|
||||
|
||||
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
|
||||
};
|
||||
|
||||
struct CFileItem
|
||||
{
|
||||
UInt64 Size;
|
||||
UInt32 Attrib;
|
||||
UInt32 Crc;
|
||||
/*
|
||||
int Parent;
|
||||
bool IsAltStream;
|
||||
*/
|
||||
bool HasStream; // Test it !!! it means that there is
|
||||
// stream in some folder. It can be empty stream
|
||||
bool IsDir;
|
||||
bool CrcDefined;
|
||||
bool AttribDefined;
|
||||
|
||||
CFileItem():
|
||||
/*
|
||||
Parent(-1),
|
||||
IsAltStream(false),
|
||||
*/
|
||||
HasStream(true),
|
||||
IsDir(false),
|
||||
CrcDefined(false),
|
||||
AttribDefined(false)
|
||||
{}
|
||||
void SetAttrib(UInt32 attrib)
|
||||
{
|
||||
AttribDefined = true;
|
||||
Attrib = attrib;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
916
CPP/7zip/Archive/7z/7zOut.cpp
Normal file
916
CPP/7zip/Archive/7z/7zOut.cpp
Normal file
@@ -0,0 +1,916 @@
|
||||
// 7zOut.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/AutoPtr.h"
|
||||
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
#include "7zOut.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
HRESULT COutArchive::WriteSignature()
|
||||
{
|
||||
Byte buf[8];
|
||||
memcpy(buf, kSignature, kSignatureSize);
|
||||
buf[kSignatureSize] = kMajorVersion;
|
||||
buf[kSignatureSize + 1] = 4;
|
||||
return WriteDirect(buf, 8);
|
||||
}
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
HRESULT COutArchive::WriteFinishSignature()
|
||||
{
|
||||
RINOK(WriteDirect(kFinishSignature, kSignatureSize));
|
||||
CArchiveVersion av;
|
||||
av.Major = kMajorVersion;
|
||||
av.Minor = 2;
|
||||
RINOK(WriteDirectByte(av.Major));
|
||||
return WriteDirectByte(av.Minor);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SetUInt32(Byte *p, UInt32 d)
|
||||
{
|
||||
for (int i = 0; i < 4; i++, d >>= 8)
|
||||
p[i] = (Byte)d;
|
||||
}
|
||||
|
||||
static void SetUInt64(Byte *p, UInt64 d)
|
||||
{
|
||||
for (int i = 0; i < 8; i++, d >>= 8)
|
||||
p[i] = (Byte)d;
|
||||
}
|
||||
|
||||
HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
|
||||
{
|
||||
Byte buf[24];
|
||||
SetUInt64(buf + 4, h.NextHeaderOffset);
|
||||
SetUInt64(buf + 12, h.NextHeaderSize);
|
||||
SetUInt32(buf + 20, h.NextHeaderCRC);
|
||||
SetUInt32(buf, CrcCalc(buf + 4, 20));
|
||||
return WriteDirect(buf, 24);
|
||||
}
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
|
||||
{
|
||||
CCRC crc;
|
||||
crc.UpdateUInt64(h.NextHeaderOffset);
|
||||
crc.UpdateUInt64(h.NextHeaderSize);
|
||||
crc.UpdateUInt32(h.NextHeaderCRC);
|
||||
crc.UpdateUInt64(h.ArchiveStartOffset);
|
||||
crc.UpdateUInt64(h.AdditionalStartBlockSize);
|
||||
RINOK(WriteDirectUInt32(crc.GetDigest()));
|
||||
RINOK(WriteDirectUInt64(h.NextHeaderOffset));
|
||||
RINOK(WriteDirectUInt64(h.NextHeaderSize));
|
||||
RINOK(WriteDirectUInt32(h.NextHeaderCRC));
|
||||
RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
|
||||
return WriteDirectUInt64(h.AdditionalStartBlockSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
|
||||
{
|
||||
Close();
|
||||
#ifdef _7Z_VOL
|
||||
// endMarker = false;
|
||||
_endMarker = endMarker;
|
||||
#endif
|
||||
SeqStream = stream;
|
||||
if (!endMarker)
|
||||
{
|
||||
SeqStream.QueryInterface(IID_IOutStream, &Stream);
|
||||
if (!Stream)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
// endMarker = true;
|
||||
}
|
||||
}
|
||||
#ifdef _7Z_VOL
|
||||
if (endMarker)
|
||||
{
|
||||
/*
|
||||
CStartHeader sh;
|
||||
sh.NextHeaderOffset = (UInt32)(Int32)-1;
|
||||
sh.NextHeaderSize = (UInt32)(Int32)-1;
|
||||
sh.NextHeaderCRC = 0;
|
||||
WriteStartHeader(sh);
|
||||
*/
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!Stream)
|
||||
return E_FAIL;
|
||||
RINOK(WriteSignature());
|
||||
RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutArchive::Close()
|
||||
{
|
||||
SeqStream.Release();
|
||||
Stream.Release();
|
||||
}
|
||||
|
||||
HRESULT COutArchive::SkipPrefixArchiveHeader()
|
||||
{
|
||||
#ifdef _7Z_VOL
|
||||
if (_endMarker)
|
||||
return S_OK;
|
||||
#endif
|
||||
Byte buf[24];
|
||||
memset(buf, 0, 24);
|
||||
return WriteDirect(buf, 24);
|
||||
}
|
||||
|
||||
UInt64 COutArchive::GetPos() const
|
||||
{
|
||||
if (_countMode)
|
||||
return _countSize;
|
||||
if (_writeToStream)
|
||||
return _outByte.GetProcessedSize();
|
||||
return _outByte2.GetPos();
|
||||
}
|
||||
|
||||
void COutArchive::WriteBytes(const void *data, size_t size)
|
||||
{
|
||||
if (_countMode)
|
||||
_countSize += size;
|
||||
else if (_writeToStream)
|
||||
{
|
||||
_outByte.WriteBytes(data, size);
|
||||
_crc = CrcUpdate(_crc, data, size);
|
||||
}
|
||||
else
|
||||
_outByte2.WriteBytes(data, size);
|
||||
}
|
||||
|
||||
void COutArchive::WriteByte(Byte b)
|
||||
{
|
||||
if (_countMode)
|
||||
_countSize++;
|
||||
else if (_writeToStream)
|
||||
{
|
||||
_outByte.WriteByte(b);
|
||||
_crc = CRC_UPDATE_BYTE(_crc, b);
|
||||
}
|
||||
else
|
||||
_outByte2.WriteByte(b);
|
||||
}
|
||||
|
||||
void COutArchive::WriteUInt32(UInt32 value)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
WriteByte((Byte)value);
|
||||
value >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void COutArchive::WriteUInt64(UInt64 value)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
WriteByte((Byte)value);
|
||||
value >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void 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;
|
||||
}
|
||||
WriteByte(firstByte);
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
WriteByte((Byte)value);
|
||||
value >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static UInt32 GetBigNumberSize(UInt64 value)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < 9; i++)
|
||||
if (value < (((UInt64)1 << (i * 7))))
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
|
||||
{
|
||||
UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
|
||||
if (nameLength != 0)
|
||||
{
|
||||
nameLength = (nameLength + 1) * 2;
|
||||
result += nameLength + GetBigNumberSize(nameLength) + 2;
|
||||
}
|
||||
if (props)
|
||||
{
|
||||
result += 20;
|
||||
}
|
||||
if (result >= 128)
|
||||
result++;
|
||||
result += kSignatureSize + 2 + kFinishHeaderSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
|
||||
{
|
||||
UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
|
||||
int testSize;
|
||||
if (volSize > headersSizeBase)
|
||||
testSize = volSize - headersSizeBase;
|
||||
else
|
||||
testSize = 1;
|
||||
UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
|
||||
UInt64 pureSize = 1;
|
||||
if (volSize > headersSize)
|
||||
pureSize = volSize - headersSize;
|
||||
return pureSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
void COutArchive::WriteFolder(const CFolder &folder)
|
||||
{
|
||||
WriteNumber(folder.Coders.Size());
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < folder.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coder = folder.Coders[i];
|
||||
{
|
||||
UInt64 id = coder.MethodID;
|
||||
unsigned idSize;
|
||||
for (idSize = 1; idSize < sizeof(id); idSize++)
|
||||
if ((id >> (8 * idSize)) == 0)
|
||||
break;
|
||||
idSize &= 0xF;
|
||||
Byte temp[16];
|
||||
for (unsigned t = idSize; t != 0; t--, id >>= 8)
|
||||
temp[t] = (Byte)(id & 0xFF);
|
||||
|
||||
Byte b = (Byte)(idSize);
|
||||
bool isComplex = !coder.IsSimpleCoder();
|
||||
b |= (isComplex ? 0x10 : 0);
|
||||
|
||||
size_t propsSize = coder.Props.Size();
|
||||
b |= ((propsSize != 0) ? 0x20 : 0);
|
||||
temp[0] = b;
|
||||
WriteBytes(temp, idSize + 1);
|
||||
if (isComplex)
|
||||
{
|
||||
WriteNumber(coder.NumStreams);
|
||||
WriteNumber(1); // NumOutStreams;
|
||||
}
|
||||
if (propsSize == 0)
|
||||
continue;
|
||||
WriteNumber(propsSize);
|
||||
WriteBytes(coder.Props, propsSize);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < folder.Bonds.Size(); i++)
|
||||
{
|
||||
const CBond &bond = folder.Bonds[i];
|
||||
WriteNumber(bond.PackIndex);
|
||||
WriteNumber(bond.UnpackIndex);
|
||||
}
|
||||
|
||||
if (folder.PackStreams.Size() > 1)
|
||||
for (i = 0; i < folder.PackStreams.Size(); i++)
|
||||
WriteNumber(folder.PackStreams[i]);
|
||||
}
|
||||
|
||||
void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
|
||||
{
|
||||
Byte b = 0;
|
||||
Byte mask = 0x80;
|
||||
FOR_VECTOR (i, boolVector)
|
||||
{
|
||||
if (boolVector[i])
|
||||
b |= mask;
|
||||
mask >>= 1;
|
||||
if (mask == 0)
|
||||
{
|
||||
WriteByte(b);
|
||||
mask = 0x80;
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
if (mask != 0x80)
|
||||
WriteByte(b);
|
||||
}
|
||||
|
||||
static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
|
||||
|
||||
void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
|
||||
{
|
||||
WriteByte(id);
|
||||
WriteNumber(Bv_GetSizeInBytes(boolVector));
|
||||
WriteBoolVector(boolVector);
|
||||
}
|
||||
|
||||
void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
|
||||
{
|
||||
unsigned numDefined = 0;
|
||||
unsigned i;
|
||||
for (i = 0; i < digests.Defs.Size(); i++)
|
||||
if (digests.Defs[i])
|
||||
numDefined++;
|
||||
if (numDefined == 0)
|
||||
return;
|
||||
|
||||
WriteByte(NID::kCRC);
|
||||
if (numDefined == digests.Defs.Size())
|
||||
WriteByte(1);
|
||||
else
|
||||
{
|
||||
WriteByte(0);
|
||||
WriteBoolVector(digests.Defs);
|
||||
}
|
||||
for (i = 0; i < digests.Defs.Size(); i++)
|
||||
if (digests.Defs[i])
|
||||
WriteUInt32(digests.Vals[i]);
|
||||
}
|
||||
|
||||
void COutArchive::WritePackInfo(
|
||||
UInt64 dataOffset,
|
||||
const CRecordVector<UInt64> &packSizes,
|
||||
const CUInt32DefVector &packCRCs)
|
||||
{
|
||||
if (packSizes.IsEmpty())
|
||||
return;
|
||||
WriteByte(NID::kPackInfo);
|
||||
WriteNumber(dataOffset);
|
||||
WriteNumber(packSizes.Size());
|
||||
WriteByte(NID::kSize);
|
||||
FOR_VECTOR (i, packSizes)
|
||||
WriteNumber(packSizes[i]);
|
||||
|
||||
WriteHashDigests(packCRCs);
|
||||
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)
|
||||
{
|
||||
if (folders.IsEmpty())
|
||||
return;
|
||||
|
||||
WriteByte(NID::kUnpackInfo);
|
||||
|
||||
WriteByte(NID::kFolder);
|
||||
WriteNumber(folders.Size());
|
||||
{
|
||||
WriteByte(0);
|
||||
FOR_VECTOR (i, folders)
|
||||
WriteFolder(folders[i]);
|
||||
}
|
||||
|
||||
WriteByte(NID::kCodersUnpackSize);
|
||||
FOR_VECTOR (i, outFolders.CoderUnpackSizes)
|
||||
WriteNumber(outFolders.CoderUnpackSizes[i]);
|
||||
|
||||
WriteHashDigests(outFolders.FolderUnpackCRCs);
|
||||
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
|
||||
const COutFolders &outFolders,
|
||||
const CRecordVector<UInt64> &unpackSizes,
|
||||
const CUInt32DefVector &digests)
|
||||
{
|
||||
const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;
|
||||
WriteByte(NID::kSubStreamsInfo);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
|
||||
if (numUnpackStreamsInFolders[i] != 1)
|
||||
{
|
||||
WriteByte(NID::kNumUnpackStream);
|
||||
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
|
||||
WriteNumber(numUnpackStreamsInFolders[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
|
||||
if (numUnpackStreamsInFolders[i] > 1)
|
||||
{
|
||||
WriteByte(NID::kSize);
|
||||
CNum index = 0;
|
||||
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
|
||||
{
|
||||
CNum num = numUnpackStreamsInFolders[i];
|
||||
for (CNum j = 0; j < num; j++)
|
||||
{
|
||||
if (j + 1 != num)
|
||||
WriteNumber(unpackSizes[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
CUInt32DefVector digests2;
|
||||
|
||||
unsigned digestIndex = 0;
|
||||
for (i = 0; i < folders.Size(); i++)
|
||||
{
|
||||
unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];
|
||||
if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))
|
||||
digestIndex++;
|
||||
else
|
||||
for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)
|
||||
{
|
||||
digests2.Defs.Add(digests.Defs[digestIndex]);
|
||||
digests2.Vals.Add(digests.Vals[digestIndex]);
|
||||
}
|
||||
}
|
||||
WriteHashDigests(digests2);
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
|
||||
|
||||
void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
|
||||
{
|
||||
if (!_useAlign)
|
||||
return;
|
||||
pos += (unsigned)GetPos();
|
||||
pos &= (alignSize - 1);
|
||||
if (pos == 0)
|
||||
return;
|
||||
unsigned skip = alignSize - pos;
|
||||
if (skip < 2)
|
||||
skip += alignSize;
|
||||
skip -= 2;
|
||||
WriteByte(NID::kDummy);
|
||||
WriteByte((Byte)skip);
|
||||
for (unsigned i = 0; i < skip; i++)
|
||||
WriteByte(0);
|
||||
}
|
||||
|
||||
void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize)
|
||||
{
|
||||
const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
|
||||
const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;
|
||||
SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize);
|
||||
|
||||
WriteByte(type);
|
||||
WriteNumber(dataSize);
|
||||
if (numDefined == v.Size())
|
||||
WriteByte(1);
|
||||
else
|
||||
{
|
||||
WriteByte(0);
|
||||
WriteBoolVector(v);
|
||||
}
|
||||
WriteByte(0);
|
||||
}
|
||||
|
||||
void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
|
||||
{
|
||||
unsigned numDefined = 0;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < v.Defs.Size(); i++)
|
||||
if (v.Defs[i])
|
||||
numDefined++;
|
||||
|
||||
if (numDefined == 0)
|
||||
return;
|
||||
|
||||
WriteAlignedBoolHeader(v.Defs, numDefined, type, 8);
|
||||
|
||||
for (i = 0; i < v.Defs.Size(); i++)
|
||||
if (v.Defs[i])
|
||||
WriteUInt64(v.Vals[i]);
|
||||
}
|
||||
|
||||
HRESULT COutArchive::EncodeStream(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CEncoder &encoder, const CByteBuffer &data,
|
||||
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
|
||||
{
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<ISequentialInStream> stream = streamSpec;
|
||||
streamSpec->Init(data, data.Size());
|
||||
outFolders.FolderUnpackCRCs.Defs.Add(true);
|
||||
outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
|
||||
// outFolders.NumUnpackStreamsVector.Add(1);
|
||||
UInt64 dataSize64 = data.Size();
|
||||
UInt64 unpackSize;
|
||||
RINOK(encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
stream,
|
||||
// NULL,
|
||||
&dataSize64,
|
||||
folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutArchive::WriteHeader(
|
||||
const CArchiveDatabaseOut &db,
|
||||
// const CHeaderOptions &headerOptions,
|
||||
UInt64 &headerOffset)
|
||||
{
|
||||
/*
|
||||
bool thereIsSecure = (db.SecureBuf.Size() != 0);
|
||||
*/
|
||||
_useAlign = true;
|
||||
|
||||
{
|
||||
UInt64 packSize = 0;
|
||||
FOR_VECTOR (i, db.PackSizes)
|
||||
packSize += db.PackSizes[i];
|
||||
headerOffset = packSize;
|
||||
}
|
||||
|
||||
|
||||
WriteByte(NID::kHeader);
|
||||
|
||||
// Archive Properties
|
||||
|
||||
if (db.Folders.Size() > 0)
|
||||
{
|
||||
WriteByte(NID::kMainStreamsInfo);
|
||||
WritePackInfo(0, db.PackSizes, db.PackCRCs);
|
||||
WriteUnpackInfo(db.Folders, (const COutFolders &)db);
|
||||
|
||||
CRecordVector<UInt64> unpackSizes;
|
||||
CUInt32DefVector digests;
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
if (!file.HasStream)
|
||||
continue;
|
||||
unpackSizes.Add(file.Size);
|
||||
digests.Defs.Add(file.CrcDefined);
|
||||
digests.Vals.Add(file.Crc);
|
||||
}
|
||||
|
||||
WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
if (db.Files.IsEmpty())
|
||||
{
|
||||
WriteByte(NID::kEnd);
|
||||
return;
|
||||
}
|
||||
|
||||
WriteByte(NID::kFilesInfo);
|
||||
WriteNumber(db.Files.Size());
|
||||
|
||||
{
|
||||
/* ---------- Empty Streams ---------- */
|
||||
CBoolVector emptyStreamVector;
|
||||
emptyStreamVector.ClearAndSetSize(db.Files.Size());
|
||||
unsigned numEmptyStreams = 0;
|
||||
{
|
||||
FOR_VECTOR (i, db.Files)
|
||||
if (db.Files[i].HasStream)
|
||||
emptyStreamVector[i] = false;
|
||||
else
|
||||
{
|
||||
emptyStreamVector[i] = true;
|
||||
numEmptyStreams++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numEmptyStreams != 0)
|
||||
{
|
||||
WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
|
||||
|
||||
CBoolVector emptyFileVector, antiVector;
|
||||
emptyFileVector.ClearAndSetSize(numEmptyStreams);
|
||||
antiVector.ClearAndSetSize(numEmptyStreams);
|
||||
bool thereAreEmptyFiles = false, thereAreAntiItems = false;
|
||||
unsigned cur = 0;
|
||||
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
if (file.HasStream)
|
||||
continue;
|
||||
emptyFileVector[cur] = !file.IsDir;
|
||||
if (!file.IsDir)
|
||||
thereAreEmptyFiles = true;
|
||||
bool isAnti = db.IsItemAnti(i);
|
||||
antiVector[cur] = isAnti;
|
||||
if (isAnti)
|
||||
thereAreAntiItems = true;
|
||||
cur++;
|
||||
}
|
||||
|
||||
if (thereAreEmptyFiles)
|
||||
WritePropBoolVector(NID::kEmptyFile, emptyFileVector);
|
||||
if (thereAreAntiItems)
|
||||
WritePropBoolVector(NID::kAnti, antiVector);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
/* ---------- Names ---------- */
|
||||
|
||||
unsigned numDefined = 0;
|
||||
size_t namesDataSize = 0;
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
const UString &name = db.Names[i];
|
||||
if (!name.IsEmpty())
|
||||
numDefined++;
|
||||
namesDataSize += (name.Len() + 1) * 2;
|
||||
}
|
||||
|
||||
if (numDefined > 0)
|
||||
{
|
||||
namesDataSize++;
|
||||
SkipAlign(2 + GetBigNumberSize(namesDataSize), 16);
|
||||
|
||||
WriteByte(NID::kName);
|
||||
WriteNumber(namesDataSize);
|
||||
WriteByte(0);
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
const UString &name = db.Names[i];
|
||||
for (unsigned t = 0; t <= name.Len(); t++)
|
||||
{
|
||||
wchar_t c = name[t];
|
||||
WriteByte((Byte)c);
|
||||
WriteByte((Byte)(c >> 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime);
|
||||
/* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime);
|
||||
/* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime);
|
||||
WriteUInt64DefVector(db.StartPos, NID::kStartPos);
|
||||
|
||||
{
|
||||
/* ---------- Write Attrib ---------- */
|
||||
CBoolVector boolVector;
|
||||
boolVector.ClearAndSetSize(db.Files.Size());
|
||||
unsigned numDefined = 0;
|
||||
|
||||
{
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
bool defined = db.Files[i].AttribDefined;
|
||||
boolVector[i] = defined;
|
||||
if (defined)
|
||||
numDefined++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numDefined != 0)
|
||||
{
|
||||
WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
if (file.AttribDefined)
|
||||
WriteUInt32(file.Attrib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
// ---------- Write IsAux ----------
|
||||
unsigned numAux = 0;
|
||||
const CBoolVector &isAux = db.IsAux;
|
||||
for (i = 0; i < isAux.Size(); i++)
|
||||
if (isAux[i])
|
||||
numAux++;
|
||||
if (numAux > 0)
|
||||
{
|
||||
const unsigned bvSize = Bv_GetSizeInBytes(isAux);
|
||||
WriteByte(NID::kIsAux);
|
||||
WriteNumber(bvSize);
|
||||
WriteBoolVector(isAux);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// ---------- Write Parent ----------
|
||||
CBoolVector boolVector;
|
||||
boolVector.Reserve(db.Files.Size());
|
||||
unsigned numIsDir = 0;
|
||||
unsigned numParentLinks = 0;
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
bool defined = !file.IsAltStream;
|
||||
boolVector.Add(defined);
|
||||
if (defined)
|
||||
numIsDir++;
|
||||
if (file.Parent >= 0)
|
||||
numParentLinks++;
|
||||
}
|
||||
if (numParentLinks > 0)
|
||||
{
|
||||
// WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4);
|
||||
const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
|
||||
const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
|
||||
SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4);
|
||||
|
||||
WriteByte(NID::kParent);
|
||||
WriteNumber(dataSize);
|
||||
if (numIsDir == boolVector.Size())
|
||||
WriteByte(1);
|
||||
else
|
||||
{
|
||||
WriteByte(0);
|
||||
WriteBoolVector(boolVector);
|
||||
}
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
// if (file.Parent >= 0)
|
||||
WriteUInt32(file.Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thereIsSecure)
|
||||
{
|
||||
UInt64 secureDataSize = 1 + 4 +
|
||||
db.SecureBuf.Size() +
|
||||
db.SecureSizes.Size() * 4;
|
||||
// secureDataSize += db.SecureIDs.Size() * 4;
|
||||
for (i = 0; i < db.SecureIDs.Size(); i++)
|
||||
secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
|
||||
SkipAlign(2 + GetBigNumberSize(secureDataSize), 4);
|
||||
WriteByte(NID::kNtSecure);
|
||||
WriteNumber(secureDataSize);
|
||||
WriteByte(0);
|
||||
WriteUInt32(db.SecureSizes.Size());
|
||||
for (i = 0; i < db.SecureSizes.Size(); i++)
|
||||
WriteUInt32(db.SecureSizes[i]);
|
||||
WriteBytes(db.SecureBuf, db.SecureBuf.Size());
|
||||
for (i = 0; i < db.SecureIDs.Size(); i++)
|
||||
{
|
||||
WriteNumber(db.SecureIDs[i]);
|
||||
// WriteUInt32(db.SecureIDs[i]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
WriteByte(NID::kEnd); // for files
|
||||
WriteByte(NID::kEnd); // for headers
|
||||
}
|
||||
|
||||
HRESULT COutArchive::WriteDatabase(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CArchiveDatabaseOut &db,
|
||||
const CCompressionMethodMode *options,
|
||||
const CHeaderOptions &headerOptions)
|
||||
{
|
||||
if (!db.CheckNumFiles())
|
||||
return E_FAIL;
|
||||
|
||||
UInt64 headerOffset;
|
||||
UInt32 headerCRC;
|
||||
UInt64 headerSize;
|
||||
if (db.IsEmpty())
|
||||
{
|
||||
headerSize = 0;
|
||||
headerOffset = 0;
|
||||
headerCRC = CrcCalc(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool encodeHeaders = false;
|
||||
if (options != 0)
|
||||
if (options->IsEmpty())
|
||||
options = 0;
|
||||
if (options != 0)
|
||||
if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
|
||||
encodeHeaders = true;
|
||||
|
||||
_outByte.SetStream(SeqStream);
|
||||
_outByte.Init();
|
||||
_crc = CRC_INIT_VAL;
|
||||
_countMode = encodeHeaders;
|
||||
_writeToStream = true;
|
||||
_countSize = 0;
|
||||
WriteHeader(db, /* headerOptions, */ headerOffset);
|
||||
|
||||
if (encodeHeaders)
|
||||
{
|
||||
CByteBuffer buf(_countSize);
|
||||
_outByte2.Init((Byte *)buf, _countSize);
|
||||
|
||||
_countMode = false;
|
||||
_writeToStream = false;
|
||||
WriteHeader(db, /* headerOptions, */ headerOffset);
|
||||
|
||||
if (_countSize != _outByte2.GetPos())
|
||||
return E_FAIL;
|
||||
|
||||
CCompressionMethodMode encryptOptions;
|
||||
encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
|
||||
encryptOptions.Password = options->Password;
|
||||
CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
|
||||
CRecordVector<UInt64> packSizes;
|
||||
CObjectVector<CFolder> folders;
|
||||
COutFolders outFolders;
|
||||
|
||||
RINOK(EncodeStream(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
encoder, buf,
|
||||
packSizes, folders, outFolders));
|
||||
|
||||
_writeToStream = true;
|
||||
|
||||
if (folders.Size() == 0)
|
||||
throw 1;
|
||||
|
||||
WriteID(NID::kEncodedHeader);
|
||||
WritePackInfo(headerOffset, packSizes, CUInt32DefVector());
|
||||
WriteUnpackInfo(folders, outFolders);
|
||||
WriteByte(NID::kEnd);
|
||||
FOR_VECTOR (i, packSizes)
|
||||
headerOffset += packSizes[i];
|
||||
}
|
||||
RINOK(_outByte.Flush());
|
||||
headerCRC = CRC_GET_DIGEST(_crc);
|
||||
headerSize = _outByte.GetProcessedSize();
|
||||
}
|
||||
#ifdef _7Z_VOL
|
||||
if (_endMarker)
|
||||
{
|
||||
CFinishHeader h;
|
||||
h.NextHeaderSize = headerSize;
|
||||
h.NextHeaderCRC = headerCRC;
|
||||
h.NextHeaderOffset =
|
||||
UInt64(0) - (headerSize +
|
||||
4 + kFinishHeaderSize);
|
||||
h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
|
||||
h.AdditionalStartBlockSize = 0;
|
||||
RINOK(WriteFinishHeader(h));
|
||||
return WriteFinishSignature();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
CStartHeader h;
|
||||
h.NextHeaderSize = headerSize;
|
||||
h.NextHeaderCRC = headerCRC;
|
||||
h.NextHeaderOffset = headerOffset;
|
||||
RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
|
||||
return WriteStartHeader(h);
|
||||
}
|
||||
}
|
||||
|
||||
void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
|
||||
{
|
||||
while (index >= Defs.Size())
|
||||
Defs.Add(false);
|
||||
Defs[index] = defined;
|
||||
if (!defined)
|
||||
return;
|
||||
while (index >= Vals.Size())
|
||||
Vals.Add(0);
|
||||
Vals[index] = value;
|
||||
}
|
||||
|
||||
void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)
|
||||
{
|
||||
unsigned index = Files.Size();
|
||||
CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
|
||||
ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
|
||||
MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
|
||||
StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
|
||||
SetItem_Anti(index, file2.IsAnti);
|
||||
// SetItem_Aux(index, file2.IsAux);
|
||||
Names.Add(name);
|
||||
Files.Add(file);
|
||||
}
|
||||
|
||||
}}
|
||||
321
CPP/7zip/Archive/7z/7zOut.h
Normal file
321
CPP/7zip/Archive/7z/7zOut.h
Normal file
@@ -0,0 +1,321 @@
|
||||
// 7zOut.h
|
||||
|
||||
#ifndef __7Z_OUT_H
|
||||
#define __7Z_OUT_H
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zEncode.h"
|
||||
#include "7zHeader.h"
|
||||
#include "7zItem.h"
|
||||
|
||||
#include "../../Common/OutBuffer.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
class CWriteBufferLoc
|
||||
{
|
||||
Byte *_data;
|
||||
size_t _size;
|
||||
size_t _pos;
|
||||
public:
|
||||
CWriteBufferLoc(): _size(0), _pos(0) {}
|
||||
void Init(Byte *data, size_t size)
|
||||
{
|
||||
_data = data;
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
}
|
||||
void WriteBytes(const void *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
if (size > _size - _pos)
|
||||
throw 1;
|
||||
memcpy(_data + _pos, data, size);
|
||||
_pos += size;
|
||||
}
|
||||
void WriteByte(Byte b)
|
||||
{
|
||||
if (_size == _pos)
|
||||
throw 1;
|
||||
_data[_pos++] = b;
|
||||
}
|
||||
size_t GetPos() const { return _pos; }
|
||||
};
|
||||
|
||||
struct CHeaderOptions
|
||||
{
|
||||
bool CompressMainHeader;
|
||||
/*
|
||||
bool WriteCTime;
|
||||
bool WriteATime;
|
||||
bool WriteMTime;
|
||||
*/
|
||||
|
||||
CHeaderOptions():
|
||||
CompressMainHeader(true)
|
||||
/*
|
||||
, WriteCTime(false)
|
||||
, WriteATime(false)
|
||||
, WriteMTime(true)
|
||||
*/
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct CFileItem2
|
||||
{
|
||||
UInt64 CTime;
|
||||
UInt64 ATime;
|
||||
UInt64 MTime;
|
||||
UInt64 StartPos;
|
||||
bool CTimeDefined;
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
bool StartPosDefined;
|
||||
bool IsAnti;
|
||||
// bool IsAux;
|
||||
|
||||
void Init()
|
||||
{
|
||||
CTimeDefined = false;
|
||||
ATimeDefined = false;
|
||||
MTimeDefined = false;
|
||||
StartPosDefined = false;
|
||||
IsAnti = false;
|
||||
// IsAux = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct COutFolders
|
||||
{
|
||||
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
|
||||
|
||||
CRecordVector<CNum> NumUnpackStreamsVector;
|
||||
CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
|
||||
|
||||
void OutFoldersClear()
|
||||
{
|
||||
FolderUnpackCRCs.Clear();
|
||||
NumUnpackStreamsVector.Clear();
|
||||
CoderUnpackSizes.Clear();
|
||||
}
|
||||
|
||||
void OutFoldersReserveDown()
|
||||
{
|
||||
FolderUnpackCRCs.ReserveDown();
|
||||
NumUnpackStreamsVector.ReserveDown();
|
||||
CoderUnpackSizes.ReserveDown();
|
||||
}
|
||||
};
|
||||
|
||||
struct CArchiveDatabaseOut: public COutFolders
|
||||
{
|
||||
CRecordVector<UInt64> PackSizes;
|
||||
CUInt32DefVector PackCRCs;
|
||||
CObjectVector<CFolder> Folders;
|
||||
|
||||
CRecordVector<CFileItem> Files;
|
||||
UStringVector Names;
|
||||
CUInt64DefVector CTime;
|
||||
CUInt64DefVector ATime;
|
||||
CUInt64DefVector MTime;
|
||||
CUInt64DefVector StartPos;
|
||||
CRecordVector<bool> IsAnti;
|
||||
|
||||
/*
|
||||
CRecordVector<bool> IsAux;
|
||||
|
||||
CByteBuffer SecureBuf;
|
||||
CRecordVector<UInt32> SecureSizes;
|
||||
CRecordVector<UInt32> SecureIDs;
|
||||
|
||||
void ClearSecure()
|
||||
{
|
||||
SecureBuf.Free();
|
||||
SecureSizes.Clear();
|
||||
SecureIDs.Clear();
|
||||
}
|
||||
*/
|
||||
|
||||
void Clear()
|
||||
{
|
||||
OutFoldersClear();
|
||||
|
||||
PackSizes.Clear();
|
||||
PackCRCs.Clear();
|
||||
Folders.Clear();
|
||||
|
||||
Files.Clear();
|
||||
Names.Clear();
|
||||
CTime.Clear();
|
||||
ATime.Clear();
|
||||
MTime.Clear();
|
||||
StartPos.Clear();
|
||||
IsAnti.Clear();
|
||||
|
||||
/*
|
||||
IsAux.Clear();
|
||||
ClearSecure();
|
||||
*/
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
OutFoldersReserveDown();
|
||||
|
||||
PackSizes.ReserveDown();
|
||||
PackCRCs.ReserveDown();
|
||||
Folders.ReserveDown();
|
||||
|
||||
Files.ReserveDown();
|
||||
Names.ReserveDown();
|
||||
CTime.ReserveDown();
|
||||
ATime.ReserveDown();
|
||||
MTime.ReserveDown();
|
||||
StartPos.ReserveDown();
|
||||
IsAnti.ReserveDown();
|
||||
|
||||
/*
|
||||
IsAux.ReserveDown();
|
||||
*/
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (
|
||||
PackSizes.IsEmpty() &&
|
||||
NumUnpackStreamsVector.IsEmpty() &&
|
||||
Folders.IsEmpty() &&
|
||||
Files.IsEmpty());
|
||||
}
|
||||
|
||||
bool CheckNumFiles() const
|
||||
{
|
||||
unsigned size = Files.Size();
|
||||
return (
|
||||
CTime.CheckSize(size) &&
|
||||
ATime.CheckSize(size) &&
|
||||
MTime.CheckSize(size) &&
|
||||
StartPos.CheckSize(size) &&
|
||||
(size == IsAnti.Size() || IsAnti.Size() == 0));
|
||||
}
|
||||
|
||||
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
|
||||
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
|
||||
|
||||
void SetItem_Anti(unsigned index, bool isAnti)
|
||||
{
|
||||
while (index >= IsAnti.Size())
|
||||
IsAnti.Add(false);
|
||||
IsAnti[index] = isAnti;
|
||||
}
|
||||
/*
|
||||
void SetItem_Aux(unsigned index, bool isAux)
|
||||
{
|
||||
while (index >= IsAux.Size())
|
||||
IsAux.Add(false);
|
||||
IsAux[index] = isAux;
|
||||
}
|
||||
*/
|
||||
|
||||
void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);
|
||||
};
|
||||
|
||||
class COutArchive
|
||||
{
|
||||
UInt64 _prefixHeaderPos;
|
||||
|
||||
HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); }
|
||||
|
||||
UInt64 GetPos() const;
|
||||
void WriteBytes(const void *data, size_t size);
|
||||
void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }
|
||||
void WriteByte(Byte b);
|
||||
void WriteUInt32(UInt32 value);
|
||||
void WriteUInt64(UInt64 value);
|
||||
void WriteNumber(UInt64 value);
|
||||
void WriteID(UInt64 value) { WriteNumber(value); }
|
||||
|
||||
void WriteFolder(const CFolder &folder);
|
||||
HRESULT WriteFileHeader(const CFileItem &itemInfo);
|
||||
void WriteBoolVector(const CBoolVector &boolVector);
|
||||
void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
|
||||
|
||||
void WriteHashDigests(const CUInt32DefVector &digests);
|
||||
|
||||
void WritePackInfo(
|
||||
UInt64 dataOffset,
|
||||
const CRecordVector<UInt64> &packSizes,
|
||||
const CUInt32DefVector &packCRCs);
|
||||
|
||||
void WriteUnpackInfo(
|
||||
const CObjectVector<CFolder> &folders,
|
||||
const COutFolders &outFolders);
|
||||
|
||||
void WriteSubStreamsInfo(
|
||||
const CObjectVector<CFolder> &folders,
|
||||
const COutFolders &outFolders,
|
||||
const CRecordVector<UInt64> &unpackSizes,
|
||||
const CUInt32DefVector &digests);
|
||||
|
||||
void SkipAlign(unsigned pos, unsigned alignSize);
|
||||
void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize);
|
||||
void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);
|
||||
|
||||
HRESULT EncodeStream(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CEncoder &encoder, const CByteBuffer &data,
|
||||
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders);
|
||||
void WriteHeader(
|
||||
const CArchiveDatabaseOut &db,
|
||||
// const CHeaderOptions &headerOptions,
|
||||
UInt64 &headerOffset);
|
||||
|
||||
bool _countMode;
|
||||
bool _writeToStream;
|
||||
size_t _countSize;
|
||||
UInt32 _crc;
|
||||
COutBuffer _outByte;
|
||||
CWriteBufferLoc _outByte2;
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
bool _endMarker;
|
||||
#endif
|
||||
|
||||
bool _useAlign;
|
||||
|
||||
HRESULT WriteSignature();
|
||||
#ifdef _7Z_VOL
|
||||
HRESULT WriteFinishSignature();
|
||||
#endif
|
||||
HRESULT WriteStartHeader(const CStartHeader &h);
|
||||
#ifdef _7Z_VOL
|
||||
HRESULT WriteFinishHeader(const CFinishHeader &h);
|
||||
#endif
|
||||
CMyComPtr<IOutStream> Stream;
|
||||
public:
|
||||
|
||||
COutArchive() { _outByte.Create(1 << 16); }
|
||||
CMyComPtr<ISequentialOutStream> SeqStream;
|
||||
HRESULT Create(ISequentialOutStream *stream, bool endMarker);
|
||||
void Close();
|
||||
HRESULT SkipPrefixArchiveHeader();
|
||||
HRESULT WriteDatabase(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CArchiveDatabaseOut &db,
|
||||
const CCompressionMethodMode *options,
|
||||
const CHeaderOptions &headerOptions);
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
|
||||
static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
174
CPP/7zip/Archive/7z/7zProperties.cpp
Normal file
174
CPP/7zip/Archive/7z/7zProperties.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
// 7zProperties.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "7zProperties.h"
|
||||
#include "7zHeader.h"
|
||||
#include "7zHandler.h"
|
||||
|
||||
// #define _MULTI_PACK
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CPropMap
|
||||
{
|
||||
UInt32 FilePropID;
|
||||
CStatProp StatProp;
|
||||
};
|
||||
|
||||
static const CPropMap kPropMap[] =
|
||||
{
|
||||
{ NID::kName, { NULL, kpidPath, VT_BSTR } },
|
||||
{ NID::kSize, { NULL, kpidSize, VT_UI8 } },
|
||||
{ NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },
|
||||
|
||||
#ifdef _MULTI_PACK
|
||||
{ 100, { "Pack0", kpidPackedSize0, VT_UI8 } },
|
||||
{ 101, { "Pack1", kpidPackedSize1, VT_UI8 } },
|
||||
{ 102, { "Pack2", kpidPackedSize2, VT_UI8 } },
|
||||
{ 103, { "Pack3", kpidPackedSize3, VT_UI8 } },
|
||||
{ 104, { "Pack4", kpidPackedSize4, VT_UI8 } },
|
||||
#endif
|
||||
|
||||
{ NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
|
||||
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
|
||||
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
|
||||
{ NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
|
||||
{ NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },
|
||||
|
||||
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
|
||||
|
||||
// { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } },
|
||||
{ NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }
|
||||
|
||||
#ifndef _SFX
|
||||
,
|
||||
{ 97, { NULL, kpidEncrypted, VT_BOOL } },
|
||||
{ 98, { NULL, kpidMethod, VT_BSTR } },
|
||||
{ 99, { NULL, kpidBlock, VT_UI4 } }
|
||||
#endif
|
||||
};
|
||||
|
||||
static void CopyOneItem(CRecordVector<UInt64> &src,
|
||||
CRecordVector<UInt64> &dest, UInt32 item)
|
||||
{
|
||||
FOR_VECTOR (i, src)
|
||||
if (src[i] == item)
|
||||
{
|
||||
dest.Add(item);
|
||||
src.Delete(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
|
||||
{
|
||||
FOR_VECTOR (i, src)
|
||||
if (src[i] == item)
|
||||
{
|
||||
src.Delete(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
|
||||
{
|
||||
FOR_VECTOR (i, dest)
|
||||
if (dest[i] == item)
|
||||
{
|
||||
dest.Delete(i);
|
||||
break;
|
||||
}
|
||||
dest.Insert(0, item);
|
||||
}
|
||||
|
||||
#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id);
|
||||
|
||||
void CHandler::FillPopIDs()
|
||||
{
|
||||
_fileInfoPopIDs.Clear();
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
if (_volumes.Size() < 1)
|
||||
return;
|
||||
const CVolume &volume = _volumes.Front();
|
||||
const CArchiveDatabaseEx &_db = volume.Database;
|
||||
#endif
|
||||
|
||||
CRecordVector<UInt64> fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs;
|
||||
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
|
||||
/*
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kParent);
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kNtSecure);
|
||||
*/
|
||||
|
||||
COPY_ONE_ITEM(kName);
|
||||
COPY_ONE_ITEM(kAnti);
|
||||
COPY_ONE_ITEM(kSize);
|
||||
COPY_ONE_ITEM(kPackInfo);
|
||||
COPY_ONE_ITEM(kCTime);
|
||||
COPY_ONE_ITEM(kMTime);
|
||||
COPY_ONE_ITEM(kATime);
|
||||
COPY_ONE_ITEM(kWinAttrib);
|
||||
COPY_ONE_ITEM(kCRC);
|
||||
COPY_ONE_ITEM(kComment);
|
||||
|
||||
_fileInfoPopIDs += fileInfoPopIDs;
|
||||
|
||||
#ifndef _SFX
|
||||
_fileInfoPopIDs.Add(97);
|
||||
_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::kMTime);
|
||||
InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
|
||||
InsertToHead(_fileInfoPopIDs, NID::kSize);
|
||||
InsertToHead(_fileInfoPopIDs, NID::kName);
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
|
||||
{
|
||||
*numProps = _fileInfoPopIDs.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
{
|
||||
if (index >= _fileInfoPopIDs.Size())
|
||||
return E_INVALIDARG;
|
||||
UInt64 id = _fileInfoPopIDs[index];
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)
|
||||
{
|
||||
const CPropMap &pr = kPropMap[i];
|
||||
if (pr.FilePropID == id)
|
||||
{
|
||||
const CStatProp &st = pr.StatProp;
|
||||
*propID = st.PropID;
|
||||
*varType = st.vt;
|
||||
/*
|
||||
if (st.lpwstrName)
|
||||
*name = ::SysAllocString(st.lpwstrName);
|
||||
else
|
||||
*/
|
||||
*name = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
}}
|
||||
22
CPP/7zip/Archive/7z/7zProperties.h
Normal file
22
CPP/7zip/Archive/7z/7zProperties.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// 7zProperties.h
|
||||
|
||||
#ifndef __7Z_PROPERTIES_H
|
||||
#define __7Z_PROPERTIES_H
|
||||
|
||||
#include "../../PropID.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
enum
|
||||
{
|
||||
kpidPackedSize0 = kpidUserDefined,
|
||||
kpidPackedSize1,
|
||||
kpidPackedSize2,
|
||||
kpidPackedSize3,
|
||||
kpidPackedSize4
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
21
CPP/7zip/Archive/7z/7zRegister.cpp
Normal file
21
CPP/7zip/Archive/7z/7zRegister.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// 7zRegister.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "7zHandler.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
|
||||
REGISTER_ARC_IO_DECREMENT_SIG(
|
||||
"7z", "7z", NULL, 7,
|
||||
k_Signature_Dec,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
NULL);
|
||||
|
||||
}}
|
||||
22
CPP/7zip/Archive/7z/7zSpecStream.cpp
Normal file
22
CPP/7zip/Archive/7z/7zSpecStream.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// 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)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
if (!_getSubStreamSize)
|
||||
return E_NOTIMPL;
|
||||
return _getSubStreamSize->GetSubStreamSize(subStream, value);
|
||||
}
|
||||
35
CPP/7zip/Archive/7z/7zSpecStream.h
Normal file
35
CPP/7zip/Archive/7z/7zSpecStream.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// 7zSpecStream.h
|
||||
|
||||
#ifndef __7Z_SPEC_STREAM_H
|
||||
#define __7Z_SPEC_STREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
class CSequentialInStreamSizeCount2:
|
||||
public ISequentialInStream,
|
||||
public ICompressGetSubStreamSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void Init(ISequentialInStream *stream)
|
||||
{
|
||||
_size = 0;
|
||||
_getSubStreamSize.Release();
|
||||
_stream = stream;
|
||||
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
|
||||
}
|
||||
UInt64 GetSize() const { return _size; }
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
|
||||
};
|
||||
|
||||
#endif
|
||||
2469
CPP/7zip/Archive/7z/7zUpdate.cpp
Normal file
2469
CPP/7zip/Archive/7z/7zUpdate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
139
CPP/7zip/Archive/7z/7zUpdate.h
Normal file
139
CPP/7zip/Archive/7z/7zUpdate.h
Normal file
@@ -0,0 +1,139 @@
|
||||
// 7zUpdate.h
|
||||
|
||||
#ifndef __7Z_UPDATE_H
|
||||
#define __7Z_UPDATE_H
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
// #include "../../Common/UniqBlocks.h"
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zIn.h"
|
||||
#include "7zOut.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
/*
|
||||
struct CTreeFolder
|
||||
{
|
||||
UString Name;
|
||||
int Parent;
|
||||
CIntVector SubFolders;
|
||||
int UpdateItemIndex;
|
||||
int SortIndex;
|
||||
int SortIndexEnd;
|
||||
|
||||
CTreeFolder(): UpdateItemIndex(-1) {}
|
||||
};
|
||||
*/
|
||||
|
||||
struct CUpdateItem
|
||||
{
|
||||
int IndexInArchive;
|
||||
int IndexInClient;
|
||||
|
||||
UInt64 CTime;
|
||||
UInt64 ATime;
|
||||
UInt64 MTime;
|
||||
|
||||
UInt64 Size;
|
||||
UString Name;
|
||||
/*
|
||||
bool IsAltStream;
|
||||
int ParentFolderIndex;
|
||||
int TreeFolderIndex;
|
||||
*/
|
||||
|
||||
// that code is not used in 9.26
|
||||
// int ParentSortIndex;
|
||||
// int ParentSortIndexEnd;
|
||||
|
||||
UInt32 Attrib;
|
||||
|
||||
bool NewData;
|
||||
bool NewProps;
|
||||
|
||||
bool IsAnti;
|
||||
bool IsDir;
|
||||
|
||||
bool AttribDefined;
|
||||
bool CTimeDefined;
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
|
||||
// int SecureIndex; // 0 means (no_security)
|
||||
|
||||
bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }
|
||||
// bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes
|
||||
|
||||
CUpdateItem():
|
||||
// ParentSortIndex(-1),
|
||||
// IsAltStream(false),
|
||||
IsAnti(false),
|
||||
IsDir(false),
|
||||
AttribDefined(false),
|
||||
CTimeDefined(false),
|
||||
ATimeDefined(false),
|
||||
MTimeDefined(false)
|
||||
// SecureIndex(0)
|
||||
{}
|
||||
void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }
|
||||
|
||||
// unsigned GetExtensionPos() const;
|
||||
// UString GetExtension() const;
|
||||
};
|
||||
|
||||
struct CUpdateOptions
|
||||
{
|
||||
const CCompressionMethodMode *Method;
|
||||
const CCompressionMethodMode *HeaderMethod;
|
||||
bool UseFilters; // use additional filters for some files
|
||||
bool MaxFilter; // use BCJ2 filter instead of BCJ
|
||||
int AnalysisLevel;
|
||||
|
||||
CHeaderOptions HeaderOptions;
|
||||
|
||||
UInt64 NumSolidFiles;
|
||||
UInt64 NumSolidBytes;
|
||||
bool SolidExtension;
|
||||
|
||||
bool UseTypeSorting;
|
||||
|
||||
bool RemoveSfxBlock;
|
||||
bool MultiThreadMixer;
|
||||
|
||||
CUpdateOptions():
|
||||
Method(NULL),
|
||||
HeaderMethod(NULL),
|
||||
UseFilters(false),
|
||||
MaxFilter(false),
|
||||
AnalysisLevel(-1),
|
||||
NumSolidFiles((UInt64)(Int64)(-1)),
|
||||
NumSolidBytes((UInt64)(Int64)(-1)),
|
||||
SolidExtension(false),
|
||||
UseTypeSorting(true),
|
||||
RemoveSfxBlock(false),
|
||||
MultiThreadMixer(true)
|
||||
{}
|
||||
};
|
||||
|
||||
HRESULT Update(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
const CDbEx *db,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
// const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root
|
||||
// const CUniqBlocks &secureBlocks,
|
||||
COutArchive &archive,
|
||||
CArchiveDatabaseOut &newDatabase,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
const CUpdateOptions &options
|
||||
#ifndef _NO_CRYPTO
|
||||
, ICryptoGetTextPassword *getDecoderPassword
|
||||
#endif
|
||||
);
|
||||
}}
|
||||
|
||||
#endif
|
||||
3
CPP/7zip/Archive/7z/StdAfx.cpp
Normal file
3
CPP/7zip/Archive/7z/StdAfx.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
8
CPP/7zip/Archive/7z/StdAfx.h
Normal file
8
CPP/7zip/Archive/7z/StdAfx.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
81
CPP/7zip/Archive/7z/makefile
Normal file
81
CPP/7zip/Archive/7z/makefile
Normal file
@@ -0,0 +1,81 @@
|
||||
PROG = 7z.dll
|
||||
DEF_FILE = ../Archive.def
|
||||
CFLAGS = $(CFLAGS) \
|
||||
-DEXTERNAL_CODECS \
|
||||
|
||||
AR_OBJS = \
|
||||
$O\ArchiveExports.obj \
|
||||
$O\DllExports.obj \
|
||||
|
||||
7Z_OBJS = \
|
||||
$O\7zCompressionMode.obj \
|
||||
$O\7zDecode.obj \
|
||||
$O\7zEncode.obj \
|
||||
$O\7zExtract.obj \
|
||||
$O\7zFolderInStream.obj \
|
||||
$O\7zHandler.obj \
|
||||
$O\7zHandlerOut.obj \
|
||||
$O\7zHeader.obj \
|
||||
$O\7zIn.obj \
|
||||
$O\7zOut.obj \
|
||||
$O\7zProperties.obj \
|
||||
$O\7zSpecStream.obj \
|
||||
$O\7zUpdate.obj \
|
||||
$O\7zRegister.obj \
|
||||
|
||||
COMMON_OBJS = \
|
||||
$O\CRC.obj \
|
||||
$O\IntToString.obj \
|
||||
$O\NewHandler.obj \
|
||||
$O\MyString.obj \
|
||||
$O\StringConvert.obj \
|
||||
$O\StringToInt.obj \
|
||||
$O\MyVector.obj \
|
||||
$O\Wildcard.obj \
|
||||
|
||||
WIN_OBJS = \
|
||||
$O\DLL.obj \
|
||||
$O\FileDir.obj \
|
||||
$O\FileFind.obj \
|
||||
$O\FileIO.obj \
|
||||
$O\FileName.obj \
|
||||
$O\PropVariant.obj \
|
||||
$O\Synchronization.obj \
|
||||
$O\System.obj \
|
||||
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\CreateCoder.obj \
|
||||
$O\InOutTempBuffer.obj \
|
||||
$O\FilterCoder.obj \
|
||||
$O\LimitedStreams.obj \
|
||||
$O\LockedStream.obj \
|
||||
$O\MethodId.obj \
|
||||
$O\MethodProps.obj \
|
||||
$O\OutBuffer.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\PropId.obj \
|
||||
$O\StreamBinder.obj \
|
||||
$O\StreamObjects.obj \
|
||||
$O\StreamUtils.obj \
|
||||
$O\VirtThread.obj \
|
||||
|
||||
COMPRESS_OBJS = \
|
||||
$O\CopyCoder.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\CoderMixer2.obj \
|
||||
$O\HandlerOut.obj \
|
||||
$O\InStreamWithCRC.obj \
|
||||
$O\ItemNameUtils.obj \
|
||||
$O\MultiStream.obj \
|
||||
$O\OutStreamWithCRC.obj \
|
||||
$O\ParseProperties.obj \
|
||||
|
||||
C_OBJS = \
|
||||
$O\Alloc.obj \
|
||||
$O\CpuArch.obj \
|
||||
$O\Threads.obj \
|
||||
|
||||
!include "../../Crc.mak"
|
||||
|
||||
!include "../../7zip.mak"
|
||||
11
CPP/7zip/Archive/7z/resource.rc
Normal file
11
CPP/7zip/Archive/7z/resource.rc
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "../../MyVersionInfo.rc"
|
||||
|
||||
MY_VERSION_INFO_DLL("7z Plugin", "7z")
|
||||
|
||||
0 ICON "../Icons/7z.ico"
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
100 "7z:0"
|
||||
END
|
||||
|
||||
Reference in New Issue
Block a user