chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
OBJS = \
|
||||
$O\StdAfx.obj \
|
||||
$(CURRENT_OBJS) \
|
||||
$(COMMON_OBJS) \
|
||||
$(WIN_OBJS) \
|
||||
$(WIN_CTRL_OBJS) \
|
||||
$(7ZIP_COMMON_OBJS) \
|
||||
$(UI_COMMON_OBJS) \
|
||||
$(AGENT_OBJS) \
|
||||
$(CONSOLE_OBJS) \
|
||||
$(EXPLORER_OBJS) \
|
||||
$(FM_OBJS) \
|
||||
$(GUI_OBJS) \
|
||||
$(AR_COMMON_OBJS) \
|
||||
$(AR_OBJS) \
|
||||
$(7Z_OBJS) \
|
||||
$(CAB_OBJS) \
|
||||
$(CHM_OBJS) \
|
||||
$(COM_OBJS) \
|
||||
$(ISO_OBJS) \
|
||||
$(NSIS_OBJS) \
|
||||
$(RAR_OBJS) \
|
||||
$(TAR_OBJS) \
|
||||
$(UDF_OBJS) \
|
||||
$(WIM_OBJS) \
|
||||
$(ZIP_OBJS) \
|
||||
$(COMPRESS_OBJS) \
|
||||
$(CRYPTO_OBJS) \
|
||||
$(C_OBJS) \
|
||||
$(ASM_OBJS) \
|
||||
$O\resource.res \
|
||||
|
||||
!include "../../../Build.mak"
|
||||
|
||||
# MAK_SINGLE_FILE = 1
|
||||
|
||||
!IFDEF MAK_SINGLE_FILE
|
||||
|
||||
!IFDEF CURRENT_OBJS
|
||||
$(CURRENT_OBJS): ./$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
|
||||
!IFDEF COMMON_OBJS
|
||||
$(COMMON_OBJS): ../../../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF WIN_OBJS
|
||||
$(WIN_OBJS): ../../../Windows/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF WIN_CTRL_OBJS
|
||||
$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF 7ZIP_COMMON_OBJS
|
||||
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF AR_OBJS
|
||||
$(AR_OBJS): ../../Archive/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF AR_COMMON_OBJS
|
||||
$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF 7Z_OBJS
|
||||
$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF CAB_OBJS
|
||||
$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF CHM_OBJS
|
||||
$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF COM_OBJS
|
||||
$(COM_OBJS): ../../Archive/Com/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF ISO_OBJS
|
||||
$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF NSIS_OBJS
|
||||
$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF RAR_OBJS
|
||||
$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF TAR_OBJS
|
||||
$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF UDF_OBJS
|
||||
$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF WIM_OBJS
|
||||
$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF ZIP_OBJS
|
||||
$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
|
||||
$(COMPL) $(ZIP_FLAGS)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF COMPRESS_OBJS
|
||||
$(COMPRESS_OBJS): ../../Compress/$(*B).cpp
|
||||
$(COMPL_O2)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF CRYPTO_OBJS
|
||||
$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp
|
||||
$(COMPL_O2)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF UI_COMMON_OBJS
|
||||
$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF AGENT_OBJS
|
||||
$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF CONSOLE_OBJS
|
||||
$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp
|
||||
$(COMPL) $(CONSOLE_VARIANT_FLAGS)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF EXPLORER_OBJS
|
||||
$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF FM_OBJS
|
||||
$(FM_OBJS): ../../UI/FileManager/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF GUI_OBJS
|
||||
$(GUI_OBJS): ../../UI/GUI/$(*B).cpp
|
||||
$(COMPL)
|
||||
!ENDIF
|
||||
|
||||
!IFDEF C_OBJS
|
||||
$(C_OBJS): ../../../../C/$(*B).c
|
||||
$(COMPL_O2)
|
||||
!ENDIF
|
||||
|
||||
|
||||
!ELSE
|
||||
|
||||
{.}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../../Common}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../../Windows}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../../Windows/Control}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Common}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
|
||||
{../../UI/Common}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../UI/Agent}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../UI/Console}.cpp{$O}.obj::
|
||||
$(COMPLB) $(CONSOLE_VARIANT_FLAGS)
|
||||
{../../UI/Explorer}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../UI/FileManager}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../UI/GUI}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
|
||||
|
||||
{../../Archive}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Common}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
|
||||
{../../Archive/7z}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Cab}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Chm}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Com}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Iso}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Nsis}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Rar}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Tar}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Udf}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Wim}.cpp{$O}.obj::
|
||||
$(COMPLB)
|
||||
{../../Archive/Zip}.cpp{$O}.obj::
|
||||
$(COMPLB) $(ZIP_FLAGS)
|
||||
|
||||
{../../Compress}.cpp{$O}.obj::
|
||||
$(COMPLB_O2)
|
||||
{../../Crypto}.cpp{$O}.obj::
|
||||
$(COMPLB_O2)
|
||||
{../../../../C}.c{$O}.obj::
|
||||
$(CCOMPLB)
|
||||
|
||||
!ENDIF
|
||||
|
||||
!include "Asm.mak"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
C_OBJS = $(C_OBJS) \
|
||||
$O\Aes.obj
|
||||
|
||||
!IF defined(USE_C_AES) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64"
|
||||
C_OBJS = $(C_OBJS) \
|
||||
$O\AesOpt.obj
|
||||
!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64"
|
||||
ASM_OBJS = $(ASM_OBJS) \
|
||||
$O\AesOpt.obj
|
||||
!ENDIF
|
||||
@@ -0,0 +1,638 @@
|
||||
# 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 "Z7_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:\Util\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 "Z7_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:\Util\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=..\..\Compress\CodecExports.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\DllExports2.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\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
|
||||
@@ -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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// CompressionMethod.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,92 @@
|
||||
// 7zCompressionMode.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_COMPRESSION_MODE_H
|
||||
#define ZIP7_INC_7Z_COMPRESSION_MODE_H
|
||||
|
||||
#include "../../Common/MethodId.h"
|
||||
#include "../../Common/MethodProps.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CMethodFull: public CMethodProps
|
||||
{
|
||||
CMethodId Id;
|
||||
UInt32 NumStreams;
|
||||
int CodecIndex;
|
||||
UInt32 NumThreads;
|
||||
bool Set_NumThreads;
|
||||
|
||||
CMethodFull(): CodecIndex(-1), NumThreads(1), Set_NumThreads(false) {}
|
||||
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;
|
||||
bool PasswordIsDefined;
|
||||
bool MemoryUsageLimit_WasSet;
|
||||
|
||||
#ifndef Z7_ST
|
||||
bool NumThreads_WasForced;
|
||||
bool MultiThreadMixer;
|
||||
UInt32 NumThreads;
|
||||
UInt32 NumThreadGroups;
|
||||
#endif
|
||||
|
||||
UString Password; // _Wipe
|
||||
UInt64 MemoryUsageLimit;
|
||||
|
||||
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
|
||||
CCompressionMethodMode():
|
||||
DefaultMethod_was_Inserted(false)
|
||||
, Filter_was_Inserted(false)
|
||||
, PasswordIsDefined(false)
|
||||
, MemoryUsageLimit_WasSet(false)
|
||||
#ifndef Z7_ST
|
||||
, NumThreads_WasForced(false)
|
||||
, MultiThreadMixer(true)
|
||||
, NumThreads(1)
|
||||
, NumThreadGroups(0)
|
||||
#endif
|
||||
, MemoryUsageLimit((UInt64)1 << 30)
|
||||
{}
|
||||
|
||||
#ifdef Z7_CPP_IS_SUPPORTED_default
|
||||
CCompressionMethodMode(const CCompressionMethodMode &) = default;
|
||||
CCompressionMethodMode& operator =(const CCompressionMethodMode &) = default;
|
||||
#endif
|
||||
~CCompressionMethodMode() { Password.Wipe_and_Empty(); }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,599 @@
|
||||
// 7zDecode.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "7zDecode.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CDecProgress
|
||||
, ICompressProgressInfo
|
||||
)
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
public:
|
||||
CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF(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)
|
||||
{
|
||||
#if defined(USE_MIXER_ST) && defined(USE_MIXER_MT)
|
||||
_useMixerMT = useMixerMT;
|
||||
#else
|
||||
UNUSED_VAR(useMixerMT)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Z7_CLASS_IMP_COM_0(
|
||||
CLockedInStream
|
||||
)
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Pos;
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CLockedSequentialInStreamMT
|
||||
, ISequentialInStream
|
||||
)
|
||||
CLockedInStream *_glob;
|
||||
UInt64 _pos;
|
||||
CMyComPtr<IUnknown> _globRef;
|
||||
public:
|
||||
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
|
||||
{
|
||||
_globRef = lockedInStream;
|
||||
_glob = lockedInStream;
|
||||
_pos = startPos;
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF(CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
|
||||
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(InStream_SeekSet(_glob->Stream, _pos))
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
UInt32 realProcessedSize = 0;
|
||||
const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
|
||||
_pos += realProcessedSize;
|
||||
_glob->Pos = _pos;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CLockedSequentialInStreamST
|
||||
, ISequentialInStream
|
||||
)
|
||||
CLockedInStream *_glob;
|
||||
UInt64 _pos;
|
||||
CMyComPtr<IUnknown> _globRef;
|
||||
public:
|
||||
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
|
||||
{
|
||||
_globRef = lockedInStream;
|
||||
_glob = lockedInStream;
|
||||
_pos = startPos;
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF(CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(InStream_SeekSet(_glob->Stream, _pos))
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
UInt32 realProcessedSize = 0;
|
||||
const 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
|
||||
|
||||
, bool &dataAfterEnd_Error
|
||||
|
||||
Z7_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(Z7_ST)
|
||||
, bool mtMode, UInt32 numThreads, UInt64 memUsage
|
||||
#endif
|
||||
)
|
||||
{
|
||||
dataAfterEnd_Error = false;
|
||||
|
||||
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 Z7_NO_CRYPTO
|
||||
isEncrypted = false;
|
||||
passwordIsDefined = false;
|
||||
#endif
|
||||
*/
|
||||
|
||||
if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
|
||||
{
|
||||
_bindInfoPrev_Defined = false;
|
||||
_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 Z7_SFX
|
||||
// we don't support RAR codecs here
|
||||
if ((coderInfo.MethodID >> 8) == 0x403)
|
||||
return E_NOTIMPL;
|
||||
#endif
|
||||
|
||||
CCreatedCoder cod;
|
||||
RINOK(CreateCoder_Id(
|
||||
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 Z7_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;
|
||||
}
|
||||
|
||||
RINOK(_mixer->ReInit2())
|
||||
|
||||
UInt32 packStreamIndex = 0;
|
||||
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
|
||||
|
||||
unsigned i;
|
||||
|
||||
#if !defined(Z7_ST)
|
||||
bool mt_wasUsed = false;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < folderInfo.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
|
||||
|
||||
// now there is no codec that uses another external codec
|
||||
/*
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(ISetCompressCodecsInfo,
|
||||
setCompressCodecsInfo, decoder)
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
// we must use g_ExternalCodecs also
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if !defined(Z7_ST)
|
||||
if (!mt_wasUsed)
|
||||
{
|
||||
if (mtMode)
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(ICompressSetCoderMt,
|
||||
setCoderMt, decoder)
|
||||
if (setCoderMt)
|
||||
{
|
||||
mt_wasUsed = true;
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads))
|
||||
}
|
||||
}
|
||||
// if (memUsage != 0)
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(ICompressSetMemLimit,
|
||||
setMemLimit, decoder)
|
||||
if (setMemLimit)
|
||||
{
|
||||
mt_wasUsed = true;
|
||||
RINOK(setMemLimit->SetMemLimit(memUsage))
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICompressSetDecoderProperties2,
|
||||
setDecoderProperties, decoder)
|
||||
const CByteBuffer &props = coderInfo.Props;
|
||||
const UInt32 size32 = (UInt32)props.Size();
|
||||
if (props.Size() != size32)
|
||||
return E_NOTIMPL;
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32);
|
||||
if (res == E_INVALIDARG)
|
||||
res = E_NOTIMPL;
|
||||
RINOK(res)
|
||||
}
|
||||
else if (size32 != 0)
|
||||
{
|
||||
// v23: we fail, if decoder doesn't support properties
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICryptoSetPassword,
|
||||
cryptoSetPassword, decoder)
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
isEncrypted = true;
|
||||
if (!getTextPassword)
|
||||
return E_NOTIMPL;
|
||||
CMyComBSTR_Wipe passwordBSTR;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR))
|
||||
passwordIsDefined = true;
|
||||
password.Wipe_and_Empty();
|
||||
size_t len = 0;
|
||||
if (passwordBSTR)
|
||||
{
|
||||
password = passwordBSTR;
|
||||
len = password.Len();
|
||||
}
|
||||
CByteBuffer_Wipe buffer(len * 2);
|
||||
const LPCOLESTR psw = passwordBSTR;
|
||||
for (size_t k = 0; k < len; k++)
|
||||
{
|
||||
const wchar_t c = psw[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
|
||||
|
||||
bool finishMode = false;
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICompressSetFinishMode,
|
||||
setFinishMode, decoder)
|
||||
if (setFinishMode)
|
||||
{
|
||||
finishMode = fullUnpack;
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode)))
|
||||
}
|
||||
}
|
||||
|
||||
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, finishMode);
|
||||
}
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
_mixer->SelectMainCoder(!fullUnpack);
|
||||
}
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
|
||||
|
||||
CMyComPtr2_Create<IUnknown, CLockedInStream> lockedInStream;
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
bool needMtLock = _useMixerMT;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (folderInfo.PackStreams.Size() > 1)
|
||||
{
|
||||
// lockedInStream.Pos = (UInt64)(Int64)-1;
|
||||
// RINOK(InStream_GetPos(inStream, lockedInStream.Pos))
|
||||
RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos))
|
||||
lockedInStream->Stream = inStream;
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
/*
|
||||
For ST-mixer mode:
|
||||
If parallel input stream reading from pack streams is possible,
|
||||
we must use MT-lock for packed streams.
|
||||
Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode.
|
||||
So we force to needMtLock mode only if there is unknown (external) decoder.
|
||||
*/
|
||||
if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
|
||||
needMtLock = true;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> packStream;
|
||||
const UInt64 packPos = startPos + packPositions[j];
|
||||
|
||||
if (folderInfo.PackStreams.Size() == 1)
|
||||
{
|
||||
RINOK(InStream_SeekSet(inStream, packPos))
|
||||
packStream = inStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (needMtLock)
|
||||
#endif
|
||||
{
|
||||
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
|
||||
packStream = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
|
||||
}
|
||||
#ifdef USE_MIXER_ST
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_MIXER_ST
|
||||
CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
|
||||
packStream = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
inStreams.AddNew() = streamSpec;
|
||||
streamSpec->SetStream(packStream);
|
||||
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
|
||||
}
|
||||
|
||||
const 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,
|
||||
dataAfterEnd_Error);
|
||||
}
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
|
||||
#else
|
||||
return E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 7zDecode.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_DECODE_H
|
||||
#define ZIP7_INC_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;
|
||||
#ifdef USE_MIXER_ST
|
||||
#ifdef USE_MIXER_MT
|
||||
bool _useMixerMT;
|
||||
#endif
|
||||
#endif
|
||||
CBindInfoEx _bindInfoPrev;
|
||||
|
||||
#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
|
||||
, bool &dataAfterEnd_Error
|
||||
|
||||
Z7_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(Z7_ST)
|
||||
, bool mtMode, UInt32 numThreads, UInt64 memUsage
|
||||
#endif
|
||||
);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,721 @@
|
||||
// 7zEncode.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.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)
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICompressSetCoderProperties,
|
||||
setCoderProperties, coder)
|
||||
if (setCoderProperties)
|
||||
return props.SetCoderProps(setCoderProperties, dataSizeReduce);
|
||||
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
|
||||
{
|
||||
_progress = progress;
|
||||
OutSize = 0;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
|
||||
{
|
||||
UInt64 outSize2;
|
||||
{
|
||||
#ifndef Z7_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;
|
||||
|
||||
if (methodFull.CodecIndex >= 0)
|
||||
{
|
||||
RINOK(CreateCoder_Index(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
(unsigned)methodFull.CodecIndex, true, cod))
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodFull.Id, true, cod))
|
||||
}
|
||||
|
||||
if (!cod.Coder && !cod.Coder2)
|
||||
{
|
||||
return E_NOTIMPL; // unsupported method, if encoder
|
||||
// return E_FAIL;
|
||||
}
|
||||
|
||||
if (cod.NumStreams != methodFull.NumStreams)
|
||||
return E_FAIL;
|
||||
|
||||
CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
|
||||
|
||||
#ifndef Z7_ST
|
||||
if (methodFull.Set_NumThreads)
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(
|
||||
/* _options.NumThreads */
|
||||
methodFull.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 Z7_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_Wipe 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CSequentialOutTempBufferImp2
|
||||
, ISequentialOutStream
|
||||
)
|
||||
public:
|
||||
CInOutTempBuffer TempBuffer;
|
||||
CMtEncMultiProgress *_mtProgressSpec;
|
||||
|
||||
CSequentialOutTempBufferImp2(): _mtProgressSpec(NULL) {}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF(CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (processed)
|
||||
*processed = 0;
|
||||
RINOK(TempBuffer.Write_HRESULT(data, size))
|
||||
if (processed)
|
||||
*processed = size;
|
||||
if (_mtProgressSpec)
|
||||
_mtProgressSpec->AddOutSize(size);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CSequentialOutMtNotify
|
||||
, ISequentialOutStream
|
||||
)
|
||||
public:
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
CMtEncMultiProgress *_mtProgressSpec;
|
||||
|
||||
CSequentialOutMtNotify(): _mtProgressSpec(NULL) {}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF(CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed))
|
||||
{
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT res = _stream->Write(data, size, &realProcessed);
|
||||
if (processed)
|
||||
*processed = realProcessed;
|
||||
if (_mtProgressSpec)
|
||||
_mtProgressSpec->AddOutSize(size);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICompressWriteCoderProperties,
|
||||
writeCoderProperties, coder)
|
||||
if (writeCoderProperties)
|
||||
{
|
||||
CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> outStreamSpec;
|
||||
outStreamSpec->Init();
|
||||
RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec))
|
||||
outStreamSpec->CopyToBuffer(props);
|
||||
}
|
||||
else
|
||||
props.Free();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CEncoder::Encode1(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream,
|
||||
// const UInt64 *inStreamSize,
|
||||
const UInt64 *inSizeForReduce,
|
||||
UInt64 expectedDataSize,
|
||||
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))
|
||||
}
|
||||
|
||||
RINOK(_mixer->ReInit2())
|
||||
|
||||
CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress;
|
||||
CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify;
|
||||
|
||||
CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
|
||||
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2();
|
||||
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
|
||||
tempBufferSpecs.Add(tempBufferSpec);
|
||||
tempBuffers.Add(tempBuffer);
|
||||
}
|
||||
|
||||
const unsigned numMethods = _bindInfo.Coders.Size();
|
||||
|
||||
for (i = 0; i < numMethods; i++)
|
||||
_mixer->SetCoderInfo(i, NULL, NULL, false);
|
||||
|
||||
|
||||
/* 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;
|
||||
ISequentialInStream *inStreamPointer = inStream;
|
||||
|
||||
CRecordVector<ISequentialOutStream *> outStreamPointers;
|
||||
|
||||
SetFolder(folderItem);
|
||||
|
||||
for (i = 0; i < numMethods; i++)
|
||||
{
|
||||
IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
|
||||
/*
|
||||
{
|
||||
CEncoder *sfEncoder = NULL;
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
IGetSfEncoderInternal,
|
||||
sf, coder)
|
||||
if (sf)
|
||||
{
|
||||
RINOK(sf->GetSfEncoder(&sfEncoder));
|
||||
if (!sfEncoder)
|
||||
return E_FAIL;
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ISetCompressCodecsInfo,
|
||||
setCompressCodecsInfo, coder)
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
// we must use g_ExternalCodecs also
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICryptoResetInitVector,
|
||||
resetInitVector, coder)
|
||||
if (resetInitVector)
|
||||
{
|
||||
RINOK(resetInitVector->ResetInitVector())
|
||||
}
|
||||
}
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICompressSetCoderPropertiesOpt,
|
||||
optProps, coder)
|
||||
if (optProps)
|
||||
{
|
||||
const PROPID propID = NCoderPropID::kExpectedDataSize;
|
||||
NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
|
||||
RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))
|
||||
}
|
||||
}
|
||||
// we must write properties from coder after ResetInitVector()
|
||||
RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
|
||||
}
|
||||
|
||||
_mixer->SelectMainCoder(false);
|
||||
const UInt32 mainCoder = _mixer->MainCoderIndex;
|
||||
|
||||
bool useMtProgress = false;
|
||||
if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
|
||||
{
|
||||
#ifdef Z7_ST
|
||||
if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
|
||||
#endif
|
||||
useMtProgress = true;
|
||||
}
|
||||
|
||||
if (useMtProgress)
|
||||
{
|
||||
mtProgress.SetFromCls(new CMtEncMultiProgress);
|
||||
mtProgress->Init(compressProgress);
|
||||
|
||||
mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify);
|
||||
mtOutStreamNotify->_stream = outStream;
|
||||
mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr();
|
||||
|
||||
FOR_VECTOR (t, tempBufferSpecs)
|
||||
{
|
||||
tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_bindInfo.PackStreams.Size() != 0)
|
||||
{
|
||||
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
outStreamSizeCount = outStreamSizeCountSpec;
|
||||
outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ?
|
||||
mtOutStreamNotify.Interface() : outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
outStreamPointers.Add(outStreamSizeCount);
|
||||
}
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
outStreamPointers.Add(tempBuffers[i - 1]);
|
||||
|
||||
bool dataAfterEnd_Error;
|
||||
|
||||
RINOK(_mixer->Code(
|
||||
&inStreamPointer,
|
||||
outStreamPointers.ConstData(),
|
||||
mtProgress.IsDefined() ? mtProgress.Interface() :
|
||||
compressProgress, dataAfterEnd_Error))
|
||||
|
||||
if (_bindInfo.PackStreams.Size() != 0)
|
||||
packSizes.Add(outStreamSizeCountSpec->GetSize());
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CInOutTempBuffer &iotb = tempBufferSpecs[i - 1]->TempBuffer;
|
||||
RINOK(iotb.WriteToStream(outStream))
|
||||
packSizes.Add(iotb.GetDataSize());
|
||||
}
|
||||
|
||||
/* Code() in some future codec can change properties.
|
||||
v23: so we fill properties again after Code() */
|
||||
for (i = 0; i < numMethods; i++)
|
||||
{
|
||||
IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
|
||||
RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CEncoder::Encode_Post(
|
||||
UInt64 unpackSize,
|
||||
CRecordVector<UInt64> &coderUnpackSizes)
|
||||
{
|
||||
// unpackSize = 0;
|
||||
for (unsigned i = 0; i < _bindInfo.Coders.Size(); i++)
|
||||
{
|
||||
const int bond = _bindInfo.FindBond_for_UnpackStream(DestOut_to_SrcIn[i]);
|
||||
UInt64 streamSize;
|
||||
if (bond < 0)
|
||||
{
|
||||
// streamSize = inStreamSizeCountSpec->GetSize();
|
||||
// unpackSize = streamSize;
|
||||
streamSize = unpackSize;
|
||||
}
|
||||
else
|
||||
streamSize = _mixer->GetBondStreamSize((unsigned)bond);
|
||||
coderUnpackSizes.Add(streamSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
const UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
|
||||
const int bond = _bindInfo.FindBond_for_PackStream(outIndex);
|
||||
if (bond >= 0)
|
||||
{
|
||||
ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
const int si = _bindInfo.FindStream_in_PackStreams(outIndex);
|
||||
if (si >= 0)
|
||||
_bindInfo.PackStreams.MoveToFront((unsigned)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() {}
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,95 @@
|
||||
// 7zEncode.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_ENCODE_H
|
||||
#define ZIP7_INC_7Z_ENCODE_H
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
|
||||
#include "../Common/CoderMixer2.h"
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CMtEncMultiProgress,
|
||||
ICompressProgressInfo
|
||||
)
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
#ifndef Z7_ST
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
#endif
|
||||
|
||||
public:
|
||||
UInt64 OutSize;
|
||||
|
||||
CMtEncMultiProgress(): OutSize(0) {}
|
||||
|
||||
void Init(ICompressProgressInfo *progress);
|
||||
|
||||
void AddOutSize(UInt64 addOutSize)
|
||||
{
|
||||
#ifndef Z7_ST
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
#endif
|
||||
OutSize += addOutSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CEncoder Z7_final MY_UNCOPYABLE
|
||||
{
|
||||
#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 Encode1(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream,
|
||||
// const UInt64 *inStreamSize,
|
||||
const UInt64 *inSizeForReduce,
|
||||
UInt64 expectedDataSize,
|
||||
CFolder &folderItem,
|
||||
// CRecordVector<UInt64> &coderUnpackSizes,
|
||||
// UInt64 &unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
CRecordVector<UInt64> &packSizes,
|
||||
ICompressProgressInfo *compressProgress);
|
||||
|
||||
void Encode_Post(
|
||||
UInt64 unpackSize,
|
||||
CRecordVector<UInt64> &coderUnpackSizes);
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,444 @@
|
||||
// 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 {
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CFolderOutStream
|
||||
, ISequentialOutStream
|
||||
/* , ICompressGetSubStreamSize */
|
||||
)
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
public:
|
||||
bool TestMode;
|
||||
bool CheckCrc;
|
||||
private:
|
||||
bool _fileIsOpen;
|
||||
bool _calcCrc;
|
||||
UInt32 _crc;
|
||||
UInt64 _rem;
|
||||
|
||||
const UInt32 *_indexes;
|
||||
// unsigned _startIndex;
|
||||
unsigned _numFiles;
|
||||
unsigned _fileIndex;
|
||||
|
||||
HRESULT OpenFile(bool isCorrupted = false);
|
||||
HRESULT CloseFile_and_SetResult(Int32 res);
|
||||
HRESULT CloseFile();
|
||||
HRESULT ProcessEmptyFiles();
|
||||
|
||||
public:
|
||||
const CDbEx *_db;
|
||||
CMyComPtr<IArchiveExtractCallback> ExtractCallback;
|
||||
|
||||
bool ExtraWriteWasCut;
|
||||
|
||||
CFolderOutStream():
|
||||
TestMode(false),
|
||||
CheckCrc(true)
|
||||
{}
|
||||
|
||||
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)
|
||||
{
|
||||
// _startIndex = startIndex;
|
||||
_fileIndex = startIndex;
|
||||
_indexes = indexes;
|
||||
_numFiles = numFiles;
|
||||
|
||||
_fileIsOpen = false;
|
||||
ExtraWriteWasCut = false;
|
||||
|
||||
return ProcessEmptyFiles();
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
|
||||
{
|
||||
const CFileItem &fi = _db->Files[_fileIndex];
|
||||
const 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;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(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);
|
||||
if (_calcCrc)
|
||||
{
|
||||
const UInt32 k_Step = (UInt32)1 << 20;
|
||||
if (cur > k_Step)
|
||||
cur = k_Step;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
Z7_COM7F_IMF(CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value))
|
||||
{
|
||||
*value = 0;
|
||||
// const unsigned numFiles_Original = _numFiles + _fileIndex - _startIndex;
|
||||
const unsigned numFiles_Original = _numFiles;
|
||||
if (subStream >= numFiles_Original)
|
||||
return S_FALSE; // E_FAIL;
|
||||
*value = _db->Files[_startIndex + (unsigned)subStream].Size;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec))
|
||||
{
|
||||
// for GCC
|
||||
// CFolderOutStream *folderOutStream = new CFolderOutStream;
|
||||
// CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
|
||||
|
||||
COM_TRY_BEGIN
|
||||
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
|
||||
|
||||
UInt64 importantTotalUnpacked = 0;
|
||||
|
||||
// numItems = (UInt32)(Int32)-1;
|
||||
|
||||
const 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++)
|
||||
{
|
||||
const UInt32 fileIndex = allFilesMode ? i : indices[i];
|
||||
const 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))
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
CDecoder decoder(
|
||||
#if !defined(USE_MIXER_MT)
|
||||
false
|
||||
#elif !defined(USE_MIXER_ST)
|
||||
true
|
||||
#elif !defined(Z7_7Z_SET_PROPERTIES)
|
||||
#ifdef Z7_ST
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
#else
|
||||
_useMultiThreadMixer
|
||||
#endif
|
||||
);
|
||||
|
||||
UInt64 curPacked, curUnpacked;
|
||||
|
||||
CMyComPtr<IArchiveExtractCallbackMessage2> callbackMessage;
|
||||
extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage2, &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];
|
||||
const 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++)
|
||||
{
|
||||
const 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;
|
||||
}
|
||||
|
||||
{
|
||||
const HRESULT result = folderOutStream->Init(fileIndex,
|
||||
allFilesMode ? NULL : indices + i,
|
||||
numSolidFiles);
|
||||
|
||||
i += numSolidFiles;
|
||||
|
||||
RINOK(result)
|
||||
}
|
||||
|
||||
if (folderOutStream->WasWritingFinished())
|
||||
{
|
||||
// for debug: to test zero size stream unpacking
|
||||
// if (folderIndex == kNumNoIndex) // enable this check for debug
|
||||
continue;
|
||||
}
|
||||
|
||||
if (folderIndex == kNumNoIndex)
|
||||
return E_FAIL;
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (extractCallback)
|
||||
extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
bool isEncrypted = false;
|
||||
bool passwordIsDefined = false;
|
||||
UString_Wipe password;
|
||||
#endif
|
||||
|
||||
bool dataAfterEnd_Error = false;
|
||||
|
||||
const HRESULT result = decoder.Decode(
|
||||
EXTERNAL_CODECS_VARS
|
||||
_inStream,
|
||||
_db.ArcInfo.DataStartPosition,
|
||||
_db, folderIndex,
|
||||
&curUnpacked,
|
||||
|
||||
outStream,
|
||||
lps,
|
||||
NULL // *inStreamMainRes
|
||||
, dataAfterEnd_Error
|
||||
|
||||
Z7_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(Z7_ST)
|
||||
, true, _numThreads, _memUsage_Decompress
|
||||
#endif
|
||||
);
|
||||
|
||||
if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error)
|
||||
{
|
||||
const bool wasFinished = folderOutStream->WasWritingFinished();
|
||||
|
||||
int resOp = NExtract::NOperationResult::kDataError;
|
||||
|
||||
if (result != S_FALSE)
|
||||
{
|
||||
if (result == E_NOTIMPL)
|
||||
resOp = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else if (wasFinished && dataAfterEnd_Error)
|
||||
resOp = NExtract::NOperationResult::kDataAfterEnd;
|
||||
}
|
||||
|
||||
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;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,264 @@
|
||||
// 7zFolderInStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "7zFolderInStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
|
||||
const UInt32 *indexes, unsigned numFiles)
|
||||
{
|
||||
_updateCallback = updateCallback;
|
||||
_indexes = indexes;
|
||||
_numFiles = numFiles;
|
||||
|
||||
_totalSize_for_Coder = 0;
|
||||
ClearFileInfo();
|
||||
|
||||
Processed.ClearAndReserve(numFiles);
|
||||
Sizes.ClearAndReserve(numFiles);
|
||||
CRCs.ClearAndReserve(numFiles);
|
||||
TimesDefined.ClearAndReserve(numFiles);
|
||||
MTimes.ClearAndReserve(Need_MTime ? numFiles : (unsigned)0);
|
||||
CTimes.ClearAndReserve(Need_CTime ? numFiles : (unsigned)0);
|
||||
ATimes.ClearAndReserve(Need_ATime ? numFiles : (unsigned)0);
|
||||
Attribs.ClearAndReserve(Need_Attrib ? numFiles : (unsigned)0);
|
||||
|
||||
// FolderCrc = CRC_INIT_VAL;
|
||||
_stream.Release();
|
||||
}
|
||||
|
||||
void CFolderInStream::ClearFileInfo()
|
||||
{
|
||||
_pos = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_size_Defined = false;
|
||||
_times_Defined = false;
|
||||
_size = 0;
|
||||
FILETIME_Clear(_mTime);
|
||||
FILETIME_Clear(_cTime);
|
||||
FILETIME_Clear(_aTime);
|
||||
_attrib = 0;
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::OpenStream()
|
||||
{
|
||||
while (Processed.Size() < _numFiles)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> stream;
|
||||
const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream);
|
||||
if (result != S_OK && result != S_FALSE)
|
||||
return result;
|
||||
|
||||
_stream = stream;
|
||||
|
||||
if (stream)
|
||||
{
|
||||
{
|
||||
CMyComPtr<IStreamGetProps> getProps;
|
||||
stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps);
|
||||
if (getProps)
|
||||
{
|
||||
// access could be changed in first myx pass
|
||||
if (getProps->GetProps(&_size,
|
||||
Need_CTime ? &_cTime : NULL,
|
||||
Need_ATime ? &_aTime : NULL,
|
||||
Need_MTime ? &_mTime : NULL,
|
||||
Need_Attrib ? &_attrib : NULL)
|
||||
== S_OK)
|
||||
{
|
||||
_size_Defined = true;
|
||||
_times_Defined = true;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
{
|
||||
CMyComPtr<IStreamGetSize> streamGetSize;
|
||||
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
|
||||
if (streamGetSize)
|
||||
{
|
||||
if (streamGetSize->GetSize(&_size) == S_OK)
|
||||
_size_Defined = true;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(AddFileInfo(result == S_OK))
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void AddFt(CRecordVector<UInt64> &vec, const FILETIME &ft)
|
||||
{
|
||||
vec.AddInReserved(FILETIME_To_UInt64(ft));
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp,
|
||||
UInt32 index, UInt64 size, const UInt32 *crc)
|
||||
{
|
||||
PROPVARIANT prop;
|
||||
prop.vt = VT_EMPTY;
|
||||
prop.wReserved1 = 0;
|
||||
|
||||
NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size);
|
||||
RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop));
|
||||
if (crc)
|
||||
{
|
||||
NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc);
|
||||
RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop));
|
||||
}
|
||||
return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK);
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CFolderInStream::AddFileInfo(bool isProcessed)
|
||||
{
|
||||
// const UInt32 index = _indexes[Processed.Size()];
|
||||
Processed.AddInReserved(isProcessed);
|
||||
Sizes.AddInReserved(_pos);
|
||||
CRCs.AddInReserved(CRC_GET_DIGEST(_crc));
|
||||
if (Need_Attrib) Attribs.AddInReserved(_attrib);
|
||||
TimesDefined.AddInReserved(_times_Defined);
|
||||
if (Need_MTime) AddFt(MTimes, _mTime);
|
||||
if (Need_CTime) AddFt(CTimes, _cTime);
|
||||
if (Need_ATime) AddFt(ATimes, _aTime);
|
||||
ClearFileInfo();
|
||||
/*
|
||||
if (isProcessed && _reportArcProp)
|
||||
RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc))
|
||||
*/
|
||||
return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
if (_stream)
|
||||
{
|
||||
/*
|
||||
if (_pos == 0)
|
||||
{
|
||||
const UInt32 align = (UInt32)1 << AlignLog;
|
||||
const UInt32 offset = (UInt32)_totalSize_for_Coder & (align - 1);
|
||||
if (offset != 0)
|
||||
{
|
||||
UInt32 cur = align - offset;
|
||||
if (cur > size)
|
||||
cur = size;
|
||||
memset(data, 0, cur);
|
||||
data = (Byte *)data + cur;
|
||||
size -= cur;
|
||||
// _pos += cur; // for debug
|
||||
_totalSize_for_Coder += cur;
|
||||
if (processedSize)
|
||||
*processedSize += cur;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
UInt32 cur = size;
|
||||
const UInt32 kMax = (UInt32)1 << 20;
|
||||
if (cur > kMax)
|
||||
cur = kMax;
|
||||
RINOK(_stream->Read(data, cur, &cur))
|
||||
if (cur != 0)
|
||||
{
|
||||
// if (Need_Crc)
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
/*
|
||||
if (FolderCrc)
|
||||
FolderCrc = CrcUpdate(FolderCrc, data, cur);
|
||||
*/
|
||||
_pos += cur;
|
||||
_totalSize_for_Coder += cur;
|
||||
if (processedSize)
|
||||
*processedSize = cur; // use +=cur, if continue is possible in loop
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_stream.Release();
|
||||
RINOK(AddFileInfo(true))
|
||||
}
|
||||
|
||||
if (Processed.Size() >= _numFiles)
|
||||
break;
|
||||
RINOK(OpenStream())
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value))
|
||||
{
|
||||
*value = 0;
|
||||
if (subStream > Sizes.Size())
|
||||
return S_FALSE; // E_FAIL;
|
||||
|
||||
const 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
HRESULT CFolderInStream::CloseCrcStream()
|
||||
{
|
||||
if (!_crcStream)
|
||||
return S_OK;
|
||||
if (!_crcStream_Spec->WasFinished())
|
||||
return E_FAIL;
|
||||
_crc = _crcStream_Spec->GetCRC() ^ CRC_INIT_VAL; // change it
|
||||
const UInt64 size = _crcStream_Spec->GetSize();
|
||||
_pos = size;
|
||||
_totalSize_for_Coder += size;
|
||||
_crcStream.Release();
|
||||
// _crcStream->ReleaseStream();
|
||||
_stream.Release();
|
||||
return AddFileInfo(true);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CFolderInStream::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream)
|
||||
{
|
||||
RINOK(CloseCrcStream())
|
||||
*stream = NULL;
|
||||
*streamIndexRes = Processed.Size();
|
||||
if (Processed.Size() >= _numFiles)
|
||||
return S_OK;
|
||||
RINOK(OpenStream());
|
||||
if (!_stream)
|
||||
return S_OK;
|
||||
if (!_crcStream)
|
||||
{
|
||||
_crcStream_Spec = new CSequentialInStreamWithCRC;
|
||||
_crcStream = _crcStream_Spec;
|
||||
}
|
||||
_crcStream_Spec->Init();
|
||||
_crcStream_Spec->SetStream(_stream);
|
||||
*stream = _crcStream;
|
||||
_crcStream->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,101 @@
|
||||
// 7zFolderInStream.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_FOLDER_IN_STREAM_H
|
||||
#define ZIP7_INC_7Z_FOLDER_IN_STREAM_H
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
// #include "../Common/InStreamWithCRC.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../IArchive.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
CFolderInStream
|
||||
, ISequentialInStream
|
||||
, ICompressGetSubStreamSize
|
||||
)
|
||||
/*
|
||||
Z7_COM7F_IMP(GetNextStream(UInt64 *streamIndex))
|
||||
Z7_IFACE_COM7_IMP(ICompressInSubStreams)
|
||||
*/
|
||||
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _totalSize_for_Coder;
|
||||
UInt64 _pos;
|
||||
UInt32 _crc;
|
||||
bool _size_Defined;
|
||||
bool _times_Defined;
|
||||
UInt64 _size;
|
||||
FILETIME _mTime;
|
||||
FILETIME _cTime;
|
||||
FILETIME _aTime;
|
||||
UInt32 _attrib;
|
||||
|
||||
unsigned _numFiles;
|
||||
const UInt32 *_indexes;
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
|
||||
|
||||
void ClearFileInfo();
|
||||
HRESULT OpenStream();
|
||||
HRESULT AddFileInfo(bool isProcessed);
|
||||
// HRESULT CloseCrcStream();
|
||||
public:
|
||||
bool Need_MTime;
|
||||
bool Need_CTime;
|
||||
bool Need_ATime;
|
||||
bool Need_Attrib;
|
||||
// bool Need_Crc;
|
||||
// bool Need_FolderCrc;
|
||||
// unsigned AlignLog;
|
||||
|
||||
CRecordVector<bool> Processed;
|
||||
CRecordVector<UInt64> Sizes;
|
||||
CRecordVector<UInt32> CRCs;
|
||||
CRecordVector<UInt32> Attribs;
|
||||
CRecordVector<bool> TimesDefined;
|
||||
CRecordVector<UInt64> MTimes;
|
||||
CRecordVector<UInt64> CTimes;
|
||||
CRecordVector<UInt64> ATimes;
|
||||
// UInt32 FolderCrc;
|
||||
|
||||
// UInt32 GetFolderCrc() const { return CRC_GET_DIGEST(FolderCrc); }
|
||||
// CSequentialInStreamWithCRC *_crcStream_Spec;
|
||||
// CMyComPtr<ISequentialInStream> _crcStream;
|
||||
// CMyComPtr<IArchiveUpdateCallbackArcProp> _reportArcProp;
|
||||
|
||||
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
|
||||
|
||||
bool WasFinished() const { return Processed.Size() == _numFiles; }
|
||||
|
||||
UInt64 Get_TotalSize_for_Coder() const { return _totalSize_for_Coder; }
|
||||
/*
|
||||
UInt64 GetFullSize() const
|
||||
{
|
||||
UInt64 size = 0;
|
||||
FOR_VECTOR (i, Sizes)
|
||||
size += Sizes[i];
|
||||
return size;
|
||||
}
|
||||
*/
|
||||
|
||||
CFolderInStream():
|
||||
Need_MTime(false),
|
||||
Need_CTime(false),
|
||||
Need_ATime(false),
|
||||
Need_Attrib(false)
|
||||
// , Need_Crc(true)
|
||||
// , Need_FolderCrc(false)
|
||||
// , AlignLog(0)
|
||||
{}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,795 @@
|
||||
// 7zHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
#ifndef Z7_7Z_SET_PROPERTIES
|
||||
#include "../../../Windows/System.h"
|
||||
#endif
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
#include "7zHandler.h"
|
||||
#include "7zProperties.h"
|
||||
|
||||
#ifdef Z7_7Z_SET_PROPERTIES
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
#include "../Common/ParseProperties.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
CHandler::CHandler()
|
||||
{
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
#endif
|
||||
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
|
||||
_crcSize = 4;
|
||||
|
||||
#ifdef Z7_7Z_SET_PROPERTIES
|
||||
_useMultiThreadMixer = true;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = _db.Files.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef Z7_SFX
|
||||
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps))
|
||||
{
|
||||
*numProps = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(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 char *GetStringForSizeValue(char *s, UInt32 val)
|
||||
{
|
||||
for (unsigned i = 0; i < 32; i++)
|
||||
if (((UInt32)1 << i) == val)
|
||||
{
|
||||
if (i >= 10)
|
||||
{
|
||||
*s++= (char)('0' + i / 10);
|
||||
i %= 10;
|
||||
}
|
||||
*s++ = (char)('0' + i);
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
char c = 'b';
|
||||
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
|
||||
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
|
||||
s = ConvertUInt32ToString(val, s);
|
||||
*s++ = c;
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static void GetLzma2String(char *s, unsigned d)
|
||||
{
|
||||
if (d > 40)
|
||||
{
|
||||
*s = 0;
|
||||
return;
|
||||
// s = MyStpCpy(s, "unsup");
|
||||
}
|
||||
else if ((d & 1) == 0)
|
||||
d = (d >> 1) + 12;
|
||||
else
|
||||
{
|
||||
// s = GetStringForSizeValue(s, (UInt32)3 << ((d >> 1) + 11));
|
||||
d = (d >> 1) + 1;
|
||||
char c = 'k';
|
||||
if (d >= 10)
|
||||
{
|
||||
c = 'm';
|
||||
d -= 10;
|
||||
}
|
||||
s = ConvertUInt32ToString((UInt32)3 << d, s);
|
||||
*s++ = c;
|
||||
*s = 0;
|
||||
return;
|
||||
}
|
||||
ConvertUInt32ToString(d, s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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);
|
||||
return ConvertUInt32ToString(v, 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
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
#ifndef Z7_SFX
|
||||
COM_TRY_BEGIN
|
||||
#endif
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
#ifndef Z7_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:";
|
||||
GetLzma2String(temp, pm.Lzma2Prop);
|
||||
s += temp;
|
||||
}
|
||||
else if (id == k_LZMA)
|
||||
{
|
||||
s += "LZMA:";
|
||||
GetStringForSizeValue(temp, pm.LzmaDic);
|
||||
s += temp;
|
||||
}
|
||||
/*
|
||||
else if (id == k_ZSTD)
|
||||
{
|
||||
s += "ZSTD";
|
||||
}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
case kpidReadOnly:
|
||||
{
|
||||
if (!_db.CanUpdate())
|
||||
prop = true;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
return prop.Detach(value);
|
||||
#ifndef Z7_SFX
|
||||
COM_TRY_END
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index)
|
||||
{
|
||||
UInt64 value;
|
||||
if (v.GetItem(index, value))
|
||||
PropVarEm_Set_FileTime64_Prec(prop, value, k_PropVar_TimePrec_100ns);
|
||||
}
|
||||
|
||||
bool CHandler::IsFolderEncrypted(CNum folderIndex) const
|
||||
{
|
||||
if (folderIndex == kNumNoIndex)
|
||||
return false;
|
||||
const size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
||||
const Byte *p = _db.CodersData.ConstData() + startPos;
|
||||
const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
|
||||
CInByte2 inByte;
|
||||
inByte.Init(p, size);
|
||||
|
||||
CNum numCoders = inByte.ReadNum();
|
||||
for (; numCoders != 0; numCoders--)
|
||||
{
|
||||
const Byte mainByte = inByte.ReadByte();
|
||||
const 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;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))
|
||||
{
|
||||
*numProps = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID))
|
||||
{
|
||||
*name = NULL;
|
||||
*propID = kpidNtSecure;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(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;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(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)
|
||||
{
|
||||
const size_t offset = _db.NameOffsets[index];
|
||||
const size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
|
||||
if (size < ((UInt32)1 << 31))
|
||||
{
|
||||
*data = (const void *)(_db.NamesBuf.ConstData() + 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 Z7_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;
|
||||
|
||||
const size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
||||
const Byte *p = _db.CodersData.ConstData() + startPos;
|
||||
const 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;
|
||||
const Byte mainByte = inByte.ReadByte();
|
||||
UInt64 id64 = 0;
|
||||
const unsigned idSize = (mainByte & 0xF);
|
||||
const Byte *longID = inByte.GetPtr();
|
||||
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)
|
||||
{
|
||||
const UInt32 id = (UInt32)id64;
|
||||
if (id == k_LZMA)
|
||||
{
|
||||
name = "LZMA";
|
||||
if (propsSize == 5)
|
||||
{
|
||||
const UInt32 dicSize = GetUi32((const Byte *)props + 1);
|
||||
char *dest = GetStringForSizeValue(s, dicSize);
|
||||
UInt32 d = props[0];
|
||||
if (d != 0x5D)
|
||||
{
|
||||
const UInt32 lc = d % 9;
|
||||
d /= 9;
|
||||
const UInt32 pb = d / 5;
|
||||
const 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)
|
||||
GetLzma2String(s, props[0]);
|
||||
}
|
||||
else if (id == k_PPMD)
|
||||
{
|
||||
name = "PPMD";
|
||||
if (propsSize == 5)
|
||||
{
|
||||
char *dest = s;
|
||||
*dest++ = 'o';
|
||||
dest = ConvertUInt32ToString(*props, 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_ARM64 || id == k_RISCV)
|
||||
{
|
||||
name = id == k_ARM64 ? "ARM64" : "RISCV";
|
||||
if (propsSize == 4)
|
||||
ConvertUInt32ToString(GetUi32(props), s);
|
||||
/*
|
||||
else if (propsSize != 0)
|
||||
MyStringCopy(s, "unsupported");
|
||||
*/
|
||||
}
|
||||
else if (id == k_BCJ2) name = "BCJ2";
|
||||
else if (id == k_BCJ) name = "BCJ";
|
||||
else if (id == k_AES)
|
||||
{
|
||||
name = "7zAES";
|
||||
if (propsSize >= 1)
|
||||
{
|
||||
const Byte firstByte = props[0];
|
||||
const UInt32 numCyclesPower = firstByte & 0x3F;
|
||||
ConvertUInt32ToString(numCyclesPower, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name)
|
||||
{
|
||||
const unsigned nameLen = MyStringLen(name);
|
||||
const 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
|
||||
{
|
||||
const 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
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
RINOK(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];
|
||||
const 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;
|
||||
{
|
||||
const 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 (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); 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 Z7_SFX
|
||||
|
||||
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
|
||||
case kpidBlock:
|
||||
{
|
||||
const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
|
||||
}
|
||||
break;
|
||||
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
|
||||
case kpidPackedSize0:
|
||||
case kpidPackedSize1:
|
||||
case kpidPackedSize2:
|
||||
case kpidPackedSize3:
|
||||
case kpidPackedSize4:
|
||||
{
|
||||
const 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
|
||||
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
// return prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
#ifndef Z7_SFX
|
||||
_fileInfoPopIDs.Clear();
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (openArchiveCallback)
|
||||
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
#endif
|
||||
|
||||
CInArchive archive(
|
||||
#ifdef Z7_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 Z7_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 Z7_SFX
|
||||
FillPopIDs();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
_inStream.Release();
|
||||
_db.Clear();
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
_password.Wipe_and_Empty();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#ifdef Z7_7Z_SET_PROPERTIES
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
|
||||
Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
InitCommon();
|
||||
_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;
|
||||
const unsigned index = ParseStringToUInt32(name, number);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsEqualTo("mtf"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer))
|
||||
continue;
|
||||
}
|
||||
{
|
||||
HRESULT hres;
|
||||
if (SetCommonProperty(name, value, hres))
|
||||
{
|
||||
RINOK(hres)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
IMPL_ISetCompressCodecsInfo
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,178 @@
|
||||
// 7z/Handler.h
|
||||
|
||||
#ifndef ZIP7_7Z_HANDLER_H
|
||||
#define ZIP7_7Z_HANDLER_H
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#ifndef Z7_7Z_SET_PROPERTIES
|
||||
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
#if !defined(Z7_ST) && !defined(Z7_SFX)
|
||||
#define Z7_7Z_SET_PROPERTIES
|
||||
#endif
|
||||
#else
|
||||
#define Z7_7Z_SET_PROPERTIES
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// #ifdef Z7_7Z_SET_PROPERTIES
|
||||
#include "../Common/HandlerOut.h"
|
||||
// #endif
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
|
||||
class COutHandler: public CMultiMethodProps
|
||||
{
|
||||
HRESULT SetSolidFromString(const UString &s);
|
||||
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
|
||||
public:
|
||||
UInt64 _numSolidFiles;
|
||||
UInt64 _numSolidBytes;
|
||||
bool _numSolidBytesDefined;
|
||||
bool _solidExtension;
|
||||
bool _useTypeSorting;
|
||||
|
||||
bool _compressHeaders;
|
||||
bool _encryptHeadersSpecified;
|
||||
bool _encryptHeaders;
|
||||
// bool _useParents; 9.26
|
||||
|
||||
CHandlerTimeOptions TimeOptions;
|
||||
|
||||
CBoolPair Write_Attrib;
|
||||
|
||||
bool _useMultiThreadMixer;
|
||||
bool _removeSfxBlock;
|
||||
// bool _volumeMode;
|
||||
|
||||
UInt32 _decoderCompatibilityVersion;
|
||||
CUIntVector _enabledFilters;
|
||||
CUIntVector _disabledFilters;
|
||||
|
||||
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
|
||||
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
|
||||
void InitSolid()
|
||||
{
|
||||
InitSolidFiles();
|
||||
InitSolidSize();
|
||||
_solidExtension = false;
|
||||
_numSolidBytesDefined = false;
|
||||
}
|
||||
|
||||
void InitProps7z();
|
||||
void InitProps();
|
||||
|
||||
COutHandler() { InitProps7z(); }
|
||||
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class CHandler Z7_final:
|
||||
public IInArchive,
|
||||
public IArchiveGetRawProps,
|
||||
|
||||
#ifdef Z7_7Z_SET_PROPERTIES
|
||||
public ISetProperties,
|
||||
#endif
|
||||
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
public IOutArchive,
|
||||
#endif
|
||||
|
||||
Z7_PUBLIC_ISetCompressCodecsInfo_IFEC
|
||||
|
||||
public CMyUnknownImp,
|
||||
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
public COutHandler
|
||||
#else
|
||||
public CCommonMethodProps
|
||||
#endif
|
||||
{
|
||||
Z7_COM_QI_BEGIN2(IInArchive)
|
||||
Z7_COM_QI_ENTRY(IArchiveGetRawProps)
|
||||
#ifdef Z7_7Z_SET_PROPERTIES
|
||||
Z7_COM_QI_ENTRY(ISetProperties)
|
||||
#endif
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
Z7_COM_QI_ENTRY(IOutArchive)
|
||||
#endif
|
||||
Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
Z7_IFACE_COM7_IMP(IInArchive)
|
||||
Z7_IFACE_COM7_IMP(IArchiveGetRawProps)
|
||||
#ifdef Z7_7Z_SET_PROPERTIES
|
||||
Z7_IFACE_COM7_IMP(ISetProperties)
|
||||
#endif
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
Z7_IFACE_COM7_IMP(IOutArchive)
|
||||
#endif
|
||||
DECL_ISetCompressCodecsInfo
|
||||
|
||||
private:
|
||||
CMyComPtr<IInStream> _inStream;
|
||||
NArchive::N7z::CDbEx _db;
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
bool _isEncrypted;
|
||||
bool _passwordIsDefined;
|
||||
UString _password; // _Wipe
|
||||
#endif
|
||||
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
|
||||
#ifdef Z7_7Z_SET_PROPERTIES
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
bool IsFolderEncrypted(CNum folderIndex) const;
|
||||
#ifndef Z7_SFX
|
||||
|
||||
CRecordVector<UInt64> _fileInfoPopIDs;
|
||||
void FillPopIDs();
|
||||
void AddMethodName(AString &s, UInt64 id);
|
||||
HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;
|
||||
|
||||
#endif
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
|
||||
public:
|
||||
CHandler();
|
||||
~CHandler()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 Z7_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;
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,156 @@
|
||||
// 7z/7zHeader.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_HEADER_H
|
||||
#define ZIP7_INC_7Z_HEADER_H
|
||||
|
||||
#include "../../../Common/MyTypes.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
const unsigned kSignatureSize = 6;
|
||||
extern Byte kSignature[kSignatureSize];
|
||||
|
||||
// #define Z7_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 Z7_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 Z7_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_ARM64 = 0xa;
|
||||
const UInt32 k_RISCV = 0xb;
|
||||
|
||||
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_Deflate64 = 0x40109;
|
||||
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_AES = 0x6F10701;
|
||||
|
||||
// const UInt32 k_ZSTD = 0x4015D; // winzip zstd
|
||||
// 0x4F71101, 7z-zstd
|
||||
|
||||
inline bool IsFilterMethod(UInt64 m)
|
||||
{
|
||||
if (m > (UInt32)0xFFFFFFFF)
|
||||
return false;
|
||||
switch ((UInt32)m)
|
||||
{
|
||||
case k_Delta:
|
||||
case k_ARM64:
|
||||
case k_RISCV:
|
||||
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;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,454 @@
|
||||
// 7zIn.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_IN_H
|
||||
#define ZIP7_INC_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 Z7_NO_CRYPTO
|
||||
#define Z7_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
#define Z7_7Z_DECODER_CRYPRO_VARS
|
||||
#else
|
||||
#define Z7_7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
|
||||
#define Z7_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;
|
||||
CUInt32DefVector Attrib;
|
||||
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();
|
||||
Attrib.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; // in stream
|
||||
UInt64 StartPositionAfterHeader; // in stream
|
||||
UInt64 DataStartPosition; // in stream
|
||||
UInt64 DataStartPosition2; // in stream. it's for headers
|
||||
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;
|
||||
// UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes)
|
||||
|
||||
/*
|
||||
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;
|
||||
// EndHeaderOffset = 0;
|
||||
}
|
||||
|
||||
bool CanUpdate() const
|
||||
{
|
||||
if (ThereIsHeaderError
|
||||
|| UnexpectedEnd
|
||||
|| StartHeaderWasRecovered
|
||||
|| UnsupportedFeatureError)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FillLinks();
|
||||
|
||||
UInt64 GetFolderStreamPos(size_t folderIndex, size_t indexInFolder) const
|
||||
{
|
||||
return ArcInfo.DataStartPosition + PackPositions.ConstData()
|
||||
[FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder];
|
||||
}
|
||||
|
||||
UInt64 GetFolderFullPackSize(size_t folderIndex) const
|
||||
{
|
||||
return
|
||||
PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] -
|
||||
PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]];
|
||||
}
|
||||
|
||||
UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const
|
||||
{
|
||||
const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex;
|
||||
return PackPositions.ConstData()[i + 1] -
|
||||
PackPositions.ConstData()[i];
|
||||
}
|
||||
|
||||
/*
|
||||
UInt64 GetFilePackSize(size_t fileIndex) const
|
||||
{
|
||||
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;
|
||||
|
||||
UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes)
|
||||
|
||||
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 Read_UInt32_Vector(CUInt32DefVector &v);
|
||||
|
||||
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
|
||||
Z7_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
HRESULT ReadHeader(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CDbEx &db
|
||||
Z7_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
HRESULT ReadDatabase2(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CDbEx &db
|
||||
Z7_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
|
||||
Z7_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,207 @@
|
||||
// 7zItem.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_ITEM_H
|
||||
#define ZIP7_INC_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
|
||||
{
|
||||
Z7_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 (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindBond_for_PackStream(UInt32 packStream) const
|
||||
{
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].PackIndex == packStream)
|
||||
return (int)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 GetItem(unsigned index, UInt32 &value) const
|
||||
{
|
||||
if (index < Defs.Size() && Defs[index])
|
||||
{
|
||||
value = Vals[index];
|
||||
return true;
|
||||
}
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
|
||||
|
||||
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
|
||||
|
||||
void SetItem(unsigned index, bool defined, UInt32 value);
|
||||
void if_NonEmpty_FillResidue_with_false(unsigned numItems)
|
||||
{
|
||||
if (Defs.Size() != 0 && Defs.Size() < numItems)
|
||||
SetItem(numItems - 1, false, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
|
||||
|
||||
void SetItem(unsigned index, bool defined, UInt64 value);
|
||||
};
|
||||
|
||||
|
||||
struct CFileItem
|
||||
{
|
||||
UInt64 Size;
|
||||
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;
|
||||
|
||||
/*
|
||||
void Clear()
|
||||
{
|
||||
HasStream = true;
|
||||
IsDir = false;
|
||||
CrcDefined = false;
|
||||
}
|
||||
|
||||
CFileItem():
|
||||
// Parent(-1),
|
||||
// IsAltStream(false),
|
||||
HasStream(true),
|
||||
IsDir(false),
|
||||
CrcDefined(false),
|
||||
{}
|
||||
*/
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,346 @@
|
||||
// 7zOut.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_OUT_H
|
||||
#define ZIP7_INC_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 {
|
||||
|
||||
const unsigned k_StartHeadersRewriteSize = 32;
|
||||
|
||||
class CWriteBufferLoc
|
||||
{
|
||||
Byte *_data;
|
||||
Byte *_dataLim;
|
||||
Byte *_dataBase;
|
||||
public:
|
||||
// CWriteBufferLoc(): _data(NULL), _dataLim(NULL), _dataBase(NULL) {}
|
||||
void Init(Byte *data, size_t size)
|
||||
{
|
||||
_data = data;
|
||||
_dataBase = data;
|
||||
_dataLim = data + size;
|
||||
}
|
||||
|
||||
Byte *GetDest_and_Update(size_t size)
|
||||
{
|
||||
Byte *dest = _data;
|
||||
if (size > (size_t)(_dataLim - dest))
|
||||
throw 1;
|
||||
_data = dest + size;
|
||||
return dest;
|
||||
}
|
||||
void WriteBytes(const void *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
Byte *dest = GetDest_and_Update(size);
|
||||
memcpy(dest, data, size);
|
||||
}
|
||||
void WriteByte(Byte b)
|
||||
{
|
||||
Byte *dest = _data;
|
||||
if (dest == _dataLim)
|
||||
throw 1;
|
||||
*dest++ = b;
|
||||
_data = dest;
|
||||
}
|
||||
size_t GetPos() const { return (size_t)(_data - _dataBase); }
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
UInt32 Attrib;
|
||||
|
||||
bool CTimeDefined;
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
bool StartPosDefined;
|
||||
bool AttribDefined;
|
||||
bool IsAnti;
|
||||
// bool IsAux;
|
||||
|
||||
/*
|
||||
void Init()
|
||||
{
|
||||
CTimeDefined = false;
|
||||
ATimeDefined = false;
|
||||
MTimeDefined = false;
|
||||
StartPosDefined = false;
|
||||
AttribDefined = 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;
|
||||
CUInt32DefVector Attrib;
|
||||
CBoolVector IsAnti;
|
||||
|
||||
/*
|
||||
CBoolVector 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();
|
||||
Attrib.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();
|
||||
Attrib.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)
|
||||
&& Attrib.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
|
||||
{
|
||||
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 WriteByte_ToStream(Byte b)
|
||||
{
|
||||
_outByte.WriteByte(b);
|
||||
// _crc = CRC_UPDATE_BYTE(_crc, 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 Write_BoolVector(const CBoolVector &boolVector);
|
||||
void Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined);
|
||||
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 SkipToAligned(unsigned pos, unsigned alignShifts);
|
||||
void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
|
||||
void Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined);
|
||||
void Write_UInt64DefVector_type(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;
|
||||
bool _useAlign;
|
||||
#ifdef Z7_7Z_VOL
|
||||
bool _endMarker;
|
||||
#endif
|
||||
// UInt32 _crc;
|
||||
size_t _countSize;
|
||||
CWriteBufferLoc _outByte2;
|
||||
COutBuffer _outByte;
|
||||
UInt64 _signatureHeaderPos;
|
||||
CMyComPtr<IOutStream> Stream;
|
||||
|
||||
#ifdef Z7_7Z_VOL
|
||||
HRESULT WriteFinishSignature();
|
||||
HRESULT WriteFinishHeader(const CFinishHeader &h);
|
||||
#endif
|
||||
HRESULT WriteStartHeader(const CStartHeader &h);
|
||||
|
||||
public:
|
||||
CMyComPtr<ISequentialOutStream> SeqStream;
|
||||
|
||||
// COutArchive();
|
||||
HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */);
|
||||
void Close();
|
||||
HRESULT WriteDatabase(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CArchiveDatabaseOut &db,
|
||||
const CCompressionMethodMode *options,
|
||||
const CHeaderOptions &headerOptions);
|
||||
|
||||
#ifdef Z7_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
|
||||
@@ -0,0 +1,182 @@
|
||||
// 7zProperties.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "7zHandler.h"
|
||||
#include "7zProperties.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CPropMap
|
||||
{
|
||||
Byte FilePropID;
|
||||
// CStatProp StatProp;
|
||||
VARTYPE vt;
|
||||
UInt32 StatPropID;
|
||||
};
|
||||
|
||||
// #define STAT_PROP(name, id, vt) { name, id, vt }
|
||||
#define STAT_PROP(name, id, vt) vt, id
|
||||
|
||||
#define STAT_PROP2(id, vt) STAT_PROP(NULL, id, vt)
|
||||
|
||||
#define k_7z_id_Encrypted 97
|
||||
#define k_7z_id_Method 98
|
||||
#define k_7z_id_Block 99
|
||||
|
||||
static const CPropMap kPropMap[] =
|
||||
{
|
||||
{ NID::kName, STAT_PROP2(kpidPath, VT_BSTR) },
|
||||
{ NID::kSize, STAT_PROP2(kpidSize, VT_UI8) },
|
||||
{ NID::kPackInfo, STAT_PROP2(kpidPackSize, VT_UI8) },
|
||||
|
||||
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
|
||||
#define k_7z_id_PackedSize0 100
|
||||
{ k_7z_id_PackedSize0 + 0, STAT_PROP("Pack0", kpidPackedSize0, VT_UI8) },
|
||||
{ k_7z_id_PackedSize0 + 1, STAT_PROP("Pack1", kpidPackedSize1, VT_UI8) },
|
||||
{ k_7z_id_PackedSize0 + 2, STAT_PROP("Pack2", kpidPackedSize2, VT_UI8) },
|
||||
{ k_7z_id_PackedSize0 + 3, STAT_PROP("Pack3", kpidPackedSize3, VT_UI8) },
|
||||
{ k_7z_id_PackedSize0 + 4, STAT_PROP("Pack4", kpidPackedSize4, VT_UI8) },
|
||||
#endif
|
||||
|
||||
{ NID::kCTime, STAT_PROP2(kpidCTime, VT_FILETIME) },
|
||||
{ NID::kMTime, STAT_PROP2(kpidMTime, VT_FILETIME) },
|
||||
{ NID::kATime, STAT_PROP2(kpidATime, VT_FILETIME) },
|
||||
{ NID::kWinAttrib, STAT_PROP2(kpidAttrib, VT_UI4) },
|
||||
{ NID::kStartPos, STAT_PROP2(kpidPosition, VT_UI8) },
|
||||
|
||||
{ NID::kCRC, STAT_PROP2(kpidCRC, VT_UI4) },
|
||||
// { NID::kIsAux, STAT_PROP2(kpidIsAux, VT_BOOL) },
|
||||
{ NID::kAnti, STAT_PROP2(kpidIsAnti, VT_BOOL) }
|
||||
|
||||
#ifndef Z7_SFX
|
||||
, { k_7z_id_Encrypted, STAT_PROP2(kpidEncrypted, VT_BOOL) }
|
||||
, { k_7z_id_Method, STAT_PROP2(kpidMethod, VT_BSTR) }
|
||||
, { k_7z_id_Block, STAT_PROP2(kpidBlock, VT_UI4) }
|
||||
#endif
|
||||
};
|
||||
|
||||
static void CopyOneItem(CRecordVector<UInt64> &src,
|
||||
CRecordVector<UInt64> &dest, const UInt32 item)
|
||||
{
|
||||
FOR_VECTOR (i, src)
|
||||
if (src[i] == item)
|
||||
{
|
||||
dest.Add(item);
|
||||
src.Delete(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveOneItem(CRecordVector<UInt64> &src, const UInt32 item)
|
||||
{
|
||||
FOR_VECTOR (i, src)
|
||||
if (src[i] == item)
|
||||
{
|
||||
src.Delete(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void InsertToHead(CRecordVector<UInt64> &dest, const 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 Z7_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 Z7_SFX
|
||||
_fileInfoPopIDs.Add(k_7z_id_Encrypted);
|
||||
_fileInfoPopIDs.Add(k_7z_id_Method);
|
||||
_fileInfoPopIDs.Add(k_7z_id_Block);
|
||||
#endif
|
||||
|
||||
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
|
||||
for (unsigned i = 0; i < 5; i++)
|
||||
_fileInfoPopIDs.Add(k_7z_id_PackedSize0 + i);
|
||||
#endif
|
||||
|
||||
#ifndef Z7_SFX
|
||||
InsertToHead(_fileInfoPopIDs, NID::kMTime);
|
||||
InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
|
||||
InsertToHead(_fileInfoPopIDs, NID::kSize);
|
||||
InsertToHead(_fileInfoPopIDs, NID::kName);
|
||||
#endif
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps))
|
||||
{
|
||||
*numProps = _fileInfoPopIDs.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType))
|
||||
{
|
||||
if (index >= _fileInfoPopIDs.Size())
|
||||
return E_INVALIDARG;
|
||||
const UInt64 id = _fileInfoPopIDs[index];
|
||||
for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPropMap); i++)
|
||||
{
|
||||
const CPropMap &pr = kPropMap[i];
|
||||
if (pr.FilePropID == id)
|
||||
{
|
||||
*propID = pr.StatPropID;
|
||||
*varType = pr.vt;
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,26 @@
|
||||
// 7zProperties.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_PROPERTIES_H
|
||||
#define ZIP7_INC_7Z_PROPERTIES_H
|
||||
|
||||
#include "../../PropID.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
// #define Z7_7Z_SHOW_PACK_STREAMS_SIZES // for debug
|
||||
|
||||
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
|
||||
enum
|
||||
{
|
||||
kpidPackedSize0 = kpidUserDefined,
|
||||
kpidPackedSize1,
|
||||
kpidPackedSize2,
|
||||
kpidPackedSize3,
|
||||
kpidPackedSize4
|
||||
};
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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
|
||||
| NArcInfoFlags::kCTime
|
||||
| NArcInfoFlags::kATime
|
||||
| NArcInfoFlags::kMTime
|
||||
| NArcInfoFlags::kMTime_Default
|
||||
, TIME_PREC_TO_ARC_FLAGS_MASK(NFileTimeType::kWindows)
|
||||
| TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(NFileTimeType::kWindows)
|
||||
, NULL)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 7zSpecStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "7zSpecStream.h"
|
||||
|
||||
/*
|
||||
Z7_COM7F_IMF(CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
const HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value))
|
||||
{
|
||||
if (!_getSubStreamSize)
|
||||
return E_NOTIMPL;
|
||||
return _getSubStreamSize->GetSubStreamSize(subStream, value);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CSequentialInStreamSizeCount2::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream))
|
||||
{
|
||||
if (!_compressGetSubStreamSize)
|
||||
return E_NOTIMPL;
|
||||
return _compressGetSubStreamSize->GetNextInSubStream(streamIndexRes, stream);
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,49 @@
|
||||
// 7zSpecStream.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_SPEC_STREAM_H
|
||||
#define ZIP7_INC_7Z_SPEC_STREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
/*
|
||||
#define Z7_COM_QI_ENTRY_AG_2(i, sub0, sub) else if (iid == IID_ ## i) \
|
||||
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
|
||||
{ i *ti = this; *outObject = ti; } }
|
||||
|
||||
class CSequentialInStreamSizeCount2 Z7_final:
|
||||
public ISequentialInStream,
|
||||
public ICompressGetSubStreamSize,
|
||||
public ICompressInSubStreams,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_QI_BEGIN2(ISequentialInStream)
|
||||
Z7_COM_QI_ENTRY(ICompressGetSubStreamSize)
|
||||
Z7_COM_QI_ENTRY_AG_2(ISequentialInStream, _stream, _compressGetSubStreamSize)
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
Z7_IFACE_COM7_IMP(ISequentialInStream)
|
||||
Z7_IFACE_COM7_IMP(ICompressGetSubStreamSize)
|
||||
Z7_IFACE_COM7_IMP(ICompressInSubStreams)
|
||||
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
|
||||
CMyComPtr<ICompressInSubStreams> _compressGetSubStreamSize;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void Init(ISequentialInStream *stream)
|
||||
{
|
||||
_size = 0;
|
||||
_getSubStreamSize.Release();
|
||||
_compressGetSubStreamSize.Release();
|
||||
_stream = stream;
|
||||
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
|
||||
_stream.QueryInterface(IID_ICompressInSubStreams, &_compressGetSubStreamSize);
|
||||
}
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
// 7zUpdate.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_UPDATE_H
|
||||
#define ZIP7_INC_7Z_UPDATE_H
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
// #include "../../Common/UniqBlocks.h"
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zIn.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;
|
||||
unsigned 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;
|
||||
|
||||
// bool ATime_WasReadByAnalysis;
|
||||
|
||||
// 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)
|
||||
// , ATime_WasReadByAnalysis(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;
|
||||
|
||||
UInt64 NumSolidFiles;
|
||||
UInt64 NumSolidBytes;
|
||||
bool SolidExtension;
|
||||
|
||||
bool UseTypeSorting;
|
||||
|
||||
bool RemoveSfxBlock;
|
||||
bool MultiThreadMixer;
|
||||
|
||||
bool Need_CTime;
|
||||
bool Need_ATime;
|
||||
bool Need_MTime;
|
||||
bool Need_Attrib;
|
||||
// bool Need_Crc;
|
||||
|
||||
CHeaderOptions HeaderOptions;
|
||||
|
||||
CUIntVector DisabledFilterIDs;
|
||||
|
||||
void Add_DisabledFilter_for_id(UInt32 id,
|
||||
const CUIntVector &enabledFilters)
|
||||
{
|
||||
if (enabledFilters.FindInSorted(id) < 0)
|
||||
DisabledFilterIDs.AddToUniqueSorted(id);
|
||||
}
|
||||
|
||||
void SetFilterSupporting_ver_enabled_disabled(
|
||||
UInt32 compatVer,
|
||||
const CUIntVector &enabledFilters,
|
||||
const CUIntVector &disabledFilters)
|
||||
{
|
||||
DisabledFilterIDs = disabledFilters;
|
||||
if (compatVer < 2300) Add_DisabledFilter_for_id(k_ARM64, enabledFilters);
|
||||
if (compatVer < 2402) Add_DisabledFilter_for_id(k_RISCV, enabledFilters);
|
||||
}
|
||||
|
||||
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),
|
||||
Need_CTime(false),
|
||||
Need_ATime(false),
|
||||
Need_MTime(false),
|
||||
Need_Attrib(false)
|
||||
// , Need_Crc(true)
|
||||
{
|
||||
DisabledFilterIDs.Add(k_RISCV);
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT Update(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
const CDbEx *db,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
// const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root
|
||||
// const CUniqBlocks &secureBlocks,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
const CUpdateOptions &options);
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,11 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
PROG = 7z.dll
|
||||
DEF_FILE = ../Archive.def
|
||||
CFLAGS = $(CFLAGS) \
|
||||
-DZ7_EXTERNAL_CODECS \
|
||||
|
||||
AR_OBJS = \
|
||||
$O\ArchiveExports.obj \
|
||||
$O\DllExports2.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\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 \
|
||||
$O\CodecExports.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"
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,422 @@
|
||||
// ApmHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../../Windows/PropVariantUtils.h"
|
||||
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "HandlerCont.h"
|
||||
|
||||
#define Get32(p) GetBe32a(p)
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
namespace NDmg {
|
||||
const char *Find_Apple_FS_Ext(const AString &name);
|
||||
bool Is_Apple_FS_Or_Unknown(const AString &name);
|
||||
}
|
||||
|
||||
namespace NApm {
|
||||
|
||||
static const Byte kSig0 = 'E';
|
||||
static const Byte kSig1 = 'R';
|
||||
|
||||
static const CUInt32PCharPair k_Flags[] =
|
||||
{
|
||||
{ 0, "VALID" },
|
||||
{ 1, "ALLOCATED" },
|
||||
{ 2, "IN_USE" },
|
||||
{ 3, "BOOTABLE" },
|
||||
{ 4, "READABLE" },
|
||||
{ 5, "WRITABLE" },
|
||||
{ 6, "OS_PIC_CODE" },
|
||||
// { 7, "OS_SPECIFIC_2" }, // "Unused"
|
||||
{ 8, "ChainCompatible" }, // "OS_SPECIFIC_1"
|
||||
{ 9, "RealDeviceDriver" },
|
||||
// { 10, "CanChainToNext" },
|
||||
{ 30, "MOUNTED_AT_STARTUP" },
|
||||
{ 31, "STARTUP" }
|
||||
};
|
||||
|
||||
#define DPME_FLAGS_VALID (1u << 0)
|
||||
#define DPME_FLAGS_ALLOCATED (1u << 1)
|
||||
|
||||
static const unsigned k_Str_Size = 32;
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 StartBlock;
|
||||
UInt32 NumBlocks;
|
||||
UInt32 Flags; // pmPartStatus
|
||||
char Name[k_Str_Size];
|
||||
char Type[k_Str_Size];
|
||||
/*
|
||||
UInt32 DataStartBlock;
|
||||
UInt32 NumDataBlocks;
|
||||
UInt32 BootStartBlock;
|
||||
UInt32 BootSize;
|
||||
UInt32 BootAddr;
|
||||
UInt32 BootEntry;
|
||||
UInt32 BootChecksum;
|
||||
char Processor[16];
|
||||
*/
|
||||
|
||||
bool Is_Valid_and_Allocated() const
|
||||
{ return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; }
|
||||
|
||||
bool Parse(const UInt32 *p32, UInt32 &numBlocksInMap)
|
||||
{
|
||||
if (GetUi32a(p32) != 0x4d50) // "PM"
|
||||
return false;
|
||||
numBlocksInMap = Get32(p32 + 4 / 4);
|
||||
StartBlock = Get32(p32 + 8 / 4);
|
||||
NumBlocks = Get32(p32 + 0xc / 4);
|
||||
Flags = Get32(p32 + 0x58 / 4);
|
||||
memcpy(Name, p32 + 0x10 / 4, k_Str_Size);
|
||||
memcpy(Type, p32 + 0x30 / 4, k_Str_Size);
|
||||
/*
|
||||
DataStartBlock = Get32(p + 0x50);
|
||||
NumDataBlocks = Get32(p + 0x54);
|
||||
BootStartBlock = Get32(p + 0x5c);
|
||||
BootSize = Get32(p + 0x60);
|
||||
BootAddr = Get32(p + 0x64);
|
||||
if (Get32(p + 0x68) != 0)
|
||||
return false;
|
||||
BootEntry = Get32(p + 0x6c);
|
||||
if (Get32(p + 0x70) != 0)
|
||||
return false;
|
||||
BootChecksum = Get32(p + 0x74);
|
||||
memcpy(Processor, p32 + 0x78 / 4, 16);
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Z7_class_CHandler_final: public CHandlerCont
|
||||
{
|
||||
Z7_IFACE_COM7_IMP(IInArchive_Cont)
|
||||
|
||||
CRecordVector<CItem> _items;
|
||||
unsigned _blockSizeLog;
|
||||
bool _isArc;
|
||||
// UInt32 _numBlocks;
|
||||
UInt64 _phySize;
|
||||
|
||||
UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
|
||||
|
||||
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
pos = BlocksToBytes(item.StartBlock);
|
||||
size = BlocksToBytes(item.NumBlocks);
|
||||
return NExtract::NOperationResult::kOK;
|
||||
}
|
||||
};
|
||||
|
||||
static const UInt32 kSectorSize = 512;
|
||||
|
||||
// we support only 4 cluster sizes: 512, 1024, 2048, 4096 */
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < kSectorSize)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (GetUi32(p + 12) != 0)
|
||||
return k_IsArc_Res_NO;
|
||||
UInt32 v = GetUi32(p); // we read as little-endian
|
||||
v ^= kSig0 | (unsigned)kSig1 << 8;
|
||||
if (v & ~((UInt32)0xf << 17))
|
||||
return k_IsArc_Res_NO;
|
||||
if ((0x116u >> (v >> 17)) & 1)
|
||||
return k_IsArc_Res_YES;
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
|
||||
UInt32 buf32[kSectorSize / 4];
|
||||
unsigned numPadSectors, blockSizeLog_from_Header;
|
||||
{
|
||||
// Driver Descriptor Map (DDM)
|
||||
RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
|
||||
// 8: UInt16 sbDevType : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso
|
||||
// 10: UInt16 sbDevId : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso
|
||||
// 12: UInt32 sbData : =0
|
||||
if (buf32[3] != 0)
|
||||
return S_FALSE;
|
||||
UInt32 v = GetUi32a(buf32); // we read as little-endian
|
||||
v ^= kSig0 | (unsigned)kSig1 << 8;
|
||||
if (v & ~((UInt32)0xf << 17))
|
||||
return S_FALSE;
|
||||
v >>= 16;
|
||||
if (v == 0)
|
||||
return S_FALSE;
|
||||
if (v & (v - 1))
|
||||
return S_FALSE;
|
||||
// v == { 16,8,4,2 } : block size (x256 bytes)
|
||||
const unsigned a =
|
||||
#if 1
|
||||
(0x30210u >> v) & 3;
|
||||
#else
|
||||
0; // for debug : hardcoded switch to 512-bytes mode
|
||||
#endif
|
||||
numPadSectors = (1u << a) - 1;
|
||||
_blockSizeLog = blockSizeLog_from_Header = 9 + a;
|
||||
}
|
||||
|
||||
/*
|
||||
some APMs (that are ".iso" macOS installation files) contain
|
||||
(blockSizeLog == 11) in DDM header,
|
||||
and contain 2 overlapping maps:
|
||||
1) map for 512-bytes-step
|
||||
2) map for 2048-bytes-step
|
||||
512-bytes-step map is correct.
|
||||
2048-bytes-step map can be incorrect in some cases.
|
||||
|
||||
macos 8 / OSX DP2 iso:
|
||||
There is shared "hfs" item in both maps.
|
||||
And correct (offset/size) values for "hfs" partition
|
||||
can be calculated only in 512-bytes mode (ignoring blockSizeLog == 11).
|
||||
But some records (Macintosh.Apple_Driver*_)
|
||||
can be correct on both modes: 512-bytes mode / 2048-bytes-step.
|
||||
|
||||
macos 921 ppc / Apple Mac OS X 10.3.0 iso:
|
||||
Both maps are correct.
|
||||
If we use 512-bytes-step, each 4th item is (Apple_Void) with zero size.
|
||||
And these zero size (Apple_Void) items will be first items in 2048-bytes-step map.
|
||||
*/
|
||||
|
||||
// we define Z7_APM_SWITCH_TO_512_BYTES, because
|
||||
// we want to support old MACOS APMs that contain correct value only
|
||||
// for 512-bytes-step mode
|
||||
#define Z7_APM_SWITCH_TO_512_BYTES
|
||||
|
||||
const UInt32 numBlocks_from_Header = Get32(buf32 + 1);
|
||||
UInt32 numBlocks = 0;
|
||||
{
|
||||
for (unsigned k = 0; k < numPadSectors; k++)
|
||||
{
|
||||
RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
|
||||
#ifdef Z7_APM_SWITCH_TO_512_BYTES
|
||||
if (k == 0)
|
||||
{
|
||||
if (GetUi32a(buf32) == 0x4d50 // "PM"
|
||||
// && (Get32(buf32 + 0x58 / 4) & 1) // Flags::VALID
|
||||
// some old APMs don't use VALID flag for Apple_partition_map item
|
||||
&& Get32(buf32 + 8 / 4) == 1) // StartBlock
|
||||
{
|
||||
// we switch the mode to 512-bytes-step map reading:
|
||||
numPadSectors = 0;
|
||||
_blockSizeLog = 9;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0;;)
|
||||
{
|
||||
#ifdef Z7_APM_SWITCH_TO_512_BYTES
|
||||
if (i != 0 || _blockSizeLog == blockSizeLog_from_Header)
|
||||
#endif
|
||||
{
|
||||
RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
|
||||
}
|
||||
|
||||
CItem item;
|
||||
UInt32 numBlocksInMap = 0;
|
||||
if (!item.Parse(buf32, numBlocksInMap))
|
||||
return S_FALSE;
|
||||
// v24.09: we don't check that all entries have same (numBlocksInMap) values,
|
||||
// because some APMs have different (numBlocksInMap) values, if (Apple_Void) is used.
|
||||
if (numBlocksInMap > (1 << 8) || numBlocksInMap <= i)
|
||||
return S_FALSE;
|
||||
|
||||
const UInt32 finish = item.StartBlock + item.NumBlocks;
|
||||
if (finish < item.StartBlock)
|
||||
return S_FALSE;
|
||||
if (numBlocks < finish)
|
||||
numBlocks = finish;
|
||||
|
||||
_items.Add(item);
|
||||
if (numPadSectors != 0)
|
||||
{
|
||||
RINOK(stream->Seek(numPadSectors << 9, STREAM_SEEK_CUR, NULL))
|
||||
}
|
||||
if (++i == numBlocksInMap)
|
||||
break;
|
||||
}
|
||||
|
||||
_phySize = BlocksToBytes(numBlocks);
|
||||
// _numBlocks = numBlocks;
|
||||
const UInt64 physSize = (UInt64)numBlocks_from_Header << blockSizeLog_from_Header;
|
||||
if (_phySize < physSize)
|
||||
_phySize = physSize;
|
||||
_isArc = true;
|
||||
_stream = stream;
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_isArc = false;
|
||||
_phySize = 0;
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidOffset,
|
||||
kpidCharacts
|
||||
// , kpidCpu
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidClusterSize
|
||||
// , kpidNumBlocks
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
static void GetString(AString &dest, const char *src)
|
||||
{
|
||||
dest.SetFrom_CalcLen(src, k_Str_Size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidMainSubfile:
|
||||
{
|
||||
int mainIndex = -1;
|
||||
FOR_VECTOR (i, _items)
|
||||
{
|
||||
const CItem &item = _items[i];
|
||||
if (!item.Is_Valid_and_Allocated())
|
||||
continue;
|
||||
AString s;
|
||||
GetString(s, item.Type);
|
||||
if (NDmg::Is_Apple_FS_Or_Unknown(s))
|
||||
{
|
||||
if (mainIndex != -1)
|
||||
{
|
||||
mainIndex = -1;
|
||||
break;
|
||||
}
|
||||
mainIndex = (int)i;
|
||||
}
|
||||
}
|
||||
if (mainIndex != -1)
|
||||
prop = (UInt32)(Int32)mainIndex;
|
||||
break;
|
||||
}
|
||||
case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
// case kpidNumBlocks: prop = _numBlocks; break;
|
||||
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
AString s;
|
||||
GetString(s, item.Name);
|
||||
if (s.IsEmpty())
|
||||
s.Add_UInt32(index);
|
||||
AString type;
|
||||
GetString(type, item.Type);
|
||||
{
|
||||
const char *ext = NDmg::Find_Apple_FS_Ext(type);
|
||||
if (ext)
|
||||
type = ext;
|
||||
}
|
||||
if (!type.IsEmpty())
|
||||
{
|
||||
s.Add_Dot();
|
||||
s += type;
|
||||
}
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case kpidCpu:
|
||||
{
|
||||
AString s;
|
||||
s.SetFrom_CalcLen(item.Processor, sizeof(item.Processor));
|
||||
if (!s.IsEmpty())
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
prop = BlocksToBytes(item.NumBlocks);
|
||||
break;
|
||||
case kpidOffset: prop = BlocksToBytes(item.StartBlock); break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(k_Flags, item.Flags, prop); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = { kSig0, kSig1 };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"APM", "apm", NULL, 0xD4,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
IsArc_Apm)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,842 @@
|
||||
// ArHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
#include "../../Common/StringToInt.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
#include "../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamObjects.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
#include "Common/ItemNameUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NAr {
|
||||
|
||||
/*
|
||||
The end of each file member (including last file in archive) is 2-bytes aligned.
|
||||
It uses 0xA padding if required.
|
||||
|
||||
File Names:
|
||||
|
||||
GNU/SVR4 variant (.a static library):
|
||||
/ - archive symbol table
|
||||
// - the list of the long filenames, separated by one or more LF characters.
|
||||
/N - the reference to name string in long filenames list
|
||||
name/ - the name
|
||||
|
||||
Microsoft variant (.lib static library):
|
||||
/ - First linker file (archive symbol table)
|
||||
/ - Second linker file
|
||||
// - the list of the long filenames, null-terminated. Each string begins
|
||||
immediately after the null byte in the previous string.
|
||||
/N - the reference to name string in long filenames list
|
||||
name/ - the name
|
||||
|
||||
BSD (Mac OS X) variant:
|
||||
"__.SYMDEF" - archive symbol table
|
||||
or
|
||||
"__.SYMDEF SORTED" - archive symbol table
|
||||
#1/N - the real filename of length N is appended to the file header.
|
||||
*/
|
||||
|
||||
static const unsigned kSignatureLen = 8;
|
||||
static const Byte kSignature[kSignatureLen] =
|
||||
{ '!', '<', 'a', 'r', 'c', 'h', '>', 0x0A };
|
||||
|
||||
static const unsigned kNameSize = 16;
|
||||
static const unsigned kTimeSize = 12;
|
||||
static const unsigned kUserSize = 6;
|
||||
static const unsigned kModeSize = 8;
|
||||
static const unsigned kSizeSize = 10;
|
||||
|
||||
static const unsigned kHeaderSize = kNameSize + kTimeSize + kUserSize * 2 + kModeSize + kSizeSize + 1 + 1;
|
||||
|
||||
enum EType
|
||||
{
|
||||
kType_Ar,
|
||||
kType_ALib,
|
||||
kType_Deb,
|
||||
kType_Lib
|
||||
};
|
||||
|
||||
static const char * const k_TypeExtionsions[] =
|
||||
{
|
||||
"ar"
|
||||
, "a"
|
||||
, "deb"
|
||||
, "lib"
|
||||
};
|
||||
|
||||
enum ESubType
|
||||
{
|
||||
kSubType_None,
|
||||
kSubType_BSD
|
||||
};
|
||||
|
||||
/*
|
||||
struct CHeader
|
||||
{
|
||||
char Name[kNameSize];
|
||||
char MTime[kTimeSize];
|
||||
char User[kUserSize];
|
||||
char Group[kUserSize];
|
||||
char Mode[kModeSize];
|
||||
char Size[kSizeSize];
|
||||
char Quote;
|
||||
char NewLine;
|
||||
};
|
||||
*/
|
||||
|
||||
struct CItem
|
||||
{
|
||||
AString Name;
|
||||
UInt64 Size;
|
||||
UInt32 MTime;
|
||||
UInt32 User;
|
||||
UInt32 Group;
|
||||
UInt32 Mode;
|
||||
|
||||
UInt64 HeaderPos;
|
||||
UInt64 HeaderSize;
|
||||
|
||||
int TextFileIndex;
|
||||
int SameNameIndex;
|
||||
|
||||
CItem(): TextFileIndex(-1), SameNameIndex(-1) {}
|
||||
UInt64 GetDataPos() const { return HeaderPos + HeaderSize; }
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
|
||||
public:
|
||||
UInt64 Position;
|
||||
ESubType SubType;
|
||||
|
||||
HRESULT GetNextItem(CItem &itemInfo, bool &filled);
|
||||
HRESULT Open(IInStream *inStream);
|
||||
HRESULT SkipData(UInt64 dataSize)
|
||||
{
|
||||
return m_Stream->Seek((Int64)(dataSize + (dataSize & 1)), STREAM_SEEK_CUR, &Position);
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream)
|
||||
{
|
||||
SubType = kSubType_None;
|
||||
RINOK(InStream_GetPos(inStream, Position))
|
||||
char signature[kSignatureLen];
|
||||
RINOK(ReadStream_FALSE(inStream, signature, kSignatureLen))
|
||||
Position += kSignatureLen;
|
||||
if (memcmp(signature, kSignature, kSignatureLen) != 0)
|
||||
return S_FALSE;
|
||||
m_Stream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static unsigned RemoveTailSpaces(char *dest, const char *s, unsigned size)
|
||||
{
|
||||
memcpy(dest, s, size);
|
||||
for (; size != 0; size--)
|
||||
{
|
||||
if (dest[size - 1] != ' ')
|
||||
break;
|
||||
}
|
||||
dest[size] = 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool OctalToNumber32(const char *s, unsigned size, UInt32 &res)
|
||||
{
|
||||
res = 0;
|
||||
char sz[32];
|
||||
size = RemoveTailSpaces(sz, s, size);
|
||||
if (size == 0 || strcmp(sz, "-1") == 0)
|
||||
return true; // some items don't contain any numbers
|
||||
const char *end;
|
||||
UInt64 res64 = ConvertOctStringToUInt64(sz, &end);
|
||||
if ((unsigned)(end - sz) != size)
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static bool DecimalToNumber(const char *s, unsigned size, UInt64 &res)
|
||||
{
|
||||
res = 0;
|
||||
char sz[32];
|
||||
size = RemoveTailSpaces(sz, s, size);
|
||||
if (size == 0 || strcmp(sz, "-1") == 0)
|
||||
return true; // some items don't contain any numbers
|
||||
const char *end;
|
||||
res = ConvertStringToUInt64(sz, &end);
|
||||
return ((unsigned)(end - sz) == size);
|
||||
}
|
||||
|
||||
static bool DecimalToNumber32(const char *s, unsigned size, UInt32 &res)
|
||||
{
|
||||
UInt64 res64;
|
||||
if (!DecimalToNumber(s, size, res64))
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
#define RIF(x) { if (!(x)) return S_FALSE; }
|
||||
|
||||
|
||||
HRESULT CInArchive::GetNextItem(CItem &item, bool &filled)
|
||||
{
|
||||
filled = false;
|
||||
|
||||
char header[kHeaderSize];
|
||||
const char *cur = header;
|
||||
|
||||
{
|
||||
size_t processedSize = sizeof(header);
|
||||
item.HeaderPos = Position;
|
||||
item.HeaderSize = kHeaderSize;
|
||||
RINOK(ReadStream(m_Stream, header, &processedSize))
|
||||
if (processedSize != sizeof(header))
|
||||
return S_OK;
|
||||
if (header[kHeaderSize - 2] != 0x60 ||
|
||||
header[kHeaderSize - 1] != 0x0A)
|
||||
return S_OK;
|
||||
for (unsigned i = 0; i < kHeaderSize - 2; i++)
|
||||
// if (header[i] < 0x20)
|
||||
if (header[i] == 0)
|
||||
return S_OK;
|
||||
Position += processedSize;
|
||||
}
|
||||
|
||||
UInt32 longNameLen = 0;
|
||||
if (cur[0] == '#' &&
|
||||
cur[1] == '1' &&
|
||||
cur[2] == '/' &&
|
||||
cur[3] != 0)
|
||||
{
|
||||
// BSD variant
|
||||
RIF(DecimalToNumber32(cur + 3, kNameSize - 3 , longNameLen))
|
||||
if (longNameLen >= (1 << 12))
|
||||
longNameLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char tempString[kNameSize + 1];
|
||||
RemoveTailSpaces(tempString, cur, kNameSize);
|
||||
item.Name = tempString;
|
||||
}
|
||||
cur += kNameSize;
|
||||
|
||||
RIF(DecimalToNumber32(cur, kTimeSize, item.MTime)) cur += kTimeSize;
|
||||
RIF(DecimalToNumber32(cur, kUserSize, item.User)) cur += kUserSize;
|
||||
RIF(DecimalToNumber32(cur, kUserSize, item.Group)) cur += kUserSize;
|
||||
RIF(OctalToNumber32(cur, kModeSize, item.Mode)) cur += kModeSize;
|
||||
RIF(DecimalToNumber(cur, kSizeSize, item.Size)) cur += kSizeSize;
|
||||
|
||||
if (longNameLen != 0 && longNameLen <= item.Size)
|
||||
{
|
||||
SubType = kSubType_BSD;
|
||||
size_t processedSize = longNameLen;
|
||||
char *s = item.Name.GetBuf(longNameLen);
|
||||
HRESULT res = ReadStream(m_Stream, s, &processedSize);
|
||||
item.Name.ReleaseBuf_CalcLen(longNameLen);
|
||||
RINOK(res)
|
||||
if (processedSize != longNameLen)
|
||||
return S_OK;
|
||||
item.Size -= longNameLen;
|
||||
item.HeaderSize += longNameLen;
|
||||
Position += processedSize;
|
||||
}
|
||||
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_1(
|
||||
IInArchiveGetStream
|
||||
)
|
||||
bool _isArc;
|
||||
CObjectVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _phySize;
|
||||
Int32 _mainSubfile;
|
||||
|
||||
EType _type;
|
||||
ESubType _subType;
|
||||
int _longNames_FileIndex;
|
||||
unsigned _numLibFiles;
|
||||
AString _errorMessage;
|
||||
AString _libFiles[2];
|
||||
|
||||
void UpdateErrorMessage(const char *s);
|
||||
|
||||
HRESULT ParseLongNames(IInStream *stream);
|
||||
void ChangeDuplicateNames();
|
||||
int FindItem(UInt32 offset) const;
|
||||
HRESULT AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos);
|
||||
HRESULT ParseLibSymbols(IInStream *stream, unsigned fileIndex);
|
||||
};
|
||||
|
||||
void CHandler::UpdateErrorMessage(const char *s)
|
||||
{
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage.Add_LF();
|
||||
_errorMessage += s;
|
||||
}
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidSubType
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidMTime,
|
||||
kpidPosixAttrib,
|
||||
kpidUserId,
|
||||
kpidGroupId
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
HRESULT CHandler::ParseLongNames(IInStream *stream)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < _items.Size(); i++)
|
||||
if (_items[i].Name.IsEqualTo("//"))
|
||||
break;
|
||||
if (i == _items.Size())
|
||||
return S_OK;
|
||||
|
||||
unsigned fileIndex = i;
|
||||
const CItem &item = _items[fileIndex];
|
||||
if (item.Size > ((UInt32)1 << 30))
|
||||
return S_FALSE;
|
||||
RINOK(InStream_SeekSet(stream, item.GetDataPos()))
|
||||
const size_t size = (size_t)item.Size;
|
||||
|
||||
CByteArr p(size);
|
||||
RINOK(ReadStream_FALSE(stream, p, size))
|
||||
|
||||
for (i = 0; i < _items.Size(); i++)
|
||||
{
|
||||
CItem &item2 = _items[i];
|
||||
if (item2.Name[0] != '/')
|
||||
continue;
|
||||
const char *ptr = item2.Name.Ptr(1);
|
||||
const char *end;
|
||||
UInt32 pos = ConvertStringToUInt32(ptr, &end);
|
||||
if (*end != 0 || end == ptr)
|
||||
continue;
|
||||
if (pos >= size)
|
||||
continue;
|
||||
UInt32 start = pos;
|
||||
for (;;)
|
||||
{
|
||||
if (pos >= size)
|
||||
return S_FALSE;
|
||||
const Byte c = p[pos];
|
||||
if (c == 0 || c == 0x0A)
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
item2.Name.SetFrom((const char *)(p + start), (unsigned)(pos - start));
|
||||
}
|
||||
|
||||
_longNames_FileIndex = (int)fileIndex;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CHandler::ChangeDuplicateNames()
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 1; i < _items.Size(); i++)
|
||||
{
|
||||
CItem &item = _items[i];
|
||||
if (item.Name[0] == '/')
|
||||
continue;
|
||||
CItem &prev = _items[i - 1];
|
||||
if (item.Name.IsEqualTo(prev.Name))
|
||||
{
|
||||
if (prev.SameNameIndex < 0)
|
||||
prev.SameNameIndex = 0;
|
||||
item.SameNameIndex = prev.SameNameIndex + 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < _items.Size(); i++)
|
||||
{
|
||||
CItem &item = _items[i];
|
||||
if (item.SameNameIndex < 0)
|
||||
continue;
|
||||
char sz[32];
|
||||
ConvertUInt32ToString((unsigned)item.SameNameIndex + 1, sz);
|
||||
unsigned len = MyStringLen(sz);
|
||||
sz[len++] = '.';
|
||||
sz[len] = 0;
|
||||
item.Name.Insert(0, sz);
|
||||
}
|
||||
}
|
||||
|
||||
int CHandler::FindItem(UInt32 offset) const
|
||||
{
|
||||
unsigned left = 0, right = _items.Size();
|
||||
while (left != right)
|
||||
{
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const UInt64 midVal = _items[mid].HeaderPos;
|
||||
if (offset == midVal)
|
||||
return (int)mid;
|
||||
if (offset < midVal)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
HRESULT CHandler::AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos)
|
||||
{
|
||||
const int fileIndex = FindItem(offset);
|
||||
if (fileIndex < (int)0)
|
||||
return S_FALSE;
|
||||
|
||||
size_t i = pos;
|
||||
do
|
||||
{
|
||||
if (i >= size)
|
||||
return S_FALSE;
|
||||
}
|
||||
while (data[i++] != 0);
|
||||
|
||||
AString &s = _libFiles[_numLibFiles];
|
||||
const AString &name = _items[(unsigned)fileIndex].Name;
|
||||
s += name;
|
||||
if (!name.IsEmpty() && name.Back() == '/')
|
||||
s.DeleteBack();
|
||||
s += " ";
|
||||
s += (const char *)(data + pos);
|
||||
// s.Add_Char((char)0xD);
|
||||
s.Add_LF();
|
||||
pos = i;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static UInt32 Get32(const Byte *p, unsigned be) { if (be) return GetBe32(p); return GetUi32(p); }
|
||||
|
||||
HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex)
|
||||
{
|
||||
CItem &item = _items[fileIndex];
|
||||
if (!item.Name.IsEqualTo("/") &&
|
||||
!item.Name.IsEqualTo("__.SYMDEF") &&
|
||||
!item.Name.IsEqualTo("__.SYMDEF SORTED"))
|
||||
return S_OK;
|
||||
if (item.Size > ((UInt32)1 << 30) ||
|
||||
item.Size < 4)
|
||||
return S_OK;
|
||||
RINOK(InStream_SeekSet(stream, item.GetDataPos()))
|
||||
size_t size = (size_t)item.Size;
|
||||
CByteArr p(size);
|
||||
RINOK(ReadStream_FALSE(stream, p, size))
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
if (!item.Name.IsEqualTo("/"))
|
||||
{
|
||||
// "__.SYMDEF" parsing (BSD)
|
||||
unsigned be;
|
||||
for (be = 0; be < 2; be++)
|
||||
{
|
||||
const UInt32 tableSize = Get32(p, be);
|
||||
pos = 4;
|
||||
if (size - pos < tableSize || (tableSize & 7) != 0)
|
||||
continue;
|
||||
size_t namesStart = pos + tableSize;
|
||||
const UInt32 namesSize = Get32(p.ConstData() + namesStart, be);
|
||||
namesStart += 4;
|
||||
if (namesStart > size || namesStart + namesSize != size)
|
||||
continue;
|
||||
|
||||
const UInt32 numSymbols = tableSize >> 3;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numSymbols; i++, pos += 8)
|
||||
{
|
||||
size_t namePos = Get32(p + pos, be);
|
||||
const UInt32 offset = Get32(p + pos + 4, be);
|
||||
if (AddFunc(offset, p + namesStart, namesSize, namePos) != S_OK)
|
||||
break;
|
||||
}
|
||||
if (i == numSymbols)
|
||||
{
|
||||
pos = size;
|
||||
_type = kType_ALib;
|
||||
_subType = kSubType_BSD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (be == 2)
|
||||
return S_FALSE;
|
||||
}
|
||||
else if (_numLibFiles == 0)
|
||||
{
|
||||
// archive symbol table (GNU)
|
||||
const UInt32 numSymbols = GetBe32(p);
|
||||
pos = 4;
|
||||
if (numSymbols > (size - pos) / 4)
|
||||
return S_FALSE;
|
||||
pos += 4 * numSymbols;
|
||||
|
||||
for (UInt32 i = 0; i < numSymbols; i++)
|
||||
{
|
||||
const UInt32 offset = GetBe32(p + 4 + i * 4);
|
||||
RINOK(AddFunc(offset, p, size, pos))
|
||||
}
|
||||
_type = kType_ALib;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second linker file (Microsoft .lib)
|
||||
const UInt32 numMembers = GetUi32(p);
|
||||
pos = 4;
|
||||
if (numMembers > (size - pos) / 4)
|
||||
return S_FALSE;
|
||||
pos += 4 * numMembers;
|
||||
|
||||
if (size - pos < 4)
|
||||
return S_FALSE;
|
||||
const UInt32 numSymbols = GetUi32(p + pos);
|
||||
pos += 4;
|
||||
if (numSymbols > (size - pos) / 2)
|
||||
return S_FALSE;
|
||||
size_t indexStart = pos;
|
||||
pos += 2 * numSymbols;
|
||||
|
||||
for (UInt32 i = 0; i < numSymbols; i++)
|
||||
{
|
||||
// index is 1-based. So 32-bit numSymbols field works as item[0]
|
||||
const UInt32 index = GetUi16(p + indexStart + i * 2);
|
||||
if (index == 0 || index > numMembers)
|
||||
return S_FALSE;
|
||||
const UInt32 offset = GetUi32(p + index * 4);
|
||||
RINOK(AddFunc(offset, p, size, pos))
|
||||
}
|
||||
_type = kType_Lib;
|
||||
}
|
||||
// size can be 2-byte aligned in linux files
|
||||
if (pos != size && pos + (pos & 1) != size)
|
||||
return S_FALSE;
|
||||
item.TextFileIndex = (int)(_numLibFiles++);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback *callback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
Close();
|
||||
|
||||
UInt64 fileSize;
|
||||
RINOK(InStream_AtBegin_GetSize(stream, fileSize))
|
||||
|
||||
CInArchive arc;
|
||||
RINOK(arc.Open(stream))
|
||||
|
||||
if (callback)
|
||||
{
|
||||
RINOK(callback->SetTotal(NULL, &fileSize))
|
||||
const UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, &arc.Position))
|
||||
}
|
||||
|
||||
CItem item;
|
||||
for (;;)
|
||||
{
|
||||
bool filled;
|
||||
RINOK(arc.GetNextItem(item, filled))
|
||||
if (!filled)
|
||||
break;
|
||||
_items.Add(item);
|
||||
arc.SkipData(item.Size);
|
||||
if (callback && (_items.Size() & 0xFF) == 0)
|
||||
{
|
||||
const UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, &arc.Position))
|
||||
}
|
||||
}
|
||||
|
||||
if (_items.IsEmpty())
|
||||
{
|
||||
// we don't need false empty archives (8-bytes signature only)
|
||||
if (arc.Position != fileSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
_isArc = true;
|
||||
|
||||
_subType = arc.SubType;
|
||||
|
||||
if (ParseLongNames(stream) != S_OK)
|
||||
UpdateErrorMessage("Long file names parsing error");
|
||||
if (_longNames_FileIndex >= 0)
|
||||
_items.Delete((unsigned)_longNames_FileIndex);
|
||||
|
||||
if (!_items.IsEmpty() && _items[0].Name.IsEqualTo("debian-binary"))
|
||||
{
|
||||
_type = kType_Deb;
|
||||
_items.DeleteFrontal(1);
|
||||
for (unsigned i = 0; i < _items.Size(); i++)
|
||||
if (_items[i].Name.IsPrefixedBy("data.tar."))
|
||||
{
|
||||
if (_mainSubfile < 0)
|
||||
_mainSubfile = (int)i;
|
||||
else
|
||||
{
|
||||
_mainSubfile = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangeDuplicateNames();
|
||||
bool error = false;
|
||||
for (unsigned li = 0; li < 2 && li < _items.Size(); li++)
|
||||
if (ParseLibSymbols(stream, li) != S_OK)
|
||||
error = true;
|
||||
if (error)
|
||||
UpdateErrorMessage("Library symbols information error");
|
||||
}
|
||||
|
||||
_stream = stream;
|
||||
_phySize = arc.Position;
|
||||
|
||||
/*
|
||||
if (fileSize < _phySize)
|
||||
UpdateErrorMessage("Unexpected end of archive");
|
||||
*/
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_isArc = false;
|
||||
_phySize = 0;
|
||||
|
||||
_errorMessage.Empty();
|
||||
_stream.Release();
|
||||
_items.Clear();
|
||||
|
||||
_type = kType_Ar;
|
||||
_subType = kSubType_None;
|
||||
_mainSubfile = -1;
|
||||
_longNames_FileIndex = -1;
|
||||
|
||||
_numLibFiles = 0;
|
||||
_libFiles[0].Empty();
|
||||
_libFiles[1].Empty();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
case kpidExtension: prop = k_TypeExtionsions[(unsigned)_type]; break;
|
||||
case kpidShortComment:
|
||||
case kpidSubType:
|
||||
{
|
||||
AString s (k_TypeExtionsions[(unsigned)_type]);
|
||||
if (_subType == kSubType_BSD)
|
||||
s += ":BSD";
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
case kpidWarning: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
|
||||
case kpidIsNotArcType: if (_type != kType_Deb) prop = true; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
if (item.TextFileIndex >= 0)
|
||||
prop = (item.TextFileIndex == 0) ? "1.txt" : "2.txt";
|
||||
else
|
||||
prop = (const wchar_t *)NItemName::GetOsPath_Remove_TailSlash(MultiByteToUnicodeString(item.Name, CP_OEMCP));
|
||||
break;
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
if (item.TextFileIndex >= 0)
|
||||
prop = (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len();
|
||||
else
|
||||
prop = item.Size;
|
||||
break;
|
||||
case kpidMTime:
|
||||
{
|
||||
if (item.MTime != 0)
|
||||
PropVariant_SetFrom_UnixTime(prop, item.MTime);
|
||||
break;
|
||||
}
|
||||
case kpidUserId: if (item.User != 0) prop = item.User; break;
|
||||
case kpidGroupId: if (item.Group != 0) prop = item.Group; break;
|
||||
case kpidPosixAttrib:
|
||||
if (item.TextFileIndex < 0)
|
||||
prop = item.Mode;
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
const CItem &item = _items[allFilesMode ? i : indices[i]];
|
||||
totalSize +=
|
||||
(item.TextFileIndex >= 0) ?
|
||||
(UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
|
||||
}
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
UInt64 currentTotalSize = 0;
|
||||
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
|
||||
inStream->SetStream(_stream);
|
||||
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
lps->InSize = lps->OutSize = currentTotalSize;
|
||||
RINOK(lps->SetCur())
|
||||
if (i >= numItems)
|
||||
break;
|
||||
Int32 opRes;
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||
currentTotalSize += (item.TextFileIndex >= 0) ?
|
||||
(UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
|
||||
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
if (testMode)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
continue;
|
||||
}
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
if (item.TextFileIndex >= 0)
|
||||
{
|
||||
const AString &f = _libFiles[(unsigned)item.TextFileIndex];
|
||||
if (realOutStream)
|
||||
RINOK(WriteStream(realOutStream, f, f.Len()))
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(InStream_SeekSet(_stream, item.GetDataPos()))
|
||||
inStream->Init(item.Size);
|
||||
RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
|
||||
if (copyCoder->TotalSize != item.Size)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
}
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(opRes))
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const CItem &item = _items[index];
|
||||
if (item.TextFileIndex >= 0)
|
||||
{
|
||||
const AString &f = _libFiles[(unsigned)item.TextFileIndex];
|
||||
Create_BufInStream_WithNewBuffer((const void *)(const char *)f, f.Len(), stream);
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"Ar", "ar a deb udeb lib", NULL, 0xEC,
|
||||
kSignature,
|
||||
0,
|
||||
0,
|
||||
NULL)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,14 @@
|
||||
EXPORTS
|
||||
CreateObject PRIVATE
|
||||
|
||||
GetHandlerProperty PRIVATE
|
||||
GetNumberOfFormats PRIVATE
|
||||
GetHandlerProperty2 PRIVATE
|
||||
GetIsArc PRIVATE
|
||||
|
||||
SetCodecs PRIVATE
|
||||
|
||||
SetLargePageMode PRIVATE
|
||||
SetCaseSensitive PRIVATE
|
||||
|
||||
GetModuleProp PRIVATE
|
||||
@@ -0,0 +1,21 @@
|
||||
EXPORTS
|
||||
CreateObject PRIVATE
|
||||
|
||||
GetHandlerProperty PRIVATE
|
||||
GetNumberOfFormats PRIVATE
|
||||
GetHandlerProperty2 PRIVATE
|
||||
GetIsArc PRIVATE
|
||||
|
||||
GetNumberOfMethods PRIVATE
|
||||
GetMethodProperty PRIVATE
|
||||
CreateDecoder PRIVATE
|
||||
CreateEncoder PRIVATE
|
||||
|
||||
GetHashers PRIVATE
|
||||
|
||||
SetCodecs PRIVATE
|
||||
|
||||
SetLargePageMode PRIVATE
|
||||
SetCaseSensitive PRIVATE
|
||||
|
||||
GetModuleProp PRIVATE
|
||||
@@ -0,0 +1,158 @@
|
||||
// ArchiveExports.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zVersion.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/RegisterArc.h"
|
||||
|
||||
static const unsigned kNumArcsMax = 72;
|
||||
static unsigned g_NumArcs = 0;
|
||||
static unsigned g_DefaultArcIndex = 0;
|
||||
static const CArcInfo *g_Arcs[kNumArcsMax];
|
||||
|
||||
void RegisterArc(const CArcInfo *arcInfo) throw()
|
||||
{
|
||||
if (g_NumArcs < kNumArcsMax)
|
||||
{
|
||||
const char *p = arcInfo->Name;
|
||||
if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
|
||||
g_DefaultArcIndex = g_NumArcs;
|
||||
g_Arcs[g_NumArcs++] = arcInfo;
|
||||
}
|
||||
// else throw 1;
|
||||
}
|
||||
|
||||
Z7_DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
k_7zip_GUID_Data1,
|
||||
k_7zip_GUID_Data2,
|
||||
k_7zip_GUID_Data3_Common,
|
||||
0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
|
||||
|
||||
#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
|
||||
|
||||
static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)
|
||||
{
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != NULL)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
|
||||
{
|
||||
return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
|
||||
}
|
||||
|
||||
static int FindFormatCalssId(const GUID *clsid)
|
||||
{
|
||||
GUID cls = *clsid;
|
||||
CLS_ARC_ID_ITEM(cls) = 0;
|
||||
if (cls != CLSID_CArchiveHandler)
|
||||
return -1;
|
||||
const Byte id = CLS_ARC_ID_ITEM(*clsid);
|
||||
for (unsigned i = 0; i < g_NumArcs; i++)
|
||||
if (g_Arcs[i]->Id == id)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
const int needIn = (*iid == IID_IInArchive);
|
||||
const int needOut = (*iid == IID_IOutArchive);
|
||||
if (!needIn && !needOut)
|
||||
return E_NOINTERFACE;
|
||||
const int formatIndex = FindFormatCalssId(clsid);
|
||||
if (formatIndex < 0)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
|
||||
const CArcInfo &arc = *g_Arcs[formatIndex];
|
||||
if (needIn)
|
||||
{
|
||||
*outObject = arc.CreateInArchive();
|
||||
((IInArchive *)*outObject)->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!arc.CreateOutArchive)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
*outObject = arc.CreateOutArchive();
|
||||
((IOutArchive *)*outObject)->AddRef();
|
||||
}
|
||||
}
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value);
|
||||
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::PropVariant_Clear(value);
|
||||
if (formatIndex >= g_NumArcs)
|
||||
return E_INVALIDARG;
|
||||
const CArcInfo &arc = *g_Arcs[formatIndex];
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case NArchive::NHandlerPropID::kName: prop = arc.Name; break;
|
||||
case NArchive::NHandlerPropID::kClassID:
|
||||
{
|
||||
GUID clsId = CLSID_CArchiveHandler;
|
||||
CLS_ARC_ID_ITEM(clsId) = arc.Id;
|
||||
return SetPropGUID(clsId, value);
|
||||
}
|
||||
case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
|
||||
case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;
|
||||
case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;
|
||||
case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;
|
||||
case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;
|
||||
case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;
|
||||
case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;
|
||||
case NArchive::NHandlerPropID::kTimeFlags: prop = (UInt32)arc.TimeFlags; break;
|
||||
case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;
|
||||
// case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
|
||||
|
||||
case NArchive::NHandlerPropID::kSignature:
|
||||
if (arc.SignatureSize != 0 && !arc.IsMultiSignature())
|
||||
return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
break;
|
||||
case NArchive::NHandlerPropID::kMultiSignature:
|
||||
if (arc.SignatureSize != 0 && arc.IsMultiSignature())
|
||||
return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
|
||||
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
|
||||
}
|
||||
|
||||
STDAPI GetNumberOfFormats(UINT32 *numFormats);
|
||||
STDAPI GetNumberOfFormats(UINT32 *numFormats)
|
||||
{
|
||||
*numFormats = g_NumArcs;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc);
|
||||
STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)
|
||||
{
|
||||
*isArc = NULL;
|
||||
if (formatIndex >= g_NumArcs)
|
||||
return E_INVALIDARG;
|
||||
*isArc = g_Arcs[formatIndex]->IsArc;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,978 @@
|
||||
// ArjHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/AutoPtr.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
#include "../../Windows/PropVariantUtils.h"
|
||||
#include "../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamObjects.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
#include "../Compress/LzhDecoder.h"
|
||||
|
||||
#include "Common/ItemNameUtils.h"
|
||||
#include "Common/OutStreamWithCRC.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NArj {
|
||||
namespace NDecoder {
|
||||
|
||||
static const unsigned kMatchMinLen = 3;
|
||||
static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14)
|
||||
|
||||
class CCoder
|
||||
{
|
||||
CLzOutWindow _outWindow;
|
||||
NBitm::CDecoder<CInBuffer> _inBitStream;
|
||||
// bool FinishMode;
|
||||
|
||||
class CCoderReleaser
|
||||
{
|
||||
CCoder *_coder;
|
||||
public:
|
||||
CCoderReleaser(CCoder *coder): _coder(coder) {}
|
||||
void Disable() { _coder = NULL; }
|
||||
~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); }
|
||||
};
|
||||
friend class CCoderReleaser;
|
||||
|
||||
HRESULT CodeReal(UInt32 outSize, ICompressProgressInfo *progress);
|
||||
public:
|
||||
|
||||
// CCoder(): FinishMode(true) {}
|
||||
UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
|
||||
HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
UInt32 outSize, ICompressProgressInfo *progress);
|
||||
};
|
||||
|
||||
|
||||
HRESULT CCoder::CodeReal(UInt32 rem, ICompressProgressInfo *progress)
|
||||
{
|
||||
const UInt32 kStep = 1 << 20;
|
||||
UInt32 next = 0;
|
||||
if (rem > kStep && progress)
|
||||
next = rem - kStep;
|
||||
|
||||
while (rem != 0)
|
||||
{
|
||||
if (rem <= next)
|
||||
{
|
||||
if (_inBitStream.ExtraBitsWereRead())
|
||||
return S_FALSE;
|
||||
const UInt64 packSize = _inBitStream.GetProcessedSize();
|
||||
const UInt64 pos = _outWindow.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &pos))
|
||||
next = 0;
|
||||
if (rem > kStep)
|
||||
next = rem - kStep;
|
||||
}
|
||||
|
||||
UInt32 len;
|
||||
{
|
||||
const unsigned kNumBits = 7 + 7;
|
||||
const UInt32 val = _inBitStream.GetValue(kNumBits);
|
||||
|
||||
if ((val & (1u << (kNumBits - 1))) == 0)
|
||||
{
|
||||
_outWindow.PutByte((Byte)(val >> 5));
|
||||
_inBitStream.MovePos(1 + 8);
|
||||
rem--;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned w;
|
||||
{
|
||||
UInt32 flag = (UInt32)1 << (kNumBits - 2);
|
||||
for (w = 1; w < 7; w++, flag >>= 1)
|
||||
if ((val & flag) == 0)
|
||||
break;
|
||||
}
|
||||
const unsigned readBits = (w != 7 ? 1 : 0) + w * 2;
|
||||
const UInt32 mask = ((UInt32)1 << w) - 1;
|
||||
len = mask + kMatchMinLen - 1 +
|
||||
((val >> (kNumBits - readBits)) & mask);
|
||||
_inBitStream.MovePos(readBits);
|
||||
}
|
||||
{
|
||||
const unsigned kNumBits = 4 + 13;
|
||||
const UInt32 val = _inBitStream.GetValue(kNumBits);
|
||||
unsigned readBits = 1;
|
||||
unsigned w;
|
||||
if ((val & ((UInt32)1 << 16)) == 0) w = 9;
|
||||
else if ((val & ((UInt32)1 << 15)) == 0) w = 10;
|
||||
else if ((val & ((UInt32)1 << 14)) == 0) w = 11;
|
||||
else if ((val & ((UInt32)1 << 13)) == 0) w = 12;
|
||||
else { w = 13; readBits = 0; }
|
||||
|
||||
readBits += w + w - 9;
|
||||
const UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
|
||||
(((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
|
||||
_inBitStream.MovePos(readBits);
|
||||
if (len > rem)
|
||||
{
|
||||
// if (FinishMode)
|
||||
return S_FALSE;
|
||||
// else len = (UInt32)rem;
|
||||
}
|
||||
if (!_outWindow.CopyBlock(dist, len))
|
||||
return S_FALSE;
|
||||
rem -= len;
|
||||
}
|
||||
}
|
||||
|
||||
// if (FinishMode)
|
||||
{
|
||||
if (_inBitStream.ReadAlignBits() != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
if (_inBitStream.ExtraBitsWereRead())
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
UInt32 outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_outWindow.Create(kWindowSize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!_inBitStream.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
_outWindow.SetStream(outStream);
|
||||
_outWindow.Init(false);
|
||||
_inBitStream.SetStream(inStream);
|
||||
_inBitStream.Init();
|
||||
{
|
||||
CCoderReleaser coderReleaser(this);
|
||||
RINOK(CodeReal(outSize, progress))
|
||||
coderReleaser.Disable();
|
||||
}
|
||||
return _outWindow.Flush();
|
||||
}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CLzOutWindowException &e) { return e.ErrorCode; }
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NArj {
|
||||
|
||||
static const unsigned kBlockSizeMin = 30;
|
||||
static const unsigned kBlockSizeMax = 2600;
|
||||
|
||||
static const Byte kSig0 = 0x60;
|
||||
static const Byte kSig1 = 0xEA;
|
||||
|
||||
namespace NCompressionMethod
|
||||
{
|
||||
enum
|
||||
{
|
||||
kStored = 0,
|
||||
kCompressed1a = 1,
|
||||
kCompressed1b = 2,
|
||||
kCompressed1c = 3,
|
||||
kCompressed2 = 4,
|
||||
kNoDataNoCRC = 8,
|
||||
kNoData = 9
|
||||
};
|
||||
}
|
||||
|
||||
namespace NFileType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kBinary = 0,
|
||||
k7BitText,
|
||||
kArchiveHeader,
|
||||
kDirectory,
|
||||
kVolumeLablel,
|
||||
kChapterLabel
|
||||
};
|
||||
}
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const Byte kGarbled = 1 << 0;
|
||||
// const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete
|
||||
const Byte kVolume = 1 << 2;
|
||||
const Byte kExtFile = 1 << 3;
|
||||
// const Byte kPathSym = 1 << 4;
|
||||
// const Byte kBackup = 1 << 5; // obsolete
|
||||
// const Byte kSecured = 1 << 6;
|
||||
// const Byte kDualName = 1 << 7;
|
||||
}
|
||||
|
||||
namespace NHostOS
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kMSDOS = 0, // MS-DOS, OS/2, Win32, pkarj 2.50 (FAT / VFAT / FAT32)
|
||||
kPRIMOS,
|
||||
kUnix,
|
||||
kAMIGA,
|
||||
kMac,
|
||||
kOS_2,
|
||||
kAPPLE_GS,
|
||||
kAtari_ST,
|
||||
kNext,
|
||||
kVAX_VMS,
|
||||
kWIN95
|
||||
};
|
||||
}
|
||||
|
||||
static const char * const kHostOS[] =
|
||||
{
|
||||
"MSDOS"
|
||||
, "PRIMOS"
|
||||
, "UNIX"
|
||||
, "AMIGA"
|
||||
, "MAC"
|
||||
, "OS/2"
|
||||
, "APPLE GS"
|
||||
, "ATARI ST"
|
||||
, "NEXT"
|
||||
, "VAX VMS"
|
||||
, "WIN95"
|
||||
};
|
||||
|
||||
struct CArcHeader
|
||||
{
|
||||
// Byte ArchiverVersion;
|
||||
// Byte ExtractVersion;
|
||||
Byte HostOS;
|
||||
// Byte Flags;
|
||||
// Byte SecuryVersion;
|
||||
// Byte FileType;
|
||||
// Byte Reserved;
|
||||
UInt32 CTime;
|
||||
UInt32 MTime;
|
||||
UInt32 ArchiveSize;
|
||||
// UInt32 SecurPos;
|
||||
// UInt16 FilespecPosInFilename;
|
||||
UInt16 SecurSize;
|
||||
// Byte EncryptionVersion;
|
||||
// Byte LastChapter;
|
||||
AString Name;
|
||||
AString Comment;
|
||||
|
||||
HRESULT Parse(const Byte *p, unsigned size);
|
||||
};
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < kBlockSizeMin + 4)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (p[0] != kSig0 || p[1] != kSig1)
|
||||
return k_IsArc_Res_NO;
|
||||
UInt32 blockSize = Get16(p + 2);
|
||||
if (blockSize < kBlockSizeMin ||
|
||||
blockSize > kBlockSizeMax)
|
||||
return k_IsArc_Res_NO;
|
||||
|
||||
p += 4;
|
||||
size -= 4;
|
||||
|
||||
Byte headerSize = p[0];
|
||||
if (headerSize < kBlockSizeMin ||
|
||||
headerSize > blockSize ||
|
||||
p[6] != NFileType::kArchiveHeader ||
|
||||
p[28] > 8) // EncryptionVersion
|
||||
return k_IsArc_Res_NO;
|
||||
|
||||
if (blockSize + 4 <= size)
|
||||
if (Get32(p + blockSize) != CrcCalc(p, blockSize))
|
||||
return k_IsArc_Res_NO;
|
||||
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT ReadString(const Byte *p, unsigned &size, AString &res)
|
||||
{
|
||||
unsigned num = size;
|
||||
for (unsigned i = 0; i < num;)
|
||||
{
|
||||
if (p[i++] == 0)
|
||||
{
|
||||
size = i;
|
||||
res = (const char *)p;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT CArcHeader::Parse(const Byte *p, unsigned size)
|
||||
{
|
||||
Byte headerSize = p[0];
|
||||
if (headerSize < kBlockSizeMin || headerSize > size)
|
||||
return S_FALSE;
|
||||
// ArchiverVersion = p[1];
|
||||
// ExtractVersion = p[2];
|
||||
HostOS = p[3];
|
||||
// Flags = p[4];
|
||||
// SecuryVersion = p[5];
|
||||
if (p[6] != NFileType::kArchiveHeader)
|
||||
return S_FALSE;
|
||||
// Reserved = p[7];
|
||||
CTime = Get32(p + 8);
|
||||
MTime = Get32(p + 12);
|
||||
ArchiveSize = Get32(p + 16); // it can be zero. (currently used only for secured archives)
|
||||
// SecurPos = Get32(p + 20);
|
||||
// UInt16 filespecPositionInFilename = Get16(p + 24);
|
||||
SecurSize = Get16(p + 26);
|
||||
// EncryptionVersion = p[28];
|
||||
// LastChapter = p[29];
|
||||
unsigned pos = headerSize;
|
||||
unsigned size1 = size - pos;
|
||||
RINOK(ReadString(p + pos, size1, Name))
|
||||
pos += size1;
|
||||
size1 = size - pos;
|
||||
RINOK(ReadString(p + pos, size1, Comment))
|
||||
pos += size1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
struct CExtendedInfo
|
||||
{
|
||||
UInt64 Size;
|
||||
bool CrcError;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Size = 0;
|
||||
CrcError = false;
|
||||
}
|
||||
void ParseToPropVar(NCOM::CPropVariant &prop) const
|
||||
{
|
||||
if (Size != 0)
|
||||
{
|
||||
AString s;
|
||||
s += "Extended:";
|
||||
s.Add_UInt32((UInt32)Size);
|
||||
if (CrcError)
|
||||
s += ":CRC_ERROR";
|
||||
prop = s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CItem
|
||||
{
|
||||
AString Name;
|
||||
AString Comment;
|
||||
|
||||
UInt32 MTime;
|
||||
UInt32 PackSize;
|
||||
UInt32 Size;
|
||||
UInt32 FileCRC;
|
||||
UInt32 SplitPos;
|
||||
|
||||
Byte Version;
|
||||
Byte ExtractVersion;
|
||||
Byte HostOS;
|
||||
Byte Flags;
|
||||
Byte Method;
|
||||
Byte FileType;
|
||||
|
||||
// UInt16 FilespecPosInFilename;
|
||||
UInt16 FileAccessMode;
|
||||
// Byte FirstChapter;
|
||||
// Byte LastChapter;
|
||||
|
||||
UInt64 DataPosition;
|
||||
|
||||
CExtendedInfo ExtendedInfo;
|
||||
|
||||
bool IsEncrypted() const { return (Flags & NFlags::kGarbled) != 0; }
|
||||
bool IsDir() const { return (FileType == NFileType::kDirectory); }
|
||||
bool IsSplitAfter() const { return (Flags & NFlags::kVolume) != 0; }
|
||||
bool IsSplitBefore() const { return (Flags & NFlags::kExtFile) != 0; }
|
||||
UInt32 GetWinAttrib() const
|
||||
{
|
||||
UInt32 atrrib = 0;
|
||||
switch (HostOS)
|
||||
{
|
||||
case NHostOS::kMSDOS:
|
||||
case NHostOS::kWIN95:
|
||||
atrrib = FileAccessMode;
|
||||
break;
|
||||
}
|
||||
if (IsDir())
|
||||
atrrib |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return atrrib;
|
||||
}
|
||||
|
||||
HRESULT Parse(const Byte *p, unsigned size);
|
||||
};
|
||||
|
||||
HRESULT CItem::Parse(const Byte *p, unsigned size)
|
||||
{
|
||||
Byte headerSize = p[0];
|
||||
if (headerSize < kBlockSizeMin || headerSize > size)
|
||||
return S_FALSE;
|
||||
Version = p[1];
|
||||
ExtractVersion = p[2];
|
||||
HostOS = p[3];
|
||||
Flags = p[4];
|
||||
Method = p[5];
|
||||
FileType = p[6];
|
||||
// Reserved = p[7];
|
||||
MTime = Get32(p + 8);
|
||||
PackSize = Get32(p + 12);
|
||||
Size = Get32(p + 16);
|
||||
FileCRC = Get32(p + 20);
|
||||
// FilespecPosInFilename = Get16(p + 24);
|
||||
FileAccessMode = Get16(p + 26);
|
||||
// FirstChapter = p[28];
|
||||
// FirstChapter = p[29];
|
||||
|
||||
SplitPos = 0;
|
||||
if (IsSplitBefore() && headerSize >= 34)
|
||||
SplitPos = Get32(p + 30);
|
||||
|
||||
unsigned pos = headerSize;
|
||||
unsigned size1 = size - pos;
|
||||
RINOK(ReadString(p + pos, size1, Name))
|
||||
pos += size1;
|
||||
size1 = size - pos;
|
||||
RINOK(ReadString(p + pos, size1, Comment))
|
||||
pos += size1;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
enum EErrorType
|
||||
{
|
||||
k_ErrorType_OK,
|
||||
k_ErrorType_Corrupted,
|
||||
k_ErrorType_UnexpectedEnd
|
||||
};
|
||||
|
||||
class CArc
|
||||
{
|
||||
public:
|
||||
UInt64 Processed;
|
||||
EErrorType Error;
|
||||
bool IsArc;
|
||||
IInStream *Stream;
|
||||
IArchiveOpenCallback *Callback;
|
||||
UInt64 NumFiles;
|
||||
CArcHeader Header;
|
||||
|
||||
CExtendedInfo ExtendedInfo;
|
||||
|
||||
HRESULT Open();
|
||||
HRESULT GetNextItem(CItem &item, bool &filled);
|
||||
void Close()
|
||||
{
|
||||
IsArc = false;
|
||||
Error = k_ErrorType_OK;
|
||||
ExtendedInfo.Clear();
|
||||
}
|
||||
private:
|
||||
unsigned _blockSize;
|
||||
CByteBuffer _block;
|
||||
|
||||
HRESULT ReadBlock(bool &filled, CExtendedInfo *extendedInfo);
|
||||
HRESULT SkipExtendedHeaders(CExtendedInfo &extendedInfo);
|
||||
HRESULT Read(void *data, size_t *size);
|
||||
};
|
||||
|
||||
HRESULT CArc::Read(void *data, size_t *size)
|
||||
{
|
||||
HRESULT res = ReadStream(Stream, data, size);
|
||||
Processed += *size;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define READ_STREAM(_dest_, _size_) \
|
||||
{ size_t _processed_ = (_size_); RINOK(Read(_dest_, &_processed_)); \
|
||||
if (_processed_ != (_size_)) { Error = k_ErrorType_UnexpectedEnd; return S_OK; } }
|
||||
|
||||
HRESULT CArc::ReadBlock(bool &filled, CExtendedInfo *extendedInfo)
|
||||
{
|
||||
Error = k_ErrorType_OK;
|
||||
filled = false;
|
||||
Byte buf[4];
|
||||
const unsigned signSize = extendedInfo ? 0 : 2;
|
||||
READ_STREAM(buf, signSize + 2)
|
||||
if (!extendedInfo)
|
||||
if (buf[0] != kSig0 || buf[1] != kSig1)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
_blockSize = Get16(buf + signSize);
|
||||
if (_blockSize == 0) // end of archive
|
||||
return S_OK;
|
||||
|
||||
if (!extendedInfo)
|
||||
if (_blockSize < kBlockSizeMin || _blockSize > kBlockSizeMax)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const size_t readSize = _blockSize + 4;
|
||||
if (readSize > _block.Size())
|
||||
{
|
||||
// extended data size is limited by (64 KB)
|
||||
// _blockSize is less than 64 KB
|
||||
const size_t upSize = (_blockSize > kBlockSizeMax ? (1 << 16) : kBlockSizeMax);
|
||||
_block.Alloc(upSize + 4);
|
||||
}
|
||||
|
||||
if (extendedInfo)
|
||||
extendedInfo->Size += _blockSize;
|
||||
|
||||
READ_STREAM(_block, readSize)
|
||||
if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize))
|
||||
{
|
||||
if (extendedInfo)
|
||||
extendedInfo->CrcError = true;
|
||||
else
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CArc::SkipExtendedHeaders(CExtendedInfo &extendedInfo)
|
||||
{
|
||||
extendedInfo.Clear();
|
||||
for (UInt32 i = 0;; i++)
|
||||
{
|
||||
bool filled;
|
||||
RINOK(ReadBlock(filled, &extendedInfo))
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
if (Callback && (i & 0xFF) == 0)
|
||||
RINOK(Callback->SetCompleted(&NumFiles, &Processed))
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CArc::Open()
|
||||
{
|
||||
bool filled;
|
||||
RINOK(ReadBlock(filled, NULL)) // (extendedInfo = NULL)
|
||||
if (!filled)
|
||||
return S_FALSE;
|
||||
RINOK(Header.Parse(_block, _blockSize))
|
||||
IsArc = true;
|
||||
return SkipExtendedHeaders(ExtendedInfo);
|
||||
}
|
||||
|
||||
HRESULT CArc::GetNextItem(CItem &item, bool &filled)
|
||||
{
|
||||
RINOK(ReadBlock(filled, NULL)) // (extendedInfo = NULL)
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
filled = false;
|
||||
if (item.Parse(_block, _blockSize) != S_OK)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
/*
|
||||
UInt32 extraData;
|
||||
if ((header.Flags & NFlags::kExtFile) != 0)
|
||||
extraData = GetUi32(_block + pos);
|
||||
*/
|
||||
|
||||
RINOK(SkipExtendedHeaders(item.ExtendedInfo))
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_0
|
||||
|
||||
CObjectVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _phySize;
|
||||
CArc _arc;
|
||||
|
||||
HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidName,
|
||||
kpidCTime,
|
||||
kpidMTime,
|
||||
kpidHostOS,
|
||||
kpidComment,
|
||||
kpidCharacts
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidIsDir,
|
||||
kpidSize,
|
||||
kpidPosition,
|
||||
kpidPackSize,
|
||||
kpidMTime,
|
||||
kpidAttrib,
|
||||
kpidEncrypted,
|
||||
kpidCRC,
|
||||
kpidMethod,
|
||||
kpidHostOS,
|
||||
kpidComment,
|
||||
kpidCharacts
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
static void SetTime(UInt32 dosTime, NCOM::CPropVariant &prop)
|
||||
{
|
||||
if (dosTime == 0)
|
||||
return;
|
||||
PropVariant_SetFrom_DosTime(prop, dosTime);
|
||||
}
|
||||
|
||||
static void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop)
|
||||
{
|
||||
TYPE_TO_PROP(kHostOS, hostOS, prop);
|
||||
}
|
||||
|
||||
static void SetUnicodeString(const AString &s, NCOM::CPropVariant &prop)
|
||||
{
|
||||
if (!s.IsEmpty())
|
||||
prop = MultiByteToUnicodeString(s, CP_OEMCP);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidName: SetUnicodeString(_arc.Header.Name, prop); break;
|
||||
case kpidCTime: SetTime(_arc.Header.CTime, prop); break;
|
||||
case kpidMTime: SetTime(_arc.Header.MTime, prop); break;
|
||||
case kpidHostOS: SetHostOS(_arc.Header.HostOS, prop); break;
|
||||
case kpidComment: SetUnicodeString(_arc.Header.Comment, prop); break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_arc.IsArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
switch (_arc.Error)
|
||||
{
|
||||
case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break;
|
||||
case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break;
|
||||
case k_ErrorType_OK:
|
||||
// default:
|
||||
break;
|
||||
}
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
case kpidCharacts: _arc.ExtendedInfo.ParseToPropVar(prop); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath: prop = NItemName::GetOsPath(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidSize: prop = item.Size; break;
|
||||
case kpidPackSize: prop = item.PackSize; break;
|
||||
case kpidPosition: if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break;
|
||||
case kpidAttrib: prop = item.GetWinAttrib(); break;
|
||||
case kpidEncrypted: prop = item.IsEncrypted(); break;
|
||||
case kpidCRC: prop = item.FileCRC; break;
|
||||
case kpidMethod: prop = item.Method; break;
|
||||
case kpidHostOS: SetHostOS(item.HostOS, prop); break;
|
||||
case kpidMTime: SetTime(item.MTime, prop); break;
|
||||
case kpidComment: SetUnicodeString(item.Comment, prop); break;
|
||||
case kpidCharacts: item.ExtendedInfo.ParseToPropVar(prop); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
Close();
|
||||
|
||||
UInt64 endPos;
|
||||
RINOK(InStream_AtBegin_GetSize(inStream, endPos))
|
||||
|
||||
_arc.Stream = inStream;
|
||||
_arc.Callback = callback;
|
||||
_arc.NumFiles = 0;
|
||||
_arc.Processed = 0;
|
||||
|
||||
RINOK(_arc.Open())
|
||||
|
||||
_phySize = _arc.Processed;
|
||||
if (_arc.Header.ArchiveSize != 0)
|
||||
_phySize = (UInt64)_arc.Header.ArchiveSize + _arc.Header.SecurSize;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CItem item;
|
||||
bool filled;
|
||||
|
||||
_arc.Error = k_ErrorType_OK;
|
||||
RINOK(_arc.GetNextItem(item, filled))
|
||||
|
||||
if (_arc.Error != k_ErrorType_OK)
|
||||
break;
|
||||
|
||||
if (!filled)
|
||||
{
|
||||
if (_arc.Error == k_ErrorType_OK)
|
||||
if (_arc.Header.ArchiveSize == 0)
|
||||
_phySize = _arc.Processed;
|
||||
break;
|
||||
}
|
||||
item.DataPosition = _arc.Processed;
|
||||
_items.Add(item);
|
||||
|
||||
UInt64 pos = item.DataPosition + item.PackSize;
|
||||
if (_arc.Header.ArchiveSize == 0)
|
||||
_phySize = pos;
|
||||
if (pos > endPos)
|
||||
{
|
||||
_arc.Error = k_ErrorType_UnexpectedEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
RINOK(InStream_SeekSet(inStream, pos))
|
||||
_arc.NumFiles = _items.Size();
|
||||
_arc.Processed = pos;
|
||||
|
||||
if (callback && (_items.Size() & 0xFF) == 0)
|
||||
{
|
||||
RINOK(callback->SetCompleted(&_arc.NumFiles, &_arc.Processed))
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
|
||||
const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
HRESULT res;
|
||||
{
|
||||
res = Open2(inStream, callback);
|
||||
if (res == S_OK)
|
||||
{
|
||||
_stream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_arc.Close();
|
||||
_phySize = 0;
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
UInt64 totalUnpacked = 0, totalPacked = 0;
|
||||
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
const CItem &item = _items[allFilesMode ? i : indices[i]];
|
||||
totalUnpacked += item.Size;
|
||||
// totalPacked += item.PackSize;
|
||||
}
|
||||
RINOK(extractCallback->SetTotal(totalUnpacked))
|
||||
|
||||
totalUnpacked = totalPacked = 0;
|
||||
UInt32 curUnpacked, curPacked;
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(extractCallback, false);
|
||||
CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;
|
||||
CMyUniquePtr<NCompress::NArj::NDecoder::CCoder> arjDecoder;
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
|
||||
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
|
||||
inStream->SetStream(_stream);
|
||||
|
||||
for (i = 0;; i++,
|
||||
totalUnpacked += curUnpacked,
|
||||
totalPacked += curPacked)
|
||||
{
|
||||
lps->InSize = totalPacked;
|
||||
lps->OutSize = totalUnpacked;
|
||||
RINOK(lps->SetCur())
|
||||
if (i >= numItems)
|
||||
break;
|
||||
|
||||
curUnpacked = curPacked = 0;
|
||||
|
||||
Int32 opRes;
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||
|
||||
if (item.IsDir())
|
||||
{
|
||||
// if (!testMode)
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
// realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
curUnpacked = item.Size;
|
||||
curPacked = item.PackSize;
|
||||
|
||||
CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
|
||||
outStream->SetStream(realOutStream);
|
||||
// realOutStream.Release();
|
||||
outStream->Init();
|
||||
|
||||
inStream->Init(item.PackSize);
|
||||
|
||||
RINOK(InStream_SeekSet(_stream, item.DataPosition))
|
||||
|
||||
HRESULT result = S_OK;
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
|
||||
if (item.IsEncrypted())
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
{
|
||||
switch (item.Method)
|
||||
{
|
||||
case NCompressionMethod::kStored:
|
||||
{
|
||||
result = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
|
||||
if (result == S_OK && copyCoder->TotalSize != item.PackSize)
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
case NCompressionMethod::kCompressed1a:
|
||||
case NCompressionMethod::kCompressed1b:
|
||||
case NCompressionMethod::kCompressed1c:
|
||||
{
|
||||
lzhDecoder.Create_if_Empty();
|
||||
// lzhDecoder->FinishMode = true;
|
||||
const UInt32 kHistorySize = 26624;
|
||||
lzhDecoder->SetDictSize(kHistorySize);
|
||||
result = lzhDecoder->Code(inStream, outStream, curUnpacked, lps);
|
||||
if (result == S_OK && lzhDecoder->GetInputProcessedSize() != item.PackSize)
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
case NCompressionMethod::kCompressed2:
|
||||
{
|
||||
arjDecoder.Create_if_Empty();
|
||||
// arjDecoderSpec->FinishMode = true;
|
||||
result = arjDecoder->Code(inStream, outStream, curUnpacked, lps);
|
||||
if (result == S_OK && arjDecoder->GetInputProcessedSize() != item.PackSize)
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
}
|
||||
}
|
||||
|
||||
if (opRes == NExtract::NOperationResult::kOK)
|
||||
{
|
||||
if (result == S_FALSE)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else
|
||||
{
|
||||
RINOK(result)
|
||||
opRes = (outStream->GetCRC() == item.FileCRC) ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kCRCError;
|
||||
}
|
||||
}
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(opRes))
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = { kSig0, kSig1 };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"Arj", "arj", NULL, 4,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
IsArc_Arj)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,596 @@
|
||||
// AvbHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "HandlerCont.h"
|
||||
|
||||
#define Get32(p) GetBe32(p)
|
||||
#define Get64(p) GetBe64(p)
|
||||
|
||||
#define G32(_offs_, dest) dest = Get32(p + (_offs_))
|
||||
#define G64(_offs_, dest) dest = Get64(p + (_offs_))
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
namespace NExt {
|
||||
API_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize);
|
||||
}
|
||||
|
||||
namespace NAvb {
|
||||
|
||||
static void AddNameToString(AString &s, const Byte *name, unsigned size, bool strictConvert)
|
||||
{
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
{
|
||||
Byte c = name[i];
|
||||
if (c == 0)
|
||||
return;
|
||||
if (strictConvert && c < 32)
|
||||
c = '_';
|
||||
s += (char)c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maximum size of a vbmeta image - 64 KiB. */
|
||||
#define VBMETA_MAX_SIZE (64 * 1024)
|
||||
|
||||
#define SIGNATURE { 'A', 'V', 'B', 'f', 0, 0, 0, 1 }
|
||||
|
||||
static const unsigned k_SignatureSize = 8;
|
||||
static const Byte k_Signature[k_SignatureSize] = SIGNATURE;
|
||||
|
||||
// #define AVB_FOOTER_MAGIC "AVBf"
|
||||
// #define AVB_FOOTER_MAGIC_LEN 4
|
||||
/* The current footer version used - keep in sync with avbtool. */
|
||||
#define AVB_FOOTER_VERSION_MAJOR 1
|
||||
|
||||
/* The struct used as a footer used on partitions, used to find the
|
||||
* AvbVBMetaImageHeader struct. This struct is always stored at the
|
||||
* end of a partition.
|
||||
*/
|
||||
// #define AVB_FOOTER_SIZE 64
|
||||
static const unsigned kFooterSize = 64;
|
||||
|
||||
struct CFooter
|
||||
{
|
||||
/* 0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
|
||||
// Byte magic[AVB_FOOTER_MAGIC_LEN];
|
||||
/* 4: The major version of the footer struct. */
|
||||
UInt32 version_major;
|
||||
/* 8: The minor version of the footer struct. */
|
||||
UInt32 version_minor;
|
||||
|
||||
/* 12: The original size of the image on the partition. */
|
||||
UInt64 original_image_size;
|
||||
|
||||
/* 20: The offset of the |AvbVBMetaImageHeader| struct. */
|
||||
UInt64 vbmeta_offset;
|
||||
|
||||
/* 28: The size of the vbmeta block (header + auth + aux blocks). */
|
||||
UInt64 vbmeta_size;
|
||||
|
||||
/* 36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
|
||||
* must be set to zeroes.
|
||||
*/
|
||||
Byte reserved[28];
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
G32 (4, version_major);
|
||||
G32 (8, version_minor);
|
||||
G64 (12, original_image_size);
|
||||
G64 (20, vbmeta_offset);
|
||||
G64 (28, vbmeta_size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Size of the vbmeta image header. */
|
||||
#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
|
||||
|
||||
/* Magic for the vbmeta image header. */
|
||||
// #define AVB_MAGIC "AVB0"
|
||||
// #define AVB_MAGIC_LEN 4
|
||||
/* Maximum size of the release string including the terminating NUL byte. */
|
||||
#define AVB_RELEASE_STRING_SIZE 48
|
||||
|
||||
struct AvbVBMetaImageHeader
|
||||
{
|
||||
/* 0: Four bytes equal to "AVB0" (AVB_MAGIC). */
|
||||
// Byte magic[AVB_MAGIC_LEN];
|
||||
|
||||
/* 4: The major version of libavb required for this header. */
|
||||
UInt32 required_libavb_version_major;
|
||||
/* 8: The minor version of libavb required for this header. */
|
||||
UInt32 required_libavb_version_minor;
|
||||
|
||||
/* 12: The size of the signature block. */
|
||||
UInt64 authentication_data_block_size;
|
||||
/* 20: The size of the auxiliary data block. */
|
||||
UInt64 auxiliary_data_block_size;
|
||||
|
||||
/* 28: The verification algorithm used, see |AvbAlgorithmType| enum. */
|
||||
UInt32 algorithm_type;
|
||||
|
||||
/* 32: Offset into the "Authentication data" block of hash data. */
|
||||
UInt64 hash_offset;
|
||||
/* 40: Length of the hash data. */
|
||||
UInt64 hash_size;
|
||||
|
||||
/* 48: Offset into the "Authentication data" block of signature data. */
|
||||
UInt64 signature_offset;
|
||||
/* 56: Length of the signature data. */
|
||||
UInt64 signature_size;
|
||||
|
||||
/* 64: Offset into the "Auxiliary data" block of public key data. */
|
||||
UInt64 public_key_offset;
|
||||
/* 72: Length of the public key data. */
|
||||
UInt64 public_key_size;
|
||||
|
||||
/* 80: Offset into the "Auxiliary data" block of public key metadata. */
|
||||
UInt64 public_key_metadata_offset;
|
||||
/* 88: Length of the public key metadata. Must be set to zero if there
|
||||
* is no public key metadata.
|
||||
*/
|
||||
UInt64 public_key_metadata_size;
|
||||
|
||||
/* 96: Offset into the "Auxiliary data" block of descriptor data. */
|
||||
UInt64 descriptors_offset;
|
||||
/* 104: Length of descriptor data. */
|
||||
UInt64 descriptors_size;
|
||||
|
||||
/* 112: The rollback index which can be used to prevent rollback to
|
||||
* older versions.
|
||||
*/
|
||||
UInt64 rollback_index;
|
||||
|
||||
/* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
|
||||
* set to zero if the vbmeta image is not a top-level image.
|
||||
*/
|
||||
UInt32 flags;
|
||||
|
||||
/* 124: The location of the rollback index defined in this header.
|
||||
* Only valid for the main vbmeta. For chained partitions, the rollback
|
||||
* index location must be specified in the AvbChainPartitionDescriptor
|
||||
* and this value must be set to 0.
|
||||
*/
|
||||
UInt32 rollback_index_location;
|
||||
|
||||
/* 128: The release string from avbtool, e.g. "avbtool 1.0.0" or
|
||||
* "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL
|
||||
* terminated. Applications must not make assumptions about how this
|
||||
* string is formatted.
|
||||
*/
|
||||
Byte release_string[AVB_RELEASE_STRING_SIZE];
|
||||
|
||||
/* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
|
||||
* bytes. This must be set to zeroes.
|
||||
*/
|
||||
// Byte reserved[80];
|
||||
bool Parse(const Byte *p);
|
||||
};
|
||||
|
||||
bool AvbVBMetaImageHeader::Parse(const Byte *p)
|
||||
{
|
||||
// Byte magic[AVB_MAGIC_LEN];
|
||||
if (Get32(p) != 0x41564230) // "AVB0"
|
||||
return false;
|
||||
G32 (4, required_libavb_version_major);
|
||||
if (required_libavb_version_major != AVB_FOOTER_VERSION_MAJOR) // "AVB0"
|
||||
return false;
|
||||
G32 (8, required_libavb_version_minor);
|
||||
G64 (12, authentication_data_block_size);
|
||||
G64 (20, auxiliary_data_block_size);
|
||||
G32 (28, algorithm_type);
|
||||
G64 (32, hash_offset);
|
||||
G64 (40, hash_size);
|
||||
G64 (48, signature_offset);
|
||||
G64 (56, signature_size);
|
||||
G64 (64, public_key_offset);
|
||||
G64 (72, public_key_size);
|
||||
G64 (80, public_key_metadata_offset);
|
||||
G64 (88, public_key_metadata_size);
|
||||
G64 (96, descriptors_offset);
|
||||
G64 (104, descriptors_size);
|
||||
G64 (112, rollback_index);
|
||||
G32 (120, flags);
|
||||
G32 (124, rollback_index_location);
|
||||
memcpy(release_string, p + 128, AVB_RELEASE_STRING_SIZE);
|
||||
|
||||
/* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
|
||||
* bytes. This must be set to zeroes.
|
||||
*/
|
||||
// Byte reserved[80];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static const unsigned k_Descriptor_Size = 16;
|
||||
|
||||
enum AvbDescriptorTag
|
||||
{
|
||||
AVB_DESCRIPTOR_TAG_PROPERTY,
|
||||
AVB_DESCRIPTOR_TAG_HASHTREE,
|
||||
AVB_DESCRIPTOR_TAG_HASH,
|
||||
AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
|
||||
AVB_DESCRIPTOR_TAG_CHAIN_PARTITION
|
||||
};
|
||||
|
||||
struct AvbDescriptor
|
||||
{
|
||||
UInt64 Tag;
|
||||
UInt64 Size;
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
G64 (0, Tag);
|
||||
G64 (8, Size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum AvbHashtreeDescriptorFlags
|
||||
{
|
||||
AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
|
||||
AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE = (1 << 1)
|
||||
};
|
||||
|
||||
/* A descriptor containing information about a dm-verity hashtree.
|
||||
*
|
||||
* Hash-trees are used to verify large partitions typically containing
|
||||
* file systems. See
|
||||
* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
|
||||
* information about dm-verity.
|
||||
*
|
||||
* Following this struct are |partition_name_len| bytes of the
|
||||
* partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
|
||||
* |root_digest_len| bytes of the root digest.
|
||||
*
|
||||
* The |reserved| field is for future expansion and must be set to NUL
|
||||
* bytes.
|
||||
*
|
||||
* Changes in v1.1:
|
||||
* - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB
|
||||
* - digest_len may be zero, which indicates the use of a persistent digest
|
||||
*/
|
||||
|
||||
static const unsigned k_Hashtree_Size_Min = 164;
|
||||
|
||||
struct AvbHashtreeDescriptor
|
||||
{
|
||||
UInt32 dm_verity_version;
|
||||
UInt64 image_size;
|
||||
UInt64 tree_offset;
|
||||
UInt64 tree_size;
|
||||
UInt32 data_block_size;
|
||||
UInt32 hash_block_size;
|
||||
UInt32 fec_num_roots;
|
||||
UInt64 fec_offset;
|
||||
UInt64 fec_size;
|
||||
Byte hash_algorithm[32];
|
||||
UInt32 partition_name_len;
|
||||
UInt32 salt_len;
|
||||
UInt32 root_digest_len;
|
||||
UInt32 flags;
|
||||
Byte reserved[60];
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
G32 (0, dm_verity_version);
|
||||
G64 (4, image_size);
|
||||
G64 (12, tree_offset);
|
||||
G64 (20, tree_size);
|
||||
G32 (28, data_block_size);
|
||||
G32 (32, hash_block_size);
|
||||
G32 (36, fec_num_roots);
|
||||
G64 (40, fec_offset);
|
||||
G64 (48, fec_size);
|
||||
memcpy(hash_algorithm, p + 56, 32);
|
||||
G32 (88, partition_name_len);
|
||||
G32 (92, salt_len);
|
||||
G32 (96, root_digest_len);
|
||||
G32 (100, flags);
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned k_PropertyDescriptor_Size_Min = 16;
|
||||
|
||||
struct AvbPropertyDescriptor
|
||||
{
|
||||
UInt64 key_num_bytes;
|
||||
UInt64 value_num_bytes;
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
G64 (0, key_num_bytes);
|
||||
G64 (8, value_num_bytes);
|
||||
}
|
||||
};
|
||||
|
||||
Z7_class_CHandler_final: public CHandlerCont
|
||||
{
|
||||
Z7_IFACE_COM7_IMP(IInArchive_Cont)
|
||||
|
||||
// UInt64 _startOffset;
|
||||
UInt64 _phySize;
|
||||
|
||||
CFooter Footer;
|
||||
AString Name;
|
||||
const char *Ext;
|
||||
|
||||
HRESULT Open2(IInStream *stream);
|
||||
|
||||
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
|
||||
{
|
||||
if (index != 0)
|
||||
return NExtract::NOperationResult::kUnavailable;
|
||||
// pos = _startOffset;
|
||||
pos = 0;
|
||||
size = Footer.original_image_size;
|
||||
return NExtract::NOperationResult::kOK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream)
|
||||
{
|
||||
UInt64 fileSize;
|
||||
{
|
||||
Byte buf[kFooterSize];
|
||||
RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))
|
||||
if (fileSize < kFooterSize)
|
||||
return S_FALSE;
|
||||
RINOK(InStream_SeekSet(stream, fileSize - kFooterSize))
|
||||
RINOK(ReadStream_FALSE(stream, buf, kFooterSize))
|
||||
if (memcmp(buf, k_Signature, k_SignatureSize) != 0)
|
||||
return S_FALSE;
|
||||
Footer.Parse(buf);
|
||||
if (Footer.vbmeta_size > VBMETA_MAX_SIZE ||
|
||||
Footer.vbmeta_size < AVB_VBMETA_IMAGE_HEADER_SIZE)
|
||||
return S_FALSE;
|
||||
for (unsigned i = 36; i < kFooterSize; i++)
|
||||
if (buf[i] != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
{
|
||||
CByteBuffer buf;
|
||||
buf.Alloc((size_t)Footer.vbmeta_size);
|
||||
RINOK(InStream_SeekSet(stream, Footer.vbmeta_offset))
|
||||
RINOK(ReadStream_FALSE(stream, buf, (size_t)Footer.vbmeta_size))
|
||||
|
||||
AvbVBMetaImageHeader meta;
|
||||
if (!meta.Parse(buf))
|
||||
return S_FALSE;
|
||||
|
||||
unsigned offset = (unsigned)AVB_VBMETA_IMAGE_HEADER_SIZE;
|
||||
unsigned rem = (unsigned)(Footer.vbmeta_size - offset);
|
||||
|
||||
if (meta.authentication_data_block_size != 0)
|
||||
{
|
||||
if (rem < meta.authentication_data_block_size)
|
||||
return S_FALSE;
|
||||
const unsigned u = (unsigned)meta.authentication_data_block_size;
|
||||
offset += u;
|
||||
rem -= u;
|
||||
}
|
||||
|
||||
if (rem < meta.descriptors_offset ||
|
||||
rem - meta.descriptors_offset < meta.descriptors_size)
|
||||
return S_FALSE;
|
||||
rem = (unsigned)meta.descriptors_size;
|
||||
while (rem != 0)
|
||||
{
|
||||
if (rem < k_Descriptor_Size)
|
||||
return S_FALSE;
|
||||
AvbDescriptor desc;
|
||||
desc.Parse(buf + offset);
|
||||
offset += k_Descriptor_Size;
|
||||
rem -= k_Descriptor_Size;
|
||||
if (desc.Size > rem)
|
||||
return S_FALSE;
|
||||
const unsigned descSize = (unsigned)desc.Size;
|
||||
if (desc.Tag == AVB_DESCRIPTOR_TAG_HASHTREE)
|
||||
{
|
||||
if (descSize < k_Hashtree_Size_Min)
|
||||
return S_FALSE;
|
||||
AvbHashtreeDescriptor ht;
|
||||
ht.Parse(buf + offset);
|
||||
unsigned pos = k_Hashtree_Size_Min;
|
||||
|
||||
if (pos + ht.partition_name_len > descSize)
|
||||
return S_FALSE;
|
||||
Name.Empty(); // UTF-8
|
||||
AddNameToString(Name, buf + offset + pos, ht.partition_name_len, false);
|
||||
pos += ht.partition_name_len;
|
||||
|
||||
if (pos + ht.salt_len > descSize)
|
||||
return S_FALSE;
|
||||
CByteBuffer salt;
|
||||
salt.CopyFrom(buf + offset + pos, ht.salt_len);
|
||||
pos += ht.salt_len;
|
||||
|
||||
if (pos + ht.root_digest_len > descSize)
|
||||
return S_FALSE;
|
||||
CByteBuffer digest;
|
||||
digest.CopyFrom(buf + offset + pos, ht.root_digest_len);
|
||||
pos += ht.root_digest_len;
|
||||
// what is that digest?
|
||||
}
|
||||
else if (desc.Tag == AVB_DESCRIPTOR_TAG_PROPERTY)
|
||||
{
|
||||
if (descSize < k_PropertyDescriptor_Size_Min + 2)
|
||||
return S_FALSE;
|
||||
AvbPropertyDescriptor pt;
|
||||
pt.Parse(buf + offset);
|
||||
unsigned pos = k_PropertyDescriptor_Size_Min;
|
||||
|
||||
if (pt.key_num_bytes > descSize - pos - 1)
|
||||
return S_FALSE;
|
||||
AString key; // UTF-8
|
||||
AddNameToString(key, buf + offset + pos, (unsigned)pt.key_num_bytes, false);
|
||||
pos += (unsigned)pt.key_num_bytes + 1;
|
||||
|
||||
if (descSize < pos)
|
||||
return S_FALSE;
|
||||
if (pt.value_num_bytes > descSize - pos - 1)
|
||||
return S_FALSE;
|
||||
AString value; // UTF-8
|
||||
AddNameToString(value, buf + offset + pos, (unsigned)pt.value_num_bytes, false);
|
||||
pos += (unsigned)pt.value_num_bytes + 1;
|
||||
}
|
||||
offset += descSize;
|
||||
rem -= descSize;
|
||||
}
|
||||
|
||||
_phySize = fileSize;
|
||||
|
||||
// _startOffset = 0;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
try
|
||||
{
|
||||
if (Open2(stream) != S_OK)
|
||||
return S_FALSE;
|
||||
_stream = stream;
|
||||
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> parseStream;
|
||||
if (GetStream(0, &parseStream) == S_OK && parseStream)
|
||||
{
|
||||
const size_t kParseSize = 1 << 11;
|
||||
Byte buf[kParseSize];
|
||||
if (ReadStream_FAIL(parseStream, buf, kParseSize) == S_OK)
|
||||
{
|
||||
UInt64 extSize;
|
||||
if (NExt::IsArc_Ext_PhySize(buf, kParseSize, &extSize) == k_IsArc_Res_YES)
|
||||
if (extSize == Footer.original_image_size)
|
||||
Ext = "ext";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_stream.Release();
|
||||
// _startOffset = 0;
|
||||
_phySize = 0;
|
||||
Ext = NULL;
|
||||
Name.Empty();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidName
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidMainSubfile: prop = (UInt32)0; break;
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidName:
|
||||
{
|
||||
if (!Name.IsEmpty())
|
||||
{
|
||||
AString s (Name);
|
||||
s += ".avb";
|
||||
prop = s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
if (!Name.IsEmpty())
|
||||
{
|
||||
AString s (Name);
|
||||
s += '.';
|
||||
s += Ext ? Ext : "img";
|
||||
prop = s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kpidPackSize:
|
||||
case kpidSize:
|
||||
prop = Footer.original_image_size;
|
||||
break;
|
||||
case kpidExtension: prop = (Ext ? Ext : "img"); break;
|
||||
}
|
||||
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
REGISTER_ARC_I_NO_SIG(
|
||||
"AVB", "avb img", NULL, 0xc0,
|
||||
/* k_Signature, */
|
||||
0,
|
||||
/* NArcInfoFlags::kUseGlobalOffset | */
|
||||
NArcInfoFlags::kBackwardOpen
|
||||
,
|
||||
NULL)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,488 @@
|
||||
// Base64Handler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
#include "../Common/InBuffer.h"
|
||||
|
||||
/*
|
||||
spaces:
|
||||
9(TAB),10(LF),13(CR),32(SPACE)
|
||||
Non-breaking space:
|
||||
0xa0 : Unicode, Windows code pages 1250-1258
|
||||
0xff (unused): DOS code pages
|
||||
|
||||
end of stream markers: '=' (0x3d):
|
||||
"=" , if numBytes (% 3 == 2)
|
||||
"==" , if numBytes (% 3 == 1)
|
||||
*/
|
||||
|
||||
|
||||
static const Byte k_Base64Table[256] =
|
||||
{
|
||||
66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63,
|
||||
52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77,
|
||||
77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
|
||||
15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77,
|
||||
77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
|
||||
41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
65,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77
|
||||
};
|
||||
|
||||
static const unsigned k_Code_Equals = 64;
|
||||
static const unsigned k_Code_Space = 65;
|
||||
static const unsigned k_Code_Zero = 66;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Base64(const Byte *p, size_t size)
|
||||
{
|
||||
size_t num = 0;
|
||||
size_t firstSpace = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c < 64)
|
||||
{
|
||||
num++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == k_Code_Space)
|
||||
{
|
||||
if (p[-1] == ' ' && firstSpace == 0)
|
||||
firstSpace = num;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c != k_Code_Equals)
|
||||
return k_IsArc_Res_NO;
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
// we try to redece false positive detection here.
|
||||
// we don't expect space character in starting base64 line
|
||||
const unsigned kNumExpectedNonSpaceSyms = 20;
|
||||
if (firstSpace != 0 && firstSpace < num && firstSpace < kNumExpectedNonSpaceSyms)
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
|
||||
num &= 3;
|
||||
|
||||
if (num <= 1)
|
||||
return k_IsArc_Res_NO;
|
||||
if (num != 3)
|
||||
{
|
||||
if (size == 0)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c != k_Code_Equals)
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
return k_IsArc_Res_YES;
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum EBase64Res
|
||||
{
|
||||
k_Base64_RES_MaybeFinished,
|
||||
k_Base64_RES_Finished,
|
||||
k_Base64_RES_NeedMoreInput,
|
||||
k_Base64_RES_UnexpectedChar
|
||||
};
|
||||
|
||||
|
||||
static EBase64Res Base64ToBin(Byte *p, size_t size, const Byte **srcEnd, Byte **destEnd)
|
||||
{
|
||||
Byte *dest = p;
|
||||
UInt32 val = 1;
|
||||
EBase64Res res = k_Base64_RES_NeedMoreInput;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
if (val == 1)
|
||||
res = k_Base64_RES_MaybeFinished;
|
||||
break;
|
||||
}
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c < 64)
|
||||
{
|
||||
val = (val << 6) | c;
|
||||
if ((val & ((UInt32)1 << 24)) == 0)
|
||||
continue;
|
||||
dest[0] = (Byte)(val >> 16);
|
||||
dest[1] = (Byte)(val >> 8);
|
||||
dest[2] = (Byte)(val);
|
||||
dest += 3;
|
||||
val = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
|
||||
if (c == k_Code_Equals)
|
||||
{
|
||||
if (val >= (1 << 12))
|
||||
{
|
||||
if (val & (1 << 18))
|
||||
{
|
||||
res = k_Base64_RES_Finished;
|
||||
break;
|
||||
}
|
||||
if (size == 0)
|
||||
break;
|
||||
c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c == k_Code_Equals)
|
||||
{
|
||||
res = k_Base64_RES_Finished;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p--;
|
||||
res = k_Base64_RES_UnexpectedChar;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val >= ((UInt32)1 << 12))
|
||||
{
|
||||
if (val & (1 << 18))
|
||||
{
|
||||
*dest++ = (Byte)(val >> 10);
|
||||
val <<= 2;
|
||||
}
|
||||
*dest++ = (Byte)(val >> 4);
|
||||
}
|
||||
|
||||
*srcEnd = p;
|
||||
*destEnd = dest;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static const Byte *Base64_SkipSpaces(const Byte *p, size_t size)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
return p;
|
||||
const UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
return p - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the following function is used by DmgHandler.cpp
|
||||
|
||||
Byte *Base64ToBin(Byte *dest, const char *src);
|
||||
Byte *Base64ToBin(Byte *dest, const char *src)
|
||||
{
|
||||
UInt32 val = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const UInt32 c = k_Base64Table[(Byte)(*src++)];
|
||||
|
||||
if (c < 64)
|
||||
{
|
||||
val = (val << 6) | c;
|
||||
if ((val & ((UInt32)1 << 24)) == 0)
|
||||
continue;
|
||||
dest[0] = (Byte)(val >> 16);
|
||||
dest[1] = (Byte)(val >> 8);
|
||||
dest[2] = (Byte)(val);
|
||||
dest += 3;
|
||||
val = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
|
||||
if (c == k_Code_Equals)
|
||||
break;
|
||||
|
||||
if (c == k_Code_Zero && val == 1) // end of string
|
||||
return dest;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (val < (1 << 12))
|
||||
return NULL;
|
||||
|
||||
if (val & (1 << 18))
|
||||
{
|
||||
*dest++ = (Byte)(val >> 10);
|
||||
val <<= 2;
|
||||
}
|
||||
else if (k_Base64Table[(Byte)(*src++)] != k_Code_Equals)
|
||||
return NULL;
|
||||
*dest++ = (Byte)(val >> 4);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const Byte c = k_Base64Table[(Byte)(*src++)];
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
if (c == k_Code_Zero)
|
||||
return dest;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace NArchive {
|
||||
namespace NBase64 {
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_0
|
||||
|
||||
bool _isArc;
|
||||
UInt64 _phySize;
|
||||
size_t _size;
|
||||
EBase64Res _sres;
|
||||
CByteBuffer _data;
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (v != 0)
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
// COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize: prop = (UInt64)_size; break;
|
||||
case kpidPackSize: prop = _phySize; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
static HRESULT ReadStream_OpenProgress(ISequentialInStream *stream, void *data, size_t size, IArchiveOpenCallback *openCallback) throw()
|
||||
{
|
||||
UInt64 bytes = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
const UInt32 kBlockSize = ((UInt32)1 << 24);
|
||||
const UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
|
||||
UInt32 processedSizeLoc;
|
||||
RINOK(stream->Read(data, curSize, &processedSizeLoc))
|
||||
if (processedSizeLoc == 0)
|
||||
return E_FAIL;
|
||||
data = (void *)((Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
bytes += processedSizeLoc;
|
||||
const UInt64 files = 1;
|
||||
RINOK(openCallback->SetCompleted(&files, &bytes))
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
Close();
|
||||
{
|
||||
const unsigned kStartSize = 1 << 12;
|
||||
_data.Alloc(kStartSize);
|
||||
size_t size = kStartSize;
|
||||
RINOK(ReadStream(stream, _data, &size))
|
||||
if (IsArc_Base64(_data, size) == k_IsArc_Res_NO)
|
||||
return S_FALSE;
|
||||
}
|
||||
_isArc = true;
|
||||
|
||||
UInt64 packSize64;
|
||||
RINOK(InStream_GetSize_SeekToEnd(stream, packSize64))
|
||||
if (packSize64 == 0)
|
||||
return S_FALSE;
|
||||
size_t curSize = 1 << 16;
|
||||
if (curSize > packSize64)
|
||||
curSize = (size_t)packSize64;
|
||||
const unsigned kLogStep = 4;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RINOK(InStream_SeekSet(stream, 0))
|
||||
|
||||
_data.Alloc(curSize);
|
||||
RINOK(ReadStream_OpenProgress(stream, _data, curSize, openCallback))
|
||||
|
||||
const Byte *srcEnd;
|
||||
Byte *dest;
|
||||
_sres = Base64ToBin(_data, curSize, &srcEnd, &dest);
|
||||
_size = (size_t)(dest - _data);
|
||||
const size_t mainSize = (size_t)(srcEnd - _data);
|
||||
_phySize = mainSize;
|
||||
if (_sres == k_Base64_RES_UnexpectedChar)
|
||||
break;
|
||||
if (curSize != mainSize)
|
||||
{
|
||||
const Byte *end2 = Base64_SkipSpaces(srcEnd, curSize - mainSize);
|
||||
if ((size_t)(end2 - _data) != curSize)
|
||||
break;
|
||||
_phySize = curSize;
|
||||
}
|
||||
|
||||
if (curSize == packSize64)
|
||||
break;
|
||||
|
||||
UInt64 curSize64 = packSize64;
|
||||
if (curSize < (packSize64 >> kLogStep))
|
||||
curSize64 = (UInt64)curSize << kLogStep;
|
||||
curSize = (size_t)curSize64;
|
||||
if (curSize != curSize64)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
if (_size == 0)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_phySize = 0;
|
||||
_size = 0;
|
||||
_isArc = false;
|
||||
_sres = k_Base64_RES_MaybeFinished;
|
||||
_data.Free();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
RINOK(extractCallback->SetTotal(_size))
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(extractCallback, false);
|
||||
// RINOK(lps->SetCur())
|
||||
Int32 opRes;
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
|
||||
if (!testMode && !realOutStream)
|
||||
return S_OK;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
if (realOutStream)
|
||||
{
|
||||
RINOK(WriteStream(realOutStream, (const Byte *)_data, _size))
|
||||
}
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
if (_sres != k_Base64_RES_Finished)
|
||||
{
|
||||
if (_sres == k_Base64_RES_NeedMoreInput)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (_sres == k_Base64_RES_UnexpectedChar)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
}
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(opRes))
|
||||
lps->InSize = _phySize;
|
||||
lps->OutSize = _size;
|
||||
return lps->SetCur();
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
REGISTER_ARC_I_NO_SIG(
|
||||
"Base64", "b64", NULL, 0xC5,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName
|
||||
| NArcInfoFlags::kStartOpen
|
||||
| NArcInfoFlags::kByExtOnlyOpen,
|
||||
IsArc_Base64)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,482 @@
|
||||
// Bz2Handler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/BZip2Decoder.h"
|
||||
#include "../Compress/BZip2Encoder.h"
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
#include "Common/DummyOutStream.h"
|
||||
#include "Common/HandlerOut.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NBz2 {
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_3(
|
||||
IArchiveOpenSeq,
|
||||
IOutArchive,
|
||||
ISetProperties
|
||||
)
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CMyComPtr<ISequentialInStream> _seqStream;
|
||||
|
||||
bool _isArc;
|
||||
bool _needSeekToStart;
|
||||
bool _dataAfterEnd;
|
||||
bool _needMoreInput;
|
||||
|
||||
bool _packSize_Defined;
|
||||
bool _unpackSize_Defined;
|
||||
bool _numStreams_Defined;
|
||||
bool _numBlocks_Defined;
|
||||
|
||||
UInt64 _packSize;
|
||||
UInt64 _unpackSize;
|
||||
UInt64 _numStreams;
|
||||
UInt64 _numBlocks;
|
||||
|
||||
CSingleMethodProps _props;
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidSize,
|
||||
kpidPackSize
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidNumStreams,
|
||||
kpidNumBlocks
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
|
||||
case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
|
||||
case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
|
||||
case kpidNumBlocks: if (_numBlocks_Defined) prop = _numBlocks; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
|
||||
case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;
|
||||
default: break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const unsigned kSignatureCheckSize = 10;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_BZip2(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < kSignatureCheckSize)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (p[0] != 'B' || p[1] != 'Z' || p[2] != 'h' || p[3] < '1' || p[3] > '9')
|
||||
return k_IsArc_Res_NO;
|
||||
p += 4;
|
||||
if (NCompress::NBZip2::IsBlockSig(p))
|
||||
return k_IsArc_Res_YES;
|
||||
if (NCompress::NBZip2::IsEndSig(p))
|
||||
return k_IsArc_Res_YES;
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
{
|
||||
Byte buf[kSignatureCheckSize];
|
||||
RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize))
|
||||
if (IsArc_BZip2(buf, kSignatureCheckSize) == k_IsArc_Res_NO)
|
||||
return S_FALSE;
|
||||
_isArc = true;
|
||||
_stream = stream;
|
||||
_seqStream = stream;
|
||||
_needSeekToStart = true;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
|
||||
{
|
||||
Close();
|
||||
_isArc = true;
|
||||
_seqStream = stream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_isArc = false;
|
||||
_needSeekToStart = false;
|
||||
_dataAfterEnd = false;
|
||||
_needMoreInput = false;
|
||||
|
||||
_packSize_Defined = false;
|
||||
_unpackSize_Defined = false;
|
||||
_numStreams_Defined = false;
|
||||
_numBlocks_Defined = false;
|
||||
|
||||
_packSize = 0;
|
||||
|
||||
_seqStream.Release();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_packSize_Defined)
|
||||
{
|
||||
RINOK(extractCallback->SetTotal(_packSize))
|
||||
}
|
||||
|
||||
Int32 opRes;
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
|
||||
if (!testMode && !realOutStream)
|
||||
return S_OK;
|
||||
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
|
||||
if (_needSeekToStart)
|
||||
{
|
||||
if (!_stream)
|
||||
return E_FAIL;
|
||||
RINOK(InStream_SeekToBegin(_stream))
|
||||
}
|
||||
else
|
||||
_needSeekToStart = true;
|
||||
|
||||
// try {
|
||||
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CDecoder> decoder;
|
||||
|
||||
#ifndef Z7_ST
|
||||
RINOK(decoder->SetNumberOfThreads(_props._numThreads))
|
||||
#endif
|
||||
|
||||
CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
|
||||
outStream->SetStream(realOutStream);
|
||||
outStream->Init();
|
||||
// realOutStream.Release();
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(extractCallback, true);
|
||||
|
||||
decoder->FinishMode = true;
|
||||
decoder->Base.DecodeAllStreams = true;
|
||||
|
||||
_dataAfterEnd = false;
|
||||
_needMoreInput = false;
|
||||
|
||||
HRESULT result = decoder.Interface()->Code(_seqStream, outStream, NULL, NULL, lps);
|
||||
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
return result;
|
||||
|
||||
if (decoder->Base.NumStreams == 0)
|
||||
{
|
||||
_isArc = false;
|
||||
result = S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const UInt64 inProcessedSize = decoder->GetInputProcessedSize();
|
||||
UInt64 packSize = inProcessedSize;
|
||||
|
||||
if (decoder->Base.NeedMoreInput)
|
||||
_needMoreInput = true;
|
||||
|
||||
if (!decoder->Base.IsBz)
|
||||
{
|
||||
packSize = decoder->Base.FinishedPackSize;
|
||||
if (packSize != inProcessedSize)
|
||||
_dataAfterEnd = true;
|
||||
}
|
||||
|
||||
_packSize = packSize;
|
||||
_unpackSize = decoder->GetOutProcessedSize();
|
||||
_numStreams = decoder->Base.NumStreams;
|
||||
_numBlocks = decoder->GetNumBlocks();
|
||||
|
||||
_packSize_Defined = true;
|
||||
_unpackSize_Defined = true;
|
||||
_numStreams_Defined = true;
|
||||
_numBlocks_Defined = true;
|
||||
|
||||
// RINOK(
|
||||
lps.Interface()->SetRatioInfo(&packSize, &_unpackSize);
|
||||
}
|
||||
|
||||
// outStream.Release();
|
||||
|
||||
if (!_isArc)
|
||||
opRes = NExtract::NOperationResult::kIsNotArc;
|
||||
else if (_needMoreInput)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (decoder->GetCrcError())
|
||||
opRes = NExtract::NOperationResult::kCRCError;
|
||||
else if (_dataAfterEnd)
|
||||
opRes = NExtract::NOperationResult::kDataAfterEnd;
|
||||
else if (result == S_FALSE)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (decoder->Base.MinorError)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (result == S_OK)
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
else
|
||||
return result;
|
||||
|
||||
}
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
|
||||
// } catch(...) { return E_FAIL; }
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
|
||||
{
|
||||
return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value);
|
||||
}
|
||||
|
||||
static HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
|
||||
{
|
||||
return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value);
|
||||
}
|
||||
|
||||
static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,
|
||||
const UInt64 *unpackSize,
|
||||
const UInt64 *numBlocks)
|
||||
{
|
||||
NCOM::CPropVariant sizeProp;
|
||||
if (unpackSize)
|
||||
{
|
||||
sizeProp = *unpackSize;
|
||||
RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp));
|
||||
RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
|
||||
if (unpackSize)
|
||||
{
|
||||
RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp));
|
||||
}
|
||||
if (numBlocks)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
prop = *numBlocks;
|
||||
RINOK(ReportArcProp(reportArcProp, kpidNumBlocks, &prop));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
static HRESULT UpdateArchive(
|
||||
UInt64 unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
const CProps &props,
|
||||
IArchiveUpdateCallback *updateCallback
|
||||
// , ArchiveUpdateCallbackArcProp *reportArcProp
|
||||
)
|
||||
{
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
RINOK(updateCallback->GetStream(0, &fileInStream))
|
||||
if (!fileInStream)
|
||||
return S_FALSE;
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
IStreamGetSize,
|
||||
streamGetSize, fileInStream)
|
||||
if (streamGetSize)
|
||||
{
|
||||
UInt64 size;
|
||||
if (streamGetSize->GetSize(&size) == S_OK)
|
||||
unpackSize = size;
|
||||
}
|
||||
}
|
||||
RINOK(updateCallback->SetTotal(unpackSize))
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(updateCallback, true);
|
||||
{
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CEncoder> encoder;
|
||||
RINOK(props.SetCoderProps(encoder.ClsPtr(), NULL))
|
||||
RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))
|
||||
/*
|
||||
if (reportArcProp)
|
||||
{
|
||||
unpackSize = encoderSpec->GetInProcessedSize();
|
||||
RINOK(ReportArcProps(reportArcProp, &unpackSize, &encoderSpec->NumBlocks));
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))
|
||||
{
|
||||
*timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType;
|
||||
// *timeType = NFileTimeType::kUnix;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
if (numItems != 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
IStreamSetRestriction,
|
||||
setRestriction, outStream)
|
||||
if (setRestriction)
|
||||
RINOK(setRestriction->SetRestriction(0, 0))
|
||||
}
|
||||
|
||||
Int32 newData, newProps;
|
||||
UInt32 indexInArchive;
|
||||
if (!updateCallback)
|
||||
return E_FAIL;
|
||||
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))
|
||||
|
||||
// Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp, reportArcProp, updateCallback)
|
||||
|
||||
if (IntToBool(newProps))
|
||||
{
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))
|
||||
if (prop.vt != VT_EMPTY)
|
||||
if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (IntToBool(newData))
|
||||
{
|
||||
UInt64 size;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidSize, &prop))
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
size = prop.uhVal.QuadPart;
|
||||
}
|
||||
|
||||
CMethodProps props2 = _props;
|
||||
#ifndef Z7_ST
|
||||
props2.AddProp_NumThreads(_props._numThreads);
|
||||
#ifdef _WIN32
|
||||
if (_props._numThreadGroups > 1)
|
||||
props2.AddProp32(NCoderPropID::kNumThreadGroups, _props._numThreadGroups);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return UpdateArchive(size, outStream, props2, updateCallback);
|
||||
}
|
||||
|
||||
if (indexInArchive != 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(updateCallback, true);
|
||||
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
IArchiveUpdateCallbackFile,
|
||||
opCallback, updateCallback)
|
||||
if (opCallback)
|
||||
{
|
||||
RINOK(opCallback->ReportOperation(
|
||||
NEventIndexType::kInArcIndex, 0,
|
||||
NUpdateNotifyOp::kReplicate))
|
||||
}
|
||||
|
||||
if (_stream)
|
||||
RINOK(InStream_SeekToBegin(_stream))
|
||||
|
||||
return NCompress::CopyStream(_stream, outStream, lps);
|
||||
|
||||
// return ReportArcProps(reportArcProp, NULL, NULL);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
|
||||
{
|
||||
return _props.SetProperties(names, values, numProps);
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = { 'B', 'Z', 'h' };
|
||||
|
||||
REGISTER_ARC_IO(
|
||||
"bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName
|
||||
, 0
|
||||
, IsArc_BZip2)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,122 @@
|
||||
// CabBlockInStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "CabBlockInStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
static const UInt32 kBlockSize = 1 << 16;
|
||||
static const unsigned k_OverReadPadZone_Size = 32;
|
||||
static const unsigned kHeaderSize = 8;
|
||||
static const unsigned kReservedMax = 256;
|
||||
static const unsigned kHeaderOffset = kBlockSize + k_OverReadPadZone_Size;
|
||||
|
||||
bool CBlockPackData::Create() throw()
|
||||
{
|
||||
if (!_buf)
|
||||
_buf = (Byte *)z7_AlignedAlloc(kBlockSize + k_OverReadPadZone_Size + kHeaderSize + kReservedMax);
|
||||
return _buf != NULL;
|
||||
}
|
||||
|
||||
CBlockPackData::~CBlockPackData() throw()
|
||||
{
|
||||
z7_AlignedFree(_buf);
|
||||
}
|
||||
|
||||
static UInt32 CheckSum(const Byte *p, UInt32 size) throw()
|
||||
{
|
||||
#ifdef MY_CPU_64BIT
|
||||
|
||||
UInt64 sum64 = 0;
|
||||
if (size >= 16)
|
||||
{
|
||||
const Byte *lim = p + (size_t)size - 16;
|
||||
do
|
||||
{
|
||||
sum64 ^= GetUi64(p) ^ GetUi64(p + 8);
|
||||
p += 16;
|
||||
}
|
||||
while (p <= lim);
|
||||
size = (UInt32)(lim + 16 - p);
|
||||
}
|
||||
if (size >= 8)
|
||||
{
|
||||
sum64 ^= GetUi64(p);
|
||||
p += 8;
|
||||
size -= 8;
|
||||
}
|
||||
|
||||
UInt32 sum = (UInt32)(sum64 >> 32) ^ (UInt32)sum64;
|
||||
|
||||
#else
|
||||
|
||||
UInt32 sum = 0;
|
||||
if (size >= 16)
|
||||
{
|
||||
const Byte *lim = p + (size_t)size - 16;
|
||||
do
|
||||
{
|
||||
sum ^= GetUi32(p)
|
||||
^ GetUi32(p + 4)
|
||||
^ GetUi32(p + 8)
|
||||
^ GetUi32(p + 12);
|
||||
p += 16;
|
||||
}
|
||||
while (p <= lim);
|
||||
size = (UInt32)(lim + 16 - p);
|
||||
}
|
||||
if (size >= 8)
|
||||
{
|
||||
sum ^= GetUi32(p + 0) ^ GetUi32(p + 4);
|
||||
p += 8;
|
||||
size -= 8;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (size >= 4)
|
||||
{
|
||||
sum ^= GetUi32(p);
|
||||
p += 4;
|
||||
}
|
||||
if (size &= 3)
|
||||
{
|
||||
if (size >= 2)
|
||||
{
|
||||
if (size > 2)
|
||||
sum ^= (UInt32)(*p++) << 16;
|
||||
sum ^= (UInt32)(*p++) << 8;
|
||||
}
|
||||
sum ^= (UInt32)(*p++);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CBlockPackData::Read(ISequentialInStream *stream, Byte ReservedSize, UInt32 &packSizeRes, UInt32 &unpackSize) throw()
|
||||
{
|
||||
const UInt32 reserved8 = kHeaderSize + ReservedSize;
|
||||
const Byte *header = _buf + kHeaderOffset;
|
||||
RINOK(ReadStream_FALSE(stream, (void *)header, reserved8))
|
||||
unpackSize = GetUi16a(header + 6);
|
||||
const UInt32 packSize = GetUi16a(header + 4);
|
||||
packSizeRes = packSize;
|
||||
if (packSize > kBlockSize - _size)
|
||||
return S_FALSE;
|
||||
RINOK(ReadStream_FALSE(stream, _buf + _size, packSize))
|
||||
memset(_buf + _size + packSize, 0xff, k_OverReadPadZone_Size);
|
||||
if (*(const UInt32 *)(const void *)header != 0) // checkSum
|
||||
if (CheckSum(header, reserved8) != CheckSum(_buf + _size, packSize))
|
||||
return S_FALSE;
|
||||
_size += packSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,28 @@
|
||||
// CabBlockInStream.h
|
||||
|
||||
#ifndef ZIP7_INC_CAB_BLOCK_IN_STREAM_H
|
||||
#define ZIP7_INC_CAB_BLOCK_IN_STREAM_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CBlockPackData
|
||||
{
|
||||
Byte *_buf;
|
||||
UInt32 _size;
|
||||
public:
|
||||
CBlockPackData(): _buf(NULL), _size(0) {}
|
||||
~CBlockPackData() throw();
|
||||
bool Create() throw();
|
||||
void InitForNewBlock() { _size = 0; }
|
||||
HRESULT Read(ISequentialInStream *stream, Byte ReservedSize, UInt32 &packSize, UInt32 &unpackSize) throw();
|
||||
UInt32 GetPackSize() const { return _size; }
|
||||
// 32 bytes of overread zone is available after PackSize:
|
||||
const Byte *GetData() const { return _buf; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
// CabHandler.h
|
||||
|
||||
#ifndef ZIP7_INC_CAB_HANDLER_H
|
||||
#define ZIP7_INC_CAB_HANDLER_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "CabIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_0
|
||||
|
||||
CMvDatabaseEx m_Database;
|
||||
UString _errorMessage;
|
||||
bool _isArc;
|
||||
bool _errorInHeaders;
|
||||
bool _unexpectedEnd;
|
||||
// int _mainVolIndex;
|
||||
UInt32 _phySize;
|
||||
UInt64 _offset;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
// CabHeader.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CabHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NHeader {
|
||||
|
||||
const Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
|
||||
|
||||
// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer;
|
||||
|
||||
}}}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Archive/CabHeader.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_CAB_HEADER_H
|
||||
#define ZIP7_INC_ARCHIVE_CAB_HEADER_H
|
||||
|
||||
#include "../../../Common/MyTypes.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NHeader {
|
||||
|
||||
const unsigned kMarkerSize = 8;
|
||||
extern const Byte kMarker[kMarkerSize];
|
||||
|
||||
namespace NArcFlags
|
||||
{
|
||||
const unsigned kPrevCabinet = 1;
|
||||
const unsigned kNextCabinet = 2;
|
||||
const unsigned kReservePresent = 4;
|
||||
}
|
||||
|
||||
namespace NMethod
|
||||
{
|
||||
const Byte kNone = 0;
|
||||
const Byte kMSZip = 1;
|
||||
const Byte kQuantum = 2;
|
||||
const Byte kLZX = 3;
|
||||
}
|
||||
|
||||
const unsigned kFileNameIsUtf8_Mask = 0x80;
|
||||
|
||||
namespace NFolderIndex
|
||||
{
|
||||
const unsigned kContinuedFromPrev = 0xFFFD;
|
||||
const unsigned kContinuedToNext = 0xFFFE;
|
||||
const unsigned kContinuedPrevAndNext = 0xFFFF;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,490 @@
|
||||
// Archive/CabIn.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "CabIn.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
struct CUnexpectedEndException {};
|
||||
|
||||
void CInArchive::Skip(unsigned size)
|
||||
{
|
||||
if (_inBuffer.Skip(size) != size)
|
||||
throw CUnexpectedEndException();
|
||||
}
|
||||
|
||||
void CInArchive::Read(Byte *data, unsigned size)
|
||||
{
|
||||
if (_inBuffer.ReadBytes(data, size) != size)
|
||||
throw CUnexpectedEndException();
|
||||
}
|
||||
|
||||
void CInArchive::ReadName(AString &s)
|
||||
{
|
||||
for (size_t i = 0; i < ((size_t)1 << 13); i++)
|
||||
{
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
throw CUnexpectedEndException();
|
||||
if (b == 0)
|
||||
{
|
||||
s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i);
|
||||
return;
|
||||
}
|
||||
if (_tempBuf.Size() == i)
|
||||
_tempBuf.ChangeSize_KeepData(i * 2, i);
|
||||
_tempBuf[i] = b;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
throw CUnexpectedEndException();
|
||||
if (b == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInNames = true;
|
||||
s = "[ERROR-LONG-PATH]";
|
||||
}
|
||||
|
||||
void CInArchive::ReadOtherArc(COtherArc &oa)
|
||||
{
|
||||
ReadName(oa.FileName);
|
||||
ReadName(oa.DiskName);
|
||||
}
|
||||
|
||||
|
||||
struct CSignatureFinder
|
||||
{
|
||||
Byte *Buf;
|
||||
UInt32 Pos;
|
||||
UInt32 End;
|
||||
const Byte *Signature;
|
||||
UInt32 SignatureSize;
|
||||
|
||||
UInt32 _headerSize;
|
||||
UInt32 _alignSize;
|
||||
UInt32 _bufUseCapacity;
|
||||
|
||||
const UInt64 *SearchLimit;
|
||||
ISequentialInStream *Stream;
|
||||
UInt64 Processed; // Global offset of start of Buf
|
||||
|
||||
UInt32 GetTotalCapacity(UInt32 basicSize, UInt32 headerSize)
|
||||
{
|
||||
_headerSize = headerSize;
|
||||
for (_alignSize = (1 << 5); _alignSize < _headerSize; _alignSize <<= 1);
|
||||
_bufUseCapacity = basicSize + _alignSize;
|
||||
return _bufUseCapacity + 16;
|
||||
}
|
||||
|
||||
/*
|
||||
returns:
|
||||
S_OK - signature found (at Pos)
|
||||
S_FALSE - signature not found
|
||||
*/
|
||||
HRESULT Find();
|
||||
};
|
||||
|
||||
|
||||
HRESULT CSignatureFinder::Find()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Buf[End] = Signature[0]; // it's for fast search;
|
||||
|
||||
while (End - Pos >= _headerSize)
|
||||
{
|
||||
const Byte *p = Buf + Pos;
|
||||
const Byte b = Signature[0];
|
||||
for (;;)
|
||||
{
|
||||
if (*p == b) { break; } p++;
|
||||
if (*p == b) { break; } p++;
|
||||
}
|
||||
Pos = (UInt32)(p - Buf);
|
||||
if (End - Pos < _headerSize)
|
||||
{
|
||||
Pos = End - _headerSize + 1;
|
||||
break;
|
||||
}
|
||||
UInt32 i;
|
||||
for (i = 1; i < SignatureSize && p[i] == Signature[i]; i++);
|
||||
if (i == SignatureSize)
|
||||
return S_OK;
|
||||
Pos++;
|
||||
}
|
||||
|
||||
if (Pos >= _alignSize)
|
||||
{
|
||||
const UInt32 num = (Pos & ~(_alignSize - 1));
|
||||
Processed += num;
|
||||
Pos -= num;
|
||||
End -= num;
|
||||
memmove(Buf, Buf + num, End);
|
||||
}
|
||||
UInt32 rem = _bufUseCapacity - End;
|
||||
if (SearchLimit)
|
||||
{
|
||||
if (Processed + Pos > *SearchLimit)
|
||||
return S_FALSE;
|
||||
const UInt64 rem2 = *SearchLimit - (Processed + End) + _headerSize;
|
||||
if (rem > rem2)
|
||||
rem = (UInt32)rem2;
|
||||
}
|
||||
|
||||
UInt32 processedSize;
|
||||
if (Processed == 0 && rem == _bufUseCapacity - _headerSize)
|
||||
rem -= _alignSize; // to make reads more aligned.
|
||||
RINOK(Stream->Read(Buf + End, rem, &processedSize))
|
||||
if (processedSize == 0)
|
||||
return S_FALSE;
|
||||
End += processedSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CInArcInfo::Parse(const Byte *p)
|
||||
{
|
||||
if (Get32(p + 0x0C) != 0 ||
|
||||
Get32(p + 0x14) != 0)
|
||||
return false;
|
||||
Size = Get32(p + 8);
|
||||
if (Size < 36)
|
||||
return false;
|
||||
Flags = Get16(p + 0x1E);
|
||||
if (Flags > 7)
|
||||
return false;
|
||||
FileHeadersOffset = Get32(p + 0x10);
|
||||
if (FileHeadersOffset != 0 && FileHeadersOffset > Size)
|
||||
return false;
|
||||
VersionMinor = p[0x18];
|
||||
VersionMajor = p[0x19];
|
||||
NumFolders = Get16(p + 0x1A);
|
||||
NumFiles = Get16(p + 0x1C);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
IsArc = false;
|
||||
ErrorInNames = false;
|
||||
UnexpectedEnd = false;
|
||||
HeaderError = false;
|
||||
|
||||
db.Clear();
|
||||
RINOK(InStream_GetPos(db.Stream, db.StartPosition))
|
||||
// UInt64 temp = db.StartPosition;
|
||||
|
||||
CByteBuffer buffer;
|
||||
CInArcInfo &ai = db.ArcInfo;
|
||||
UInt64 startInBuf = 0;
|
||||
|
||||
CLimitedSequentialInStream *limitedStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialInStream> limitedStream;
|
||||
|
||||
// for (int iii = 0; iii < 10000; iii++)
|
||||
{
|
||||
// db.StartPosition = temp; RINOK(InStream_SeekSet(db.Stream, db.StartPosition))
|
||||
|
||||
const UInt32 kMainHeaderSize = 32;
|
||||
Byte header[kMainHeaderSize];
|
||||
const UInt32 kBufSize = 1 << 15;
|
||||
RINOK(ReadStream_FALSE(db.Stream, header, kMainHeaderSize))
|
||||
if (memcmp(header, NHeader::kMarker, NHeader::kMarkerSize) == 0 && ai.Parse(header))
|
||||
{
|
||||
limitedStreamSpec = new CLimitedSequentialInStream;
|
||||
limitedStream = limitedStreamSpec;
|
||||
limitedStreamSpec->SetStream(db.Stream);
|
||||
limitedStreamSpec->Init(ai.Size - NHeader::kMarkerSize);
|
||||
buffer.Alloc(kBufSize);
|
||||
memcpy(buffer, header, kMainHeaderSize);
|
||||
UInt32 numProcessedBytes;
|
||||
RINOK(limitedStream->Read(buffer + kMainHeaderSize, kBufSize - kMainHeaderSize, &numProcessedBytes))
|
||||
_inBuffer.SetBuf(buffer, (UInt32)kBufSize, kMainHeaderSize + numProcessedBytes, kMainHeaderSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
|
||||
return S_FALSE;
|
||||
|
||||
CSignatureFinder finder;
|
||||
|
||||
finder.Stream = db.Stream;
|
||||
finder.Signature = NHeader::kMarker;
|
||||
finder.SignatureSize = NHeader::kMarkerSize;
|
||||
finder.SearchLimit = searchHeaderSizeLimit;
|
||||
|
||||
buffer.Alloc(finder.GetTotalCapacity(kBufSize, kMainHeaderSize));
|
||||
finder.Buf = buffer;
|
||||
|
||||
memcpy(buffer, header, kMainHeaderSize);
|
||||
finder.Processed = db.StartPosition;
|
||||
finder.End = kMainHeaderSize;
|
||||
finder.Pos = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RINOK(finder.Find())
|
||||
if (ai.Parse(finder.Buf + finder.Pos))
|
||||
{
|
||||
db.StartPosition = finder.Processed + finder.Pos;
|
||||
limitedStreamSpec = new CLimitedSequentialInStream;
|
||||
limitedStreamSpec->SetStream(db.Stream);
|
||||
limitedStream = limitedStreamSpec;
|
||||
const UInt32 remInFinder = finder.End - finder.Pos;
|
||||
if (ai.Size <= remInFinder)
|
||||
{
|
||||
limitedStreamSpec->Init(0);
|
||||
finder.End = finder.Pos + ai.Size;
|
||||
}
|
||||
else
|
||||
limitedStreamSpec->Init(ai.Size - remInFinder);
|
||||
|
||||
startInBuf = finder.Pos;
|
||||
_inBuffer.SetBuf(buffer, (UInt32)kBufSize, finder.End, finder.Pos + kMainHeaderSize);
|
||||
break;
|
||||
}
|
||||
finder.Pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IsArc = true;
|
||||
|
||||
_inBuffer.SetStream(limitedStream);
|
||||
if (_tempBuf.Size() == 0)
|
||||
_tempBuf.Alloc(1 << 12);
|
||||
|
||||
Byte p[16];
|
||||
const unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0);
|
||||
Read(p, nextSize);
|
||||
ai.SetID = Get16(p);
|
||||
ai.CabinetNumber = Get16(p + 2);
|
||||
|
||||
if (ai.ReserveBlockPresent())
|
||||
{
|
||||
ai.PerCabinet_AreaSize = Get16(p + 4);
|
||||
ai.PerFolder_AreaSize = p[6];
|
||||
ai.PerDataBlock_AreaSize = p[7];
|
||||
Skip(ai.PerCabinet_AreaSize);
|
||||
}
|
||||
|
||||
if (ai.IsTherePrev()) ReadOtherArc(ai.PrevArc);
|
||||
if (ai.IsThereNext()) ReadOtherArc(ai.NextArc);
|
||||
|
||||
UInt32 i;
|
||||
|
||||
db.Folders.ClearAndReserve(ai.NumFolders);
|
||||
|
||||
for (i = 0; i < ai.NumFolders; i++)
|
||||
{
|
||||
Read(p, 8);
|
||||
CFolder folder;
|
||||
folder.DataStart = Get32(p);
|
||||
folder.NumDataBlocks = Get16(p + 4);
|
||||
folder.MethodMajor = p[6];
|
||||
folder.MethodMinor = p[7];
|
||||
Skip(ai.PerFolder_AreaSize);
|
||||
db.Folders.AddInReserved(folder);
|
||||
}
|
||||
|
||||
// for (int iii = 0; iii < 10000; iii++) {
|
||||
|
||||
if (_inBuffer.GetProcessedSize() - startInBuf != ai.FileHeadersOffset)
|
||||
{
|
||||
// printf("\n!!! Seek Error !!!!\n");
|
||||
// fflush(stdout);
|
||||
RINOK(InStream_SeekSet(db.Stream, db.StartPosition + ai.FileHeadersOffset))
|
||||
limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset);
|
||||
_inBuffer.Init();
|
||||
}
|
||||
|
||||
db.Items.ClearAndReserve(ai.NumFiles);
|
||||
|
||||
for (i = 0; i < ai.NumFiles; i++)
|
||||
{
|
||||
Read(p, 16);
|
||||
CItem &item = db.Items.AddNewInReserved();
|
||||
item.Size = Get32(p);
|
||||
item.Offset = Get32(p + 4);
|
||||
item.FolderIndex = Get16(p + 8);
|
||||
const UInt16 pureDate = Get16(p + 10);
|
||||
const UInt16 pureTime = Get16(p + 12);
|
||||
item.Time = (((UInt32)pureDate << 16)) | pureTime;
|
||||
item.Attributes = Get16(p + 14);
|
||||
|
||||
ReadName(item.Name);
|
||||
|
||||
if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size())
|
||||
{
|
||||
HeaderError = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Open2(db, searchHeaderSizeLimit);
|
||||
}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }
|
||||
|
||||
static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
|
||||
{
|
||||
const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;
|
||||
const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];
|
||||
const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];
|
||||
const CItem &item1 = db1.Items[p1->ItemIndex];
|
||||
const CItem &item2 = db2.Items[p2->ItemIndex];
|
||||
const bool isDir1 = item1.IsDir();
|
||||
const bool isDir2 = item2.IsDir();
|
||||
if (isDir1 && !isDir2) return -1;
|
||||
if (isDir2 && !isDir1) return 1;
|
||||
const int f1 = mvDb.GetFolderIndex(p1);
|
||||
const int f2 = mvDb.GetFolderIndex(p2);
|
||||
RINOZ(MyCompare(f1, f2))
|
||||
RINOZ(MyCompare(item1.Offset, item2.Offset))
|
||||
RINOZ(MyCompare(item1.Size, item2.Size))
|
||||
RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex))
|
||||
return MyCompare(p1->ItemIndex, p2->ItemIndex);
|
||||
}
|
||||
|
||||
|
||||
bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)
|
||||
{
|
||||
const CMvItem *p1 = &Items[i1];
|
||||
const CMvItem *p2 = &Items[i2];
|
||||
const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];
|
||||
const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];
|
||||
const CItem &item1 = db1.Items[p1->ItemIndex];
|
||||
const CItem &item2 = db2.Items[p2->ItemIndex];
|
||||
return GetFolderIndex(p1) == GetFolderIndex(p2)
|
||||
&& item1.Offset == item2.Offset
|
||||
&& item1.Size == item2.Size
|
||||
&& item1.Name == item2.Name;
|
||||
}
|
||||
|
||||
|
||||
void CMvDatabaseEx::FillSortAndShrink()
|
||||
{
|
||||
Items.Clear();
|
||||
StartFolderOfVol.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
|
||||
int offset = 0;
|
||||
|
||||
FOR_VECTOR (v, Volumes)
|
||||
{
|
||||
const CDatabaseEx &db = Volumes[v];
|
||||
int curOffset = offset;
|
||||
if (db.IsTherePrevFolder())
|
||||
curOffset--;
|
||||
StartFolderOfVol.Add(curOffset);
|
||||
offset += db.GetNumberOfNewFolders();
|
||||
|
||||
CMvItem mvItem;
|
||||
mvItem.VolumeIndex = v;
|
||||
FOR_VECTOR (i, db.Items)
|
||||
{
|
||||
mvItem.ItemIndex = i;
|
||||
Items.Add(mvItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (Items.Size() > 1)
|
||||
{
|
||||
Items.Sort(CompareMvItems, (void *)this);
|
||||
unsigned j = 1;
|
||||
unsigned i = 1;
|
||||
for (; i < Items.Size(); i++)
|
||||
if (!AreItemsEqual(i, i - 1))
|
||||
Items[j++] = Items[i];
|
||||
Items.DeleteFrom(j);
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, Items)
|
||||
{
|
||||
const int folderIndex = GetFolderIndex(&Items[i]);
|
||||
while (folderIndex >= (int)FolderStartFileIndex.Size())
|
||||
FolderStartFileIndex.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CMvDatabaseEx::Check()
|
||||
{
|
||||
for (unsigned v = 1; v < Volumes.Size(); v++)
|
||||
{
|
||||
const CDatabaseEx &db1 = Volumes[v];
|
||||
if (db1.IsTherePrevFolder())
|
||||
{
|
||||
const CDatabaseEx &db0 = Volumes[v - 1];
|
||||
if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())
|
||||
return false;
|
||||
const CFolder &f0 = db0.Folders.Back();
|
||||
const CFolder &f1 = db1.Folders.FrontItem();
|
||||
if (f0.MethodMajor != f1.MethodMajor ||
|
||||
f0.MethodMinor != f1.MethodMinor)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 beginPos = 0;
|
||||
UInt64 endPos = 0;
|
||||
int prevFolder = -2;
|
||||
|
||||
FOR_VECTOR (i, Items)
|
||||
{
|
||||
const CMvItem &mvItem = Items[i];
|
||||
const int fIndex = GetFolderIndex(&mvItem);
|
||||
if (fIndex >= (int)FolderStartFileIndex.Size())
|
||||
return false;
|
||||
const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
|
||||
if (item.IsDir())
|
||||
continue;
|
||||
|
||||
const int folderIndex = GetFolderIndex(&mvItem);
|
||||
|
||||
if (folderIndex != prevFolder)
|
||||
prevFolder = folderIndex;
|
||||
else if (item.Offset < endPos &&
|
||||
(item.Offset != beginPos || item.GetEndOffset() != endPos))
|
||||
return false;
|
||||
|
||||
beginPos = item.Offset;
|
||||
endPos = item.GetEndOffset();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,176 @@
|
||||
// Archive/CabIn.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_CAB_IN_H
|
||||
#define ZIP7_INC_ARCHIVE_CAB_IN_H
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
#include "CabItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
struct COtherArc
|
||||
{
|
||||
AString FileName;
|
||||
AString DiskName;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
FileName.Empty();
|
||||
DiskName.Empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CArchInfo
|
||||
{
|
||||
Byte VersionMinor; // cabinet file format version, minor
|
||||
Byte VersionMajor; // cabinet file format version, major
|
||||
UInt32 NumFolders; // number of CFFOLDER entries in this cabinet
|
||||
UInt32 NumFiles; // number of CFFILE entries in this cabinet
|
||||
UInt32 Flags; // cabinet file option indicators
|
||||
UInt32 SetID; // must be the same for all cabinets in a set
|
||||
UInt32 CabinetNumber; // number of this cabinet file in a set
|
||||
|
||||
UInt16 PerCabinet_AreaSize; // (optional) size of per-cabinet reserved area
|
||||
Byte PerFolder_AreaSize; // (optional) size of per-folder reserved area
|
||||
Byte PerDataBlock_AreaSize; // (optional) size of per-datablock reserved area
|
||||
|
||||
COtherArc PrevArc; // prev link can skip some volumes !!!
|
||||
COtherArc NextArc;
|
||||
|
||||
bool ReserveBlockPresent() const { return (Flags & NHeader::NArcFlags::kReservePresent) != 0; }
|
||||
bool IsTherePrev() const { return (Flags & NHeader::NArcFlags::kPrevCabinet) != 0; }
|
||||
bool IsThereNext() const { return (Flags & NHeader::NArcFlags::kNextCabinet) != 0; }
|
||||
Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlock_AreaSize : 0); }
|
||||
|
||||
CArchInfo()
|
||||
{
|
||||
PerCabinet_AreaSize = 0;
|
||||
PerFolder_AreaSize = 0;
|
||||
PerDataBlock_AreaSize = 0;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
PerCabinet_AreaSize = 0;
|
||||
PerFolder_AreaSize = 0;
|
||||
PerDataBlock_AreaSize = 0;
|
||||
|
||||
PrevArc.Clear();
|
||||
NextArc.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CInArcInfo: public CArchInfo
|
||||
{
|
||||
UInt32 Size; // size of this cabinet file in bytes
|
||||
UInt32 FileHeadersOffset; // offset of the first CFFILE entry
|
||||
|
||||
bool Parse(const Byte *p);
|
||||
};
|
||||
|
||||
|
||||
struct CDatabase
|
||||
{
|
||||
CRecordVector<CFolder> Folders;
|
||||
CObjectVector<CItem> Items;
|
||||
UInt64 StartPosition;
|
||||
CInArcInfo ArcInfo;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
ArcInfo.Clear();
|
||||
Folders.Clear();
|
||||
Items.Clear();
|
||||
}
|
||||
|
||||
bool IsTherePrevFolder() const
|
||||
{
|
||||
FOR_VECTOR (i, Items)
|
||||
if (Items[i].ContinuedFromPrev())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetNumberOfNewFolders() const
|
||||
{
|
||||
int res = (int)Folders.Size();
|
||||
if (IsTherePrevFolder())
|
||||
res--;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CDatabaseEx: public CDatabase
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
};
|
||||
|
||||
|
||||
struct CMvItem
|
||||
{
|
||||
unsigned VolumeIndex;
|
||||
unsigned ItemIndex;
|
||||
};
|
||||
|
||||
|
||||
class CMvDatabaseEx
|
||||
{
|
||||
bool AreItemsEqual(unsigned i1, unsigned i2);
|
||||
|
||||
public:
|
||||
CObjectVector<CDatabaseEx> Volumes;
|
||||
CRecordVector<CMvItem> Items;
|
||||
CRecordVector<int> StartFolderOfVol; // can be negative
|
||||
CRecordVector<unsigned> FolderStartFileIndex;
|
||||
|
||||
int GetFolderIndex(const CMvItem *mvi) const
|
||||
{
|
||||
const CDatabaseEx &db = Volumes[mvi->VolumeIndex];
|
||||
return StartFolderOfVol[mvi->VolumeIndex] +
|
||||
db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size());
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Volumes.Clear();
|
||||
Items.Clear();
|
||||
StartFolderOfVol.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
}
|
||||
|
||||
void FillSortAndShrink();
|
||||
bool Check();
|
||||
};
|
||||
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CInBufferBase _inBuffer;
|
||||
CByteBuffer _tempBuf;
|
||||
|
||||
void Skip(unsigned size);
|
||||
void Read(Byte *data, unsigned size);
|
||||
void ReadName(AString &s);
|
||||
void ReadOtherArc(COtherArc &oa);
|
||||
HRESULT Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
|
||||
|
||||
public:
|
||||
bool IsArc;
|
||||
bool ErrorInNames;
|
||||
bool UnexpectedEnd;
|
||||
bool HeaderError;
|
||||
|
||||
HRESULT Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
// Archive/CabItem.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_CAB_ITEM_H
|
||||
#define ZIP7_INC_ARCHIVE_CAB_ITEM_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "CabHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
const unsigned kNumMethodsMax = 16;
|
||||
|
||||
struct CFolder
|
||||
{
|
||||
UInt32 DataStart; // offset of the first CFDATA block in this folder
|
||||
UInt16 NumDataBlocks; // number of CFDATA blocks in this folder
|
||||
Byte MethodMajor;
|
||||
Byte MethodMinor;
|
||||
|
||||
Byte GetMethod() const { return (Byte)(MethodMajor & 0xF); }
|
||||
};
|
||||
|
||||
struct CItem
|
||||
{
|
||||
AString Name;
|
||||
UInt32 Offset;
|
||||
UInt32 Size;
|
||||
UInt32 Time;
|
||||
UInt32 FolderIndex;
|
||||
UInt16 Flags;
|
||||
UInt16 Attributes;
|
||||
|
||||
UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }
|
||||
UInt32 GetWinAttrib() const { return (UInt32)Attributes & ~(UInt32)NHeader::kFileNameIsUtf8_Mask; }
|
||||
bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUtf8_Mask) != 0; }
|
||||
bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
|
||||
|
||||
bool ContinuedFromPrev() const
|
||||
{
|
||||
return
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev ||
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
|
||||
}
|
||||
|
||||
bool ContinuedToNext() const
|
||||
{
|
||||
return
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedToNext ||
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
|
||||
}
|
||||
|
||||
int GetFolderIndex(unsigned numFolders) const
|
||||
{
|
||||
if (ContinuedFromPrev())
|
||||
return 0;
|
||||
if (ContinuedToNext())
|
||||
return (int)numFolders - 1;
|
||||
return (int)FolderIndex;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
// CabRegister.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "CabHandler.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"Cab", "cab", NULL, 8,
|
||||
NHeader::kMarker,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
NULL)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,11 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,790 @@
|
||||
// ChmHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/AutoPtr.h"
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
#include "../../Compress/LzxDecoder.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
#include "ChmHandler.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
// #define CHM_DETAILS
|
||||
|
||||
#ifdef CHM_DETAILS
|
||||
|
||||
enum
|
||||
{
|
||||
kpidSection = kpidUserDefined
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidMethod,
|
||||
kpidBlock
|
||||
|
||||
#ifdef CHM_DETAILS
|
||||
,
|
||||
L"Section", kpidSection,
|
||||
kpidOffset
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
// kpidNumBlocks,
|
||||
};
|
||||
*/
|
||||
|
||||
IMP_IInArchive_Props
|
||||
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
// COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
/*
|
||||
case kpidNumBlocks:
|
||||
{
|
||||
UInt64 numBlocks = 0;
|
||||
FOR_VECTOR(i, m_Database.Sections)
|
||||
{
|
||||
const CSectionInfo &s = m_Database.Sections[i];
|
||||
FOR_VECTOR(j, s.Methods)
|
||||
{
|
||||
const CMethodInfo &m = s.Methods[j];
|
||||
if (m.IsLzx())
|
||||
numBlocks += m.LzxInfo.ResetTable.GetNumBlocks();
|
||||
}
|
||||
}
|
||||
prop = numBlocks;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case kpidOffset: prop = m_Database.StartPosition; break;
|
||||
case kpidPhySize: prop = m_Database.PhySize; break;
|
||||
|
||||
case kpidErrorFlags: prop = m_ErrorFlags; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
if (m_Database.NewFormat)
|
||||
{
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize:
|
||||
prop = (UInt64)m_Database.NewFormatString.Len();
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
unsigned entryIndex;
|
||||
if (m_Database.LowLevel)
|
||||
entryIndex = index;
|
||||
else
|
||||
entryIndex = m_Database.Indices[index];
|
||||
|
||||
const CItem &item = m_Database.Items[entryIndex];
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
UString us;
|
||||
// if (
|
||||
ConvertUTF8ToUnicode(item.Name, us);
|
||||
{
|
||||
if (!m_Database.LowLevel)
|
||||
{
|
||||
if (us.Len() > 1 && us[0] == L'/')
|
||||
us.Delete(0);
|
||||
}
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(us);
|
||||
prop = us;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidSize: prop = item.Size; break;
|
||||
case kpidMethod:
|
||||
{
|
||||
if (!item.IsDir())
|
||||
{
|
||||
if (item.Section == 0)
|
||||
prop = "Copy";
|
||||
else if (item.Section < m_Database.Sections.Size())
|
||||
prop = m_Database.Sections[(unsigned)item.Section].GetMethodName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kpidBlock:
|
||||
if (m_Database.LowLevel)
|
||||
prop = item.Section;
|
||||
else if (item.Section != 0 && item.Section < m_Database.Sections.Size())
|
||||
prop = m_Database.GetFolder(index);
|
||||
break;
|
||||
|
||||
#ifdef CHM_DETAILS
|
||||
|
||||
case kpidSection: prop = (UInt32)item.Section; break;
|
||||
case kpidOffset: prop = (UInt32)item.Offset; break;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
try
|
||||
{
|
||||
CInArchive archive(_help2);
|
||||
// CProgressImp progressImp(openArchiveCallback);
|
||||
const HRESULT res = archive.Open(inStream, maxCheckStartPosition, m_Database);
|
||||
if (!archive.IsArc) m_ErrorFlags |= kpv_ErrorFlags_IsNotArc;
|
||||
if (archive.HeadersError) m_ErrorFlags |= kpv_ErrorFlags_HeadersError;
|
||||
if (archive.UnexpectedEnd) m_ErrorFlags |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (archive.UnsupportedFeature) m_ErrorFlags |= kpv_ErrorFlags_UnsupportedFeature;
|
||||
|
||||
RINOK(res)
|
||||
/*
|
||||
if (m_Database.LowLevel)
|
||||
return S_FALSE;
|
||||
*/
|
||||
m_Stream = inStream;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
m_ErrorFlags = 0;
|
||||
m_Database.Clear();
|
||||
m_Stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
CChmFolderOutStream
|
||||
, ISequentialOutStream
|
||||
)
|
||||
bool m_TestMode;
|
||||
bool m_IsOk;
|
||||
bool m_FileIsOpen;
|
||||
const CFilesDatabase *m_Database;
|
||||
CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
|
||||
CMyComPtr<ISequentialOutStream> m_RealOutStream;
|
||||
UInt64 m_RemainFileSize;
|
||||
|
||||
HRESULT OpenFile();
|
||||
HRESULT WriteEmptyFiles();
|
||||
HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
|
||||
public:
|
||||
|
||||
UInt64 m_FolderSize;
|
||||
UInt64 m_PosInFolder;
|
||||
UInt64 m_PosInSection;
|
||||
const CRecordVector<bool> *m_ExtractStatuses;
|
||||
unsigned m_StartIndex;
|
||||
unsigned m_CurrentIndex;
|
||||
unsigned m_NumFiles;
|
||||
|
||||
void Init(
|
||||
const CFilesDatabase *database,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode);
|
||||
HRESULT FlushCorrupted(UInt64 maxSize);
|
||||
};
|
||||
|
||||
void CChmFolderOutStream::Init(
|
||||
const CFilesDatabase *database,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode)
|
||||
{
|
||||
m_Database = database;
|
||||
m_ExtractCallback = extractCallback;
|
||||
m_TestMode = testMode;
|
||||
|
||||
m_CurrentIndex = 0;
|
||||
m_FileIsOpen = false;
|
||||
}
|
||||
|
||||
HRESULT CChmFolderOutStream::OpenFile()
|
||||
{
|
||||
Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? m_TestMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract :
|
||||
NExtract::NAskMode::kSkip;
|
||||
m_RealOutStream.Release();
|
||||
RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode))
|
||||
if (!m_RealOutStream && !m_TestMode)
|
||||
askMode = NExtract::NAskMode::kSkip;
|
||||
return m_ExtractCallback->PrepareOperation(askMode);
|
||||
}
|
||||
|
||||
HRESULT CChmFolderOutStream::WriteEmptyFiles()
|
||||
{
|
||||
if (m_FileIsOpen)
|
||||
return S_OK;
|
||||
for (; m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
|
||||
{
|
||||
const UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);
|
||||
if (fileSize != 0)
|
||||
return S_OK;
|
||||
const HRESULT result = OpenFile();
|
||||
m_RealOutStream.Release();
|
||||
RINOK(result)
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// This is WritePart function
|
||||
HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
|
||||
{
|
||||
UInt32 realProcessed = 0;
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (m_FileIsOpen)
|
||||
{
|
||||
UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size));
|
||||
HRESULT res = S_OK;
|
||||
if (numBytesToWrite > 0)
|
||||
{
|
||||
if (!isOK)
|
||||
m_IsOk = false;
|
||||
if (m_RealOutStream)
|
||||
{
|
||||
UInt32 processedSizeLocal = 0;
|
||||
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
|
||||
numBytesToWrite = processedSizeLocal;
|
||||
}
|
||||
}
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_RemainFileSize -= numBytesToWrite;
|
||||
m_PosInSection += numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
if (m_RemainFileSize == 0)
|
||||
{
|
||||
m_RealOutStream.Release();
|
||||
RINOK(m_ExtractCallback->SetOperationResult(
|
||||
m_IsOk ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kDataError))
|
||||
m_FileIsOpen = false;
|
||||
}
|
||||
if (realProcessed > 0)
|
||||
break; // with this break this function works as write part
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_CurrentIndex >= m_NumFiles)
|
||||
{
|
||||
realProcessed += size;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
return S_OK;
|
||||
// return E_FAIL;
|
||||
}
|
||||
|
||||
unsigned fullIndex = m_StartIndex + m_CurrentIndex;
|
||||
m_RemainFileSize = m_Database->GetFileSize(fullIndex);
|
||||
UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);
|
||||
if (fileOffset < m_PosInSection)
|
||||
return E_FAIL;
|
||||
|
||||
if (fileOffset > m_PosInSection)
|
||||
{
|
||||
UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size));
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_PosInSection += numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
}
|
||||
|
||||
if (fileOffset == m_PosInSection)
|
||||
{
|
||||
RINOK(OpenFile())
|
||||
m_FileIsOpen = true;
|
||||
m_CurrentIndex++;
|
||||
m_IsOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return WriteEmptyFiles();
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
return Write2(data, size, processedSize, true);
|
||||
}
|
||||
|
||||
HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)
|
||||
{
|
||||
const UInt32 kBufferSize = (1 << 10);
|
||||
Byte buffer[kBufferSize];
|
||||
for (unsigned i = 0; i < kBufferSize; i++)
|
||||
buffer[i] = 0;
|
||||
if (maxSize > m_FolderSize)
|
||||
maxSize = m_FolderSize;
|
||||
while (m_PosInFolder < maxSize)
|
||||
{
|
||||
UInt32 size = (UInt32)MyMin(maxSize - m_PosInFolder, (UInt64)kBufferSize);
|
||||
UInt32 processedSizeLocal = 0;
|
||||
RINOK(Write2(buffer, size, &processedSizeLocal, false))
|
||||
if (processedSizeLocal == 0)
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testModeSpec, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
|
||||
if (allFilesMode)
|
||||
numItems = m_Database.NewFormat ? 1:
|
||||
(m_Database.LowLevel ?
|
||||
m_Database.Items.Size():
|
||||
m_Database.Indices.Size());
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
const bool testMode = (testModeSpec != 0);
|
||||
|
||||
UInt64 currentTotalSize = 0;
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
|
||||
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
|
||||
inStream->SetStream(m_Stream);
|
||||
|
||||
UInt32 i;
|
||||
|
||||
if (m_Database.LowLevel)
|
||||
{
|
||||
UInt64 currentItemSize = 0;
|
||||
UInt64 totalSize = 0;
|
||||
|
||||
if (m_Database.NewFormat)
|
||||
totalSize = m_Database.NewFormatString.Len();
|
||||
else
|
||||
for (i = 0; i < numItems; i++)
|
||||
totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
|
||||
|
||||
RINOK(extractCallback->SetTotal(totalSize))
|
||||
|
||||
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
|
||||
{
|
||||
currentItemSize = 0;
|
||||
lps->InSize = currentTotalSize; // Change it
|
||||
lps->OutSize = currentTotalSize;
|
||||
|
||||
RINOK(lps->SetCur())
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
const Int32 askMode= testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||
|
||||
if (m_Database.NewFormat)
|
||||
{
|
||||
if (index != 0)
|
||||
return E_FAIL;
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
if (!testMode)
|
||||
{
|
||||
const unsigned size = m_Database.NewFormatString.Len();
|
||||
RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size))
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
continue;
|
||||
}
|
||||
|
||||
const CItem &item = m_Database.Items[index];
|
||||
|
||||
currentItemSize = item.Size;
|
||||
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
if (item.Section != 0)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (testMode)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
continue;
|
||||
}
|
||||
|
||||
RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
|
||||
inStream->Init(item.Size);
|
||||
|
||||
RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult((copyCoder->TotalSize == item.Size) ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kDataError))
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UInt64 lastFolderIndex = (UInt64)0 - 1;
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = m_Database.Items[m_Database.Indices[index]];
|
||||
const UInt64 sectionIndex = item.Section;
|
||||
if (item.IsDir() || item.Size == 0)
|
||||
continue;
|
||||
if (sectionIndex == 0)
|
||||
{
|
||||
currentTotalSize += item.Size;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sectionIndex >= m_Database.Sections.Size())
|
||||
continue;
|
||||
|
||||
const CSectionInfo §ion = m_Database.Sections[(unsigned)sectionIndex];
|
||||
if (section.IsLzx())
|
||||
{
|
||||
const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
|
||||
UInt64 folderIndex = m_Database.GetFolder(index);
|
||||
if (lastFolderIndex == folderIndex)
|
||||
folderIndex++;
|
||||
lastFolderIndex = m_Database.GetLastFolder(index);
|
||||
for (; folderIndex <= lastFolderIndex; folderIndex++)
|
||||
currentTotalSize += lzxInfo.GetFolderSize();
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(extractCallback->SetTotal(currentTotalSize))
|
||||
|
||||
CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;
|
||||
CMyComPtr2_Create<ISequentialOutStream, CChmFolderOutStream> chmFolderOutStream;
|
||||
|
||||
currentTotalSize = 0;
|
||||
|
||||
CRecordVector<bool> extractStatuses;
|
||||
|
||||
CByteBuffer packBuf;
|
||||
|
||||
for (i = 0;;)
|
||||
{
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalSize))
|
||||
|
||||
if (i >= numItems)
|
||||
break;
|
||||
|
||||
UInt32 index = allFilesMode ? i : indices[i];
|
||||
i++;
|
||||
const CItem &item = m_Database.Items[m_Database.Indices[index]];
|
||||
const UInt64 sectionIndex = item.Section;
|
||||
const Int32 askMode= testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
|
||||
if (item.IsDir())
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
continue;
|
||||
}
|
||||
|
||||
lps->InSize = currentTotalSize; // Change it
|
||||
lps->OutSize = currentTotalSize;
|
||||
|
||||
if (item.Size == 0 || sectionIndex == 0)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
Int32 opRes = NExtract::NOperationResult::kOK;
|
||||
if (!testMode && item.Size != 0)
|
||||
{
|
||||
RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
|
||||
inStream->Init(item.Size);
|
||||
RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
|
||||
if (copyCoder->TotalSize != item.Size)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
}
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(opRes))
|
||||
currentTotalSize += item.Size;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sectionIndex >= m_Database.Sections.Size())
|
||||
{
|
||||
// we must report error here;
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError))
|
||||
continue;
|
||||
}
|
||||
|
||||
const CSectionInfo §ion = m_Database.Sections[(unsigned)sectionIndex];
|
||||
|
||||
if (!section.IsLzx())
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
|
||||
continue;
|
||||
}
|
||||
|
||||
const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
|
||||
|
||||
chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
|
||||
|
||||
lzxDecoder.Create_if_Empty();
|
||||
|
||||
UInt64 folderIndex = m_Database.GetFolder(index);
|
||||
|
||||
const UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
|
||||
RINOK(lzxDecoder->Set_DictBits_and_Alloc(lzxInfo.GetNumDictBits()))
|
||||
|
||||
const CItem *lastItem = &item;
|
||||
extractStatuses.Clear();
|
||||
extractStatuses.Add(true);
|
||||
|
||||
for (;; folderIndex++)
|
||||
{
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalSize))
|
||||
|
||||
const UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);
|
||||
UInt64 finishPos = lastItem->Offset + lastItem->Size;
|
||||
const UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);
|
||||
|
||||
lastFolderIndex = m_Database.GetLastFolder(index);
|
||||
const UInt64 folderSize = lzxInfo.GetFolderSize();
|
||||
UInt64 unPackSize = folderSize;
|
||||
|
||||
if (extractStatuses.IsEmpty())
|
||||
chmFolderOutStream->m_StartIndex = index + 1;
|
||||
else
|
||||
chmFolderOutStream->m_StartIndex = index;
|
||||
|
||||
if (limitFolderIndex == folderIndex)
|
||||
{
|
||||
for (; i < numItems; i++)
|
||||
{
|
||||
const UInt32 nextIndex = allFilesMode ? i : indices[i];
|
||||
const CItem &nextItem = m_Database.Items[m_Database.Indices[nextIndex]];
|
||||
if (nextItem.Section != sectionIndex)
|
||||
break;
|
||||
const UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);
|
||||
if (nextFolderIndex != folderIndex)
|
||||
break;
|
||||
for (index++; index < nextIndex; index++)
|
||||
extractStatuses.Add(false);
|
||||
extractStatuses.Add(true);
|
||||
index = nextIndex;
|
||||
lastItem = &nextItem;
|
||||
if (nextItem.Size != 0)
|
||||
finishPos = nextItem.Offset + nextItem.Size;
|
||||
lastFolderIndex = m_Database.GetLastFolder(index);
|
||||
}
|
||||
}
|
||||
|
||||
unPackSize = MyMin(finishPos - startPos, unPackSize);
|
||||
|
||||
chmFolderOutStream->m_FolderSize = folderSize;
|
||||
chmFolderOutStream->m_PosInFolder = 0;
|
||||
chmFolderOutStream->m_PosInSection = startPos;
|
||||
chmFolderOutStream->m_ExtractStatuses = &extractStatuses;
|
||||
chmFolderOutStream->m_NumFiles = extractStatuses.Size();
|
||||
chmFolderOutStream->m_CurrentIndex = 0;
|
||||
|
||||
try
|
||||
{
|
||||
const UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
|
||||
const CResetTable &rt = lzxInfo.ResetTable;
|
||||
const UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
|
||||
|
||||
for (UInt32 b = 0; b < numBlocks; b++)
|
||||
{
|
||||
UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;
|
||||
RINOK(extractCallback->SetCompleted(&completedSize))
|
||||
UInt64 bCur = startBlock + b;
|
||||
if (bCur >= rt.ResetOffsets.Size())
|
||||
return E_FAIL;
|
||||
const UInt64 offset = rt.ResetOffsets[(unsigned)bCur];
|
||||
UInt64 compressedSize;
|
||||
rt.GetCompressedSizeOfBlock(bCur, compressedSize);
|
||||
|
||||
// chm writes full blocks. So we don't need to use reduced size for last block
|
||||
|
||||
RINOK(InStream_SeekSet(m_Stream, compressedPos + offset))
|
||||
inStream->Init(compressedSize);
|
||||
|
||||
lzxDecoder->Set_KeepHistory(b > 0);
|
||||
|
||||
HRESULT res = S_FALSE;
|
||||
if (compressedSize <= (1u << 30))
|
||||
{
|
||||
const unsigned kAdditionalInputSize = 32;
|
||||
const size_t compressedSizeT = (size_t)compressedSize;
|
||||
const size_t allocSize = compressedSizeT + kAdditionalInputSize;
|
||||
if (allocSize <= compressedSize)
|
||||
throw 2;
|
||||
packBuf.AllocAtLeast(allocSize);
|
||||
res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);
|
||||
if (res == S_OK)
|
||||
{
|
||||
memset(packBuf + compressedSizeT, 0xff, kAdditionalInputSize);
|
||||
lzxDecoder->Set_KeepHistoryForNext(true);
|
||||
res = lzxDecoder->Code_WithExceedReadWrite(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize;
|
||||
if (res == S_OK)
|
||||
res = WriteStream(chmFolderOutStream,
|
||||
lzxDecoder->GetUnpackData(),
|
||||
lzxDecoder->GetUnpackSize());
|
||||
}
|
||||
}
|
||||
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (res != S_FALSE)
|
||||
return res;
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
RINOK(chmFolderOutStream->FlushCorrupted(unPackSize))
|
||||
}
|
||||
|
||||
currentTotalSize += folderSize;
|
||||
if (folderIndex == lastFolderIndex)
|
||||
break;
|
||||
extractStatuses.Clear();
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = m_Database.NewFormat ? 1:
|
||||
(m_Database.LowLevel ?
|
||||
m_Database.Items.Size():
|
||||
m_Database.Indices.Size());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
namespace NChm {
|
||||
|
||||
static const Byte k_Signature[] = { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 };
|
||||
|
||||
REGISTER_ARC_I_CLS(
|
||||
CHandler(false),
|
||||
"Chm", "chm chi chq chw", NULL, 0xE9,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
NULL)
|
||||
|
||||
}
|
||||
|
||||
namespace NHxs {
|
||||
|
||||
static const Byte k_Signature[] = { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 };
|
||||
|
||||
REGISTER_ARC_I_CLS(
|
||||
CHandler(true),
|
||||
"Hxs", "hxs hxi hxr hxq hxw lit", NULL, 0xCE,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
NULL)
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,27 @@
|
||||
// ChmHandler.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_CHM_HANDLER_H
|
||||
#define ZIP7_INC_ARCHIVE_CHM_HANDLER_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "ChmIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_0
|
||||
|
||||
CFilesDatabase m_Database;
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
bool _help2;
|
||||
UInt32 m_ErrorFlags;
|
||||
public:
|
||||
CHandler(bool help2): _help2(help2) {}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,282 @@
|
||||
// Archive/ChmIn.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_CHM_IN_H
|
||||
#define ZIP7_INC_ARCHIVE_CHM_IN_H
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt64 Section;
|
||||
UInt64 Offset;
|
||||
UInt64 Size;
|
||||
AString Name;
|
||||
|
||||
bool IsFormatRelatedItem() const
|
||||
{
|
||||
if (Name.Len() < 2)
|
||||
return false;
|
||||
return Name[0] == ':' && Name[1] == ':';
|
||||
}
|
||||
|
||||
bool IsUserItem() const
|
||||
{
|
||||
if (Name.Len() < 2)
|
||||
return false;
|
||||
return Name[0] == '/';
|
||||
}
|
||||
|
||||
bool IsDir() const
|
||||
{
|
||||
if (Name.IsEmpty())
|
||||
return false;
|
||||
return (Name.Back() == '/');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CDatabase
|
||||
{
|
||||
CObjectVector<CItem> Items;
|
||||
UInt64 StartPosition;
|
||||
UInt64 ContentOffset;
|
||||
AString NewFormatString;
|
||||
bool Help2Format;
|
||||
bool NewFormat;
|
||||
UInt64 PhySize;
|
||||
|
||||
void UpdatePhySize(UInt64 v) { if (PhySize < v) PhySize = v; }
|
||||
|
||||
int FindItem(const AString &name) const
|
||||
{
|
||||
FOR_VECTOR (i, Items)
|
||||
if (Items[i].Name == name)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
NewFormat = false;
|
||||
NewFormatString.Empty();
|
||||
Help2Format = false;
|
||||
Items.Clear();
|
||||
StartPosition = 0;
|
||||
PhySize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const UInt32 kBlockSize = 1 << 15;
|
||||
|
||||
struct CResetTable
|
||||
{
|
||||
UInt64 UncompressedSize;
|
||||
UInt64 CompressedSize;
|
||||
// unsigned BlockSizeBits;
|
||||
CRecordVector<UInt64> ResetOffsets;
|
||||
|
||||
CResetTable():
|
||||
UncompressedSize(0),
|
||||
CompressedSize(0)
|
||||
{}
|
||||
|
||||
bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const
|
||||
{
|
||||
if (blockIndex >= ResetOffsets.Size())
|
||||
return false;
|
||||
UInt64 startPos = ResetOffsets[(unsigned)blockIndex];
|
||||
if (blockIndex + numBlocks >= ResetOffsets.Size())
|
||||
size = CompressedSize - startPos;
|
||||
else
|
||||
size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const
|
||||
{
|
||||
return GetCompressedSizeOfBlocks(blockIndex, 1, size);
|
||||
}
|
||||
|
||||
UInt64 GetNumBlocks(UInt64 size) const
|
||||
{
|
||||
return (size + kBlockSize - 1) / kBlockSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CLzxInfo
|
||||
{
|
||||
UInt32 Version;
|
||||
|
||||
unsigned ResetIntervalBits;
|
||||
unsigned WindowSizeBits;
|
||||
UInt32 CacheSize;
|
||||
|
||||
CResetTable ResetTable;
|
||||
|
||||
CLzxInfo():
|
||||
Version(0),
|
||||
ResetIntervalBits(0),
|
||||
WindowSizeBits(0),
|
||||
CacheSize(0)
|
||||
{}
|
||||
|
||||
unsigned GetNumDictBits() const
|
||||
{
|
||||
if (Version == 2 || Version == 3)
|
||||
return 15 + WindowSizeBits;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 GetFolderSize() const { return (UInt64)kBlockSize << ResetIntervalBits; }
|
||||
UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }
|
||||
UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }
|
||||
UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex << ResetIntervalBits; }
|
||||
|
||||
bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
|
||||
{
|
||||
const UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
|
||||
if (blockIndex >= ResetTable.ResetOffsets.Size())
|
||||
return false;
|
||||
offset = ResetTable.ResetOffsets[(unsigned)blockIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const
|
||||
{
|
||||
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
|
||||
return ResetTable.GetCompressedSizeOfBlocks(blockIndex, (UInt32)1 << ResetIntervalBits, size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CMethodInfo
|
||||
{
|
||||
Byte Guid[16];
|
||||
// CByteBuffer ControlData;
|
||||
CLzxInfo LzxInfo;
|
||||
|
||||
bool IsLzx() const;
|
||||
bool IsDes() const;
|
||||
AString GetGuidString() const;
|
||||
AString GetName() const;
|
||||
};
|
||||
|
||||
|
||||
struct CSectionInfo
|
||||
{
|
||||
UInt64 Offset;
|
||||
UInt64 CompressedSize;
|
||||
UInt64 UncompressedSize;
|
||||
|
||||
AString Name;
|
||||
CObjectVector<CMethodInfo> Methods;
|
||||
|
||||
bool IsLzx() const;
|
||||
UString GetMethodName() const;
|
||||
};
|
||||
|
||||
class CFilesDatabase: public CDatabase
|
||||
{
|
||||
public:
|
||||
CUIntVector Indices;
|
||||
CObjectVector<CSectionInfo> Sections;
|
||||
bool LowLevel;
|
||||
|
||||
UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; }
|
||||
UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; }
|
||||
|
||||
UInt64 GetFolder(unsigned fileIndex) const
|
||||
{
|
||||
const CItem &item = Items[Indices[fileIndex]];
|
||||
if (item.Section < Sections.Size())
|
||||
{
|
||||
const CSectionInfo §ion = Sections[(unsigned)item.Section];
|
||||
if (section.IsLzx())
|
||||
return section.Methods[0].LzxInfo.GetFolder(item.Offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 GetLastFolder(unsigned fileIndex) const
|
||||
{
|
||||
const CItem &item = Items[Indices[fileIndex]];
|
||||
if (item.Section < Sections.Size())
|
||||
{
|
||||
const CSectionInfo §ion = Sections[(unsigned)item.Section];
|
||||
if (section.IsLzx())
|
||||
return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HighLevelClear()
|
||||
{
|
||||
LowLevel = true;
|
||||
Indices.Clear();
|
||||
Sections.Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CDatabase::Clear();
|
||||
HighLevelClear();
|
||||
}
|
||||
|
||||
void SetIndices();
|
||||
void Sort();
|
||||
bool Check();
|
||||
bool CheckSectionRefs();
|
||||
};
|
||||
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> m_InStreamRef;
|
||||
::CInBuffer _inBuffer;
|
||||
UInt64 _chunkSize;
|
||||
bool _help2;
|
||||
|
||||
Byte ReadByte();
|
||||
void ReadBytes(Byte *data, UInt32 size);
|
||||
void Skip(size_t size);
|
||||
UInt16 ReadUInt16();
|
||||
UInt32 ReadUInt32();
|
||||
UInt64 ReadUInt64();
|
||||
UInt64 ReadEncInt();
|
||||
void ReadString(unsigned size, AString &s);
|
||||
void ReadUString(unsigned size, UString &s);
|
||||
void ReadGUID(Byte *g);
|
||||
|
||||
HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);
|
||||
|
||||
HRESULT ReadDirEntry(CDatabase &database);
|
||||
HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name);
|
||||
|
||||
public:
|
||||
bool IsArc;
|
||||
bool HeadersError;
|
||||
bool UnexpectedEnd;
|
||||
bool UnsupportedFeature;
|
||||
|
||||
CInArchive(bool help2) { _help2 = help2; }
|
||||
|
||||
HRESULT OpenChm(IInStream *inStream, CDatabase &database);
|
||||
HRESULT OpenHelp2(IInStream *inStream, CDatabase &database);
|
||||
HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database);
|
||||
HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
|
||||
HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,447 @@
|
||||
// CoderMixer2.h
|
||||
|
||||
#ifndef ZIP7_INC_CODER_MIXER2_H
|
||||
#define ZIP7_INC_CODER_MIXER2_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#ifdef Z7_ST
|
||||
#define USE_MIXER_ST
|
||||
#else
|
||||
#define USE_MIXER_MT
|
||||
#ifndef Z7_SFX
|
||||
#define USE_MIXER_ST
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../Common/VirtThread.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CSequentialInStreamCalcSize
|
||||
, ISequentialInStream
|
||||
)
|
||||
bool _wasFinished;
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
_wasFinished = false;
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
COutStreamCalcSize
|
||||
, ISequentialOutStream
|
||||
, IOutStreamFinish
|
||||
)
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init() { _size = 0; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
struct CBond
|
||||
{
|
||||
UInt32 PackIndex;
|
||||
UInt32 UnpackIndex;
|
||||
|
||||
UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }
|
||||
UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }
|
||||
};
|
||||
|
||||
|
||||
struct CCoderStreamsInfo
|
||||
{
|
||||
UInt32 NumStreams;
|
||||
};
|
||||
|
||||
|
||||
struct CBindInfo
|
||||
{
|
||||
CRecordVector<CCoderStreamsInfo> Coders;
|
||||
CRecordVector<CBond> Bonds;
|
||||
CRecordVector<UInt32> PackStreams;
|
||||
unsigned UnpackCoder;
|
||||
|
||||
unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
|
||||
|
||||
int FindBond_for_PackStream(UInt32 packStream) const
|
||||
{
|
||||
FOR_VECTOR (i, Bonds)
|
||||
if (Bonds[i].PackIndex == packStream)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindBond_for_UnpackStream(UInt32 unpackStream) const
|
||||
{
|
||||
FOR_VECTOR (i, Bonds)
|
||||
if (Bonds[i].UnpackIndex == unpackStream)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SetUnpackCoder()
|
||||
{
|
||||
bool isOk = false;
|
||||
FOR_VECTOR (i, Coders)
|
||||
{
|
||||
if (FindBond_for_UnpackStream(i) < 0)
|
||||
{
|
||||
if (isOk)
|
||||
return false;
|
||||
UnpackCoder = i;
|
||||
isOk = true;
|
||||
}
|
||||
}
|
||||
return isOk;
|
||||
}
|
||||
|
||||
bool IsStream_in_PackStreams(UInt32 streamIndex) const
|
||||
{
|
||||
return FindStream_in_PackStreams(streamIndex) >= 0;
|
||||
}
|
||||
|
||||
int FindStream_in_PackStreams(UInt32 streamIndex) const
|
||||
{
|
||||
FOR_VECTOR (i, PackStreams)
|
||||
if (PackStreams[i] == streamIndex)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// that function is used before Maps is calculated
|
||||
|
||||
UInt32 GetStream_for_Coder(UInt32 coderIndex) const
|
||||
{
|
||||
UInt32 streamIndex = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
streamIndex += Coders[i].NumStreams;
|
||||
return streamIndex;
|
||||
}
|
||||
|
||||
// ---------- Maps Section ----------
|
||||
|
||||
CRecordVector<UInt32> Coder_to_Stream;
|
||||
CRecordVector<UInt32> Stream_to_Coder;
|
||||
|
||||
void ClearMaps();
|
||||
bool CalcMapsAndCheck();
|
||||
|
||||
// ---------- End of Maps Section ----------
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Coders.Clear();
|
||||
Bonds.Clear();
|
||||
PackStreams.Clear();
|
||||
|
||||
ClearMaps();
|
||||
}
|
||||
|
||||
void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const
|
||||
{
|
||||
coderIndex = Stream_to_Coder[streamIndex];
|
||||
coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CCoder
|
||||
{
|
||||
Z7_CLASS_NO_COPY(CCoder)
|
||||
public:
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ICompressCoder2> Coder2;
|
||||
UInt32 NumStreams;
|
||||
bool Finish;
|
||||
|
||||
UInt64 UnpackSize;
|
||||
const UInt64 *UnpackSizePointer;
|
||||
|
||||
CRecordVector<UInt64> PackSizes;
|
||||
CRecordVector<const UInt64 *> PackSizePointers;
|
||||
|
||||
CCoder(): Finish(false) {}
|
||||
|
||||
void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);
|
||||
|
||||
HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;
|
||||
|
||||
IUnknown *GetUnknown() const
|
||||
{
|
||||
return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
|
||||
}
|
||||
|
||||
HRESULT QueryInterface(REFGUID iid, void** pp) const
|
||||
{
|
||||
return GetUnknown()->QueryInterface(iid, pp);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CMixer
|
||||
{
|
||||
bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
|
||||
|
||||
protected:
|
||||
CBindInfo _bi;
|
||||
|
||||
int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const
|
||||
{
|
||||
if (EncodeMode == forInputStream)
|
||||
return _bi.FindBond_for_UnpackStream(streamIndex);
|
||||
else
|
||||
return _bi.FindBond_for_PackStream(streamIndex);
|
||||
}
|
||||
|
||||
CBoolVector IsFilter_Vector;
|
||||
CBoolVector IsExternal_Vector;
|
||||
bool EncodeMode;
|
||||
public:
|
||||
unsigned MainCoderIndex;
|
||||
|
||||
// bool InternalPackSizeError;
|
||||
|
||||
CMixer(bool encodeMode):
|
||||
EncodeMode(encodeMode),
|
||||
MainCoderIndex(0)
|
||||
// , InternalPackSizeError(false)
|
||||
{}
|
||||
|
||||
virtual ~CMixer() {}
|
||||
/*
|
||||
Sequence of calling:
|
||||
|
||||
SetBindInfo();
|
||||
for each coder
|
||||
AddCoder();
|
||||
SelectMainCoder();
|
||||
|
||||
for each file
|
||||
{
|
||||
ReInit()
|
||||
for each coder
|
||||
SetCoderInfo();
|
||||
Code();
|
||||
}
|
||||
*/
|
||||
|
||||
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
_bi = bindInfo;
|
||||
IsFilter_Vector.Clear();
|
||||
MainCoderIndex = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual void AddCoder(const CCreatedCoder &cod) = 0;
|
||||
virtual CCoder &GetCoder(unsigned index) = 0;
|
||||
virtual void SelectMainCoder(bool useFirst) = 0;
|
||||
virtual HRESULT ReInit2() = 0;
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress,
|
||||
bool &dataAfterEnd_Error) = 0;
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
|
||||
|
||||
bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
|
||||
bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
|
||||
bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
|
||||
struct CCoderST: public CCoder
|
||||
{
|
||||
bool CanRead;
|
||||
bool CanWrite;
|
||||
|
||||
CCoderST(): CanRead(false), CanWrite(false) {}
|
||||
};
|
||||
|
||||
|
||||
struct CStBinderStream
|
||||
{
|
||||
CSequentialInStreamCalcSize *InStreamSpec;
|
||||
COutStreamCalcSize *OutStreamSpec;
|
||||
CMyComPtr<IUnknown> StreamRef;
|
||||
|
||||
CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
|
||||
};
|
||||
|
||||
|
||||
class CMixerST:
|
||||
public IUnknown,
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_UNKNOWN_IMP_0
|
||||
Z7_CLASS_NO_COPY(CMixerST)
|
||||
|
||||
HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
|
||||
HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
|
||||
HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
|
||||
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
|
||||
|
||||
HRESULT FinishStream(UInt32 streamIndex);
|
||||
HRESULT FinishCoder(UInt32 coderIndex);
|
||||
|
||||
public:
|
||||
CObjectVector<CCoderST> _coders;
|
||||
|
||||
CObjectVector<CStBinderStream> _binderStreams;
|
||||
|
||||
CMixerST(bool encodeMode);
|
||||
~CMixerST() Z7_DESTRUCTOR_override;
|
||||
|
||||
virtual void AddCoder(const CCreatedCoder &cod) Z7_override;
|
||||
virtual CCoder &GetCoder(unsigned index) Z7_override;
|
||||
virtual void SelectMainCoder(bool useFirst) Z7_override;
|
||||
virtual HRESULT ReInit2() Z7_override;
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress,
|
||||
bool &dataAfterEnd_Error) Z7_override;
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override;
|
||||
|
||||
HRESULT GetMainUnpackStream(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialInStream **inStreamRes);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
|
||||
class CCoderMT: public CCoder, public CVirtThread
|
||||
{
|
||||
Z7_CLASS_NO_COPY(CCoderMT)
|
||||
CRecordVector<ISequentialInStream*> InStreamPointers;
|
||||
CRecordVector<ISequentialOutStream*> OutStreamPointers;
|
||||
|
||||
private:
|
||||
virtual void Execute() Z7_override;
|
||||
public:
|
||||
bool EncodeMode;
|
||||
HRESULT Result;
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
|
||||
|
||||
void Release()
|
||||
{
|
||||
InStreamPointers.Clear();
|
||||
OutStreamPointers.Clear();
|
||||
unsigned i;
|
||||
for (i = 0; i < InStreams.Size(); i++)
|
||||
InStreams[i].Release();
|
||||
for (i = 0; i < OutStreams.Size(); i++)
|
||||
OutStreams[i].Release();
|
||||
}
|
||||
|
||||
class CReleaser
|
||||
{
|
||||
Z7_CLASS_NO_COPY(CReleaser)
|
||||
CCoderMT &_c;
|
||||
public:
|
||||
CReleaser(CCoderMT &c): _c(c) {}
|
||||
~CReleaser() { _c.Release(); }
|
||||
};
|
||||
|
||||
CCoderMT(): EncodeMode(false) {}
|
||||
~CCoderMT() Z7_DESTRUCTOR_override
|
||||
{
|
||||
/* WaitThreadFinish() will be called in ~CVirtThread().
|
||||
But we need WaitThreadFinish() call before CCoder destructor,
|
||||
and before destructors of this class members.
|
||||
*/
|
||||
CVirtThread::WaitThreadFinish();
|
||||
}
|
||||
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
};
|
||||
|
||||
|
||||
class CMixerMT:
|
||||
public IUnknown,
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_UNKNOWN_IMP_0
|
||||
Z7_CLASS_NO_COPY(CMixerMT)
|
||||
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
|
||||
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
|
||||
HRESULT ReturnIfError(HRESULT code);
|
||||
|
||||
// virtual ~CMixerMT() {}
|
||||
public:
|
||||
CObjectVector<CCoderMT> _coders;
|
||||
|
||||
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) Z7_override;
|
||||
virtual void AddCoder(const CCreatedCoder &cod) Z7_override;
|
||||
virtual CCoder &GetCoder(unsigned index) Z7_override;
|
||||
virtual void SelectMainCoder(bool useFirst) Z7_override;
|
||||
virtual HRESULT ReInit2() Z7_override;
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress,
|
||||
bool &dataAfterEnd_Error) Z7_override;
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override;
|
||||
|
||||
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
// DummyOutStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "DummyOutStream.h"
|
||||
|
||||
Z7_COM7F_IMF(CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 realProcessedSize = size;
|
||||
HRESULT res = S_OK;
|
||||
if (_stream)
|
||||
res = _stream->Write(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// DummyOutStream.h
|
||||
|
||||
#ifndef ZIP7_INC_DUMMY_OUT_STREAM_H
|
||||
#define ZIP7_INC_DUMMY_OUT_STREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
CDummyOutStream
|
||||
, ISequentialOutStream
|
||||
)
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void SetStream(ISequentialOutStream *outStream) { _stream = outStream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init() { _size = 0; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
// FindSignature.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "FindSignature.h"
|
||||
|
||||
HRESULT FindSignatureInStream(ISequentialInStream *stream,
|
||||
const Byte *signature, unsigned signatureSize,
|
||||
const UInt64 *limit, UInt64 &resPos)
|
||||
{
|
||||
resPos = 0;
|
||||
CByteBuffer byteBuffer2(signatureSize);
|
||||
RINOK(ReadStream_FALSE(stream, byteBuffer2, signatureSize))
|
||||
|
||||
if (memcmp(byteBuffer2, signature, signatureSize) == 0)
|
||||
return S_OK;
|
||||
|
||||
const size_t kBufferSize = 1 << 16;
|
||||
CByteBuffer byteBuffer(kBufferSize);
|
||||
Byte *buffer = byteBuffer;
|
||||
size_t numPrevBytes = signatureSize - 1;
|
||||
memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes);
|
||||
resPos = 1;
|
||||
for (;;)
|
||||
{
|
||||
if (limit)
|
||||
if (resPos > *limit)
|
||||
return S_FALSE;
|
||||
do
|
||||
{
|
||||
const size_t numReadBytes = kBufferSize - numPrevBytes;
|
||||
UInt32 processedSize;
|
||||
RINOK(stream->Read(buffer + numPrevBytes, (UInt32)numReadBytes, &processedSize))
|
||||
numPrevBytes += (size_t)processedSize;
|
||||
if (processedSize == 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
while (numPrevBytes < signatureSize);
|
||||
const size_t numTests = numPrevBytes - signatureSize + 1;
|
||||
for (size_t pos = 0; pos < numTests; pos++)
|
||||
{
|
||||
const Byte b = signature[0];
|
||||
for (; buffer[pos] != b && pos < numTests; pos++);
|
||||
if (pos == numTests)
|
||||
break;
|
||||
if (memcmp(buffer + pos, signature, signatureSize) == 0)
|
||||
{
|
||||
resPos += pos;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
resPos += numTests;
|
||||
numPrevBytes -= numTests;
|
||||
memmove(buffer, buffer + numTests, numPrevBytes);
|
||||
}
|
||||
}
|
||||
|
||||
namespace NArchive {
|
||||
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);
|
||||
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||
{
|
||||
areThereNonZeros = false;
|
||||
numZeros = 0;
|
||||
const size_t kBufSize = 1 << 11;
|
||||
Byte buf[kBufSize];
|
||||
for (;;)
|
||||
{
|
||||
UInt32 size = 0;
|
||||
RINOK(stream->Read(buf, kBufSize, &size))
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
if (buf[i] != 0)
|
||||
{
|
||||
areThereNonZeros = true;
|
||||
numZeros += i;
|
||||
return S_OK;
|
||||
}
|
||||
numZeros += size;
|
||||
if (numZeros > maxSize)
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// FindSignature.h
|
||||
|
||||
#ifndef ZIP7_INC_FIND_SIGNATURE_H
|
||||
#define ZIP7_INC_FIND_SIGNATURE_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
HRESULT FindSignatureInStream(ISequentialInStream *stream,
|
||||
const Byte *signature, unsigned signatureSize,
|
||||
const UInt64 *limit, UInt64 &resPos);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,315 @@
|
||||
// HandlerOut.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/StringToInt.h"
|
||||
|
||||
#include "HandlerOut.h"
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res)
|
||||
{
|
||||
if (*s == 0)
|
||||
{
|
||||
switch (prop.vt)
|
||||
{
|
||||
case VT_UI4: res = prop.ulVal; return true;
|
||||
case VT_UI8: res = prop.uhVal.QuadPart; return true;
|
||||
case VT_BSTR:
|
||||
s = prop.bstrVal;
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return false;
|
||||
|
||||
bool percentMode = false;
|
||||
{
|
||||
const wchar_t c = *s;
|
||||
if (MyCharLower_Ascii(c) == 'p')
|
||||
{
|
||||
percentMode = true;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *end;
|
||||
const UInt64 v = ConvertStringToUInt64(s, &end);
|
||||
if (s == end)
|
||||
return false;
|
||||
const wchar_t c = *end;
|
||||
|
||||
if (percentMode)
|
||||
{
|
||||
if (c != 0)
|
||||
return false;
|
||||
res = Calc_From_Val_Percents(percentsBase, v);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
res = v;
|
||||
return true;
|
||||
}
|
||||
if (end[1] != 0)
|
||||
return false;
|
||||
|
||||
if (c == '%')
|
||||
{
|
||||
res = Calc_From_Val_Percents(percentsBase, v);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned numBits;
|
||||
switch (MyCharLower_Ascii(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 false;
|
||||
}
|
||||
const UInt64 val2 = v << numBits;
|
||||
if ((val2 >> numBits) != v)
|
||||
return false;
|
||||
res = val2;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)
|
||||
{
|
||||
hres = S_OK;
|
||||
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
#ifndef Z7_ST
|
||||
_numThreads = _numProcessors;
|
||||
_numThreads_WasForced = false;
|
||||
hres = ParseMtProp2(name.Ptr(2), value, _numThreads, _numThreads_WasForced);
|
||||
// "mt" means "_numThreads_WasForced = false" here
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
|
||||
{
|
||||
UInt64 v;
|
||||
if (!ParseSizeString(name.Ptr(6), value, _memAvail, v))
|
||||
hres = E_INVALIDARG;
|
||||
_memUsage_Decompress = v;
|
||||
_memUsage_Compress = v;
|
||||
_memUsage_WasSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
|
||||
static void SetMethodProp32(CMethodProps &m, PROPID propID, UInt32 value)
|
||||
{
|
||||
if (m.FindProp(propID) < 0)
|
||||
m.AddProp32(propID, value);
|
||||
}
|
||||
|
||||
void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
|
||||
{
|
||||
UInt32 level = _level;
|
||||
if (level != (UInt32)(Int32)-1)
|
||||
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
|
||||
}
|
||||
|
||||
#ifndef Z7_ST
|
||||
|
||||
static void SetMethodProp32_Replace(CMethodProps &m, PROPID propID, UInt32 value)
|
||||
{
|
||||
const int i = m.FindProp(propID);
|
||||
if (i >= 0)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant &val = m.Props[(unsigned)i].Value;
|
||||
val = (UInt32)value;
|
||||
return;
|
||||
}
|
||||
m.AddProp32(propID, value);
|
||||
}
|
||||
|
||||
void CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreads)
|
||||
{
|
||||
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
||||
}
|
||||
|
||||
void CMultiMethodProps::SetMethodThreadsTo_Replace(CMethodProps &oneMethodInfo, UInt32 numThreads)
|
||||
{
|
||||
SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
||||
}
|
||||
|
||||
void CMultiMethodProps::Set_Method_NumThreadGroups_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreadGroups)
|
||||
{
|
||||
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreadGroups, numThreadGroups);
|
||||
}
|
||||
|
||||
#endif // Z7_ST
|
||||
|
||||
|
||||
void CMultiMethodProps::InitMulti()
|
||||
{
|
||||
_level = (UInt32)(Int32)-1;
|
||||
_analysisLevel = -1;
|
||||
_crcSize = 4;
|
||||
_autoFilter = true;
|
||||
}
|
||||
|
||||
void CMultiMethodProps::Init()
|
||||
{
|
||||
InitCommon();
|
||||
InitMulti();
|
||||
_methods.Clear();
|
||||
_filterMethod.Clear();
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
{
|
||||
UString name = nameSpec;
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (name[0] == 'x')
|
||||
{
|
||||
name.Delete(0);
|
||||
_level = 9;
|
||||
return ParsePropToUInt32(name, value, _level);
|
||||
}
|
||||
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("yx"))
|
||||
{
|
||||
name.Delete(0, 2);
|
||||
UInt32 v = 9;
|
||||
RINOK(ParsePropToUInt32(name, value, v))
|
||||
_analysisLevel = (int)v;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("crc"))
|
||||
{
|
||||
name.Delete(0, 3);
|
||||
_crcSize = 4;
|
||||
return ParsePropToUInt32(name, value, _crcSize);
|
||||
}
|
||||
|
||||
{
|
||||
HRESULT hres;
|
||||
if (SetCommonProperty(name, value, hres))
|
||||
return hres;
|
||||
}
|
||||
|
||||
UInt32 number;
|
||||
const unsigned index = ParseStringToUInt32(name, number);
|
||||
const UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsEqualTo("f"))
|
||||
{
|
||||
const HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
|
||||
if (res == S_OK)
|
||||
return res;
|
||||
if (value.vt != VT_BSTR)
|
||||
return E_INVALIDARG;
|
||||
return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
|
||||
}
|
||||
number = 0;
|
||||
}
|
||||
if (number > 64)
|
||||
return E_INVALIDARG;
|
||||
for (unsigned j = _methods.Size(); j <= number; j++)
|
||||
_methods.AddNew();
|
||||
return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CSingleMethodProps::Init()
|
||||
{
|
||||
InitCommon();
|
||||
InitSingle();
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
HRESULT CSingleMethodProps::SetProperty(const wchar_t *name2, const PROPVARIANT &value)
|
||||
{
|
||||
// processed = false;
|
||||
UString name = name2;
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("x"))
|
||||
{
|
||||
UInt32 a = 9;
|
||||
RINOK(ParsePropToUInt32(name.Ptr(1), value, a))
|
||||
_level = a;
|
||||
AddProp_Level(a);
|
||||
// processed = true;
|
||||
return S_OK;
|
||||
}
|
||||
{
|
||||
HRESULT hres;
|
||||
if (SetCommonProperty(name, value, hres))
|
||||
{
|
||||
// processed = true;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
RINOK(ParseMethodFromPROPVARIANT(name, value))
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
Init();
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
RINOK(SetProperty(names[i], values[i]))
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, dest.Val))
|
||||
dest.Def = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandlerTimeOptions::Parse(const UString &name, const PROPVARIANT &prop, bool &processed)
|
||||
{
|
||||
processed = true;
|
||||
if (name.IsEqualTo_Ascii_NoCase("tm")) { return PROPVARIANT_to_BoolPair(prop, Write_MTime); }
|
||||
if (name.IsEqualTo_Ascii_NoCase("ta")) { return PROPVARIANT_to_BoolPair(prop, Write_ATime); }
|
||||
if (name.IsEqualTo_Ascii_NoCase("tc")) { return PROPVARIANT_to_BoolPair(prop, Write_CTime); }
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("tp"))
|
||||
{
|
||||
UInt32 v = 0;
|
||||
RINOK(ParsePropToUInt32(name.Ptr(2), prop, v))
|
||||
Prec = v;
|
||||
return S_OK;
|
||||
}
|
||||
processed = false;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
// HandlerOut.h
|
||||
|
||||
#ifndef ZIP7_INC_HANDLER_OUT_H
|
||||
#define ZIP7_INC_HANDLER_OUT_H
|
||||
|
||||
#include "../../../Windows/System.h"
|
||||
|
||||
#include "../../Common/MethodProps.h"
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
bool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res);
|
||||
|
||||
class CCommonMethodProps
|
||||
{
|
||||
protected:
|
||||
void InitCommon()
|
||||
{
|
||||
// _Write_MTime = true;
|
||||
{
|
||||
#ifndef Z7_ST
|
||||
_numThreads_WasForced = false;
|
||||
UInt32 numThreads;
|
||||
#ifdef _WIN32
|
||||
NWindows::NSystem::CProcessAffinity aff;
|
||||
numThreads = aff.Load_and_GetNumberOfThreads();
|
||||
_numThreadGroups = aff.IsGroupMode ? aff.Groups.GroupSizes.Size() : 0;
|
||||
#else
|
||||
numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
||||
#endif // _WIN32
|
||||
_numProcessors = _numThreads = numThreads;
|
||||
#endif // Z7_ST
|
||||
}
|
||||
|
||||
size_t memAvail = (size_t)sizeof(size_t) << 28;
|
||||
_memAvail = memAvail;
|
||||
_memUsage_Compress = memAvail;
|
||||
_memUsage_Decompress = memAvail;
|
||||
_memUsage_WasSet = NWindows::NSystem::GetRamSize(memAvail);
|
||||
if (_memUsage_WasSet)
|
||||
{
|
||||
_memAvail = memAvail;
|
||||
unsigned bits = sizeof(size_t) * 8;
|
||||
if (bits == 32)
|
||||
{
|
||||
const UInt32 limit2 = (UInt32)7 << 28;
|
||||
if (memAvail > limit2)
|
||||
memAvail = limit2;
|
||||
}
|
||||
// 80% - is auto usage limit in handlers
|
||||
// _memUsage_Compress = memAvail * 4 / 5;
|
||||
// _memUsage_Compress = Calc_From_Val_Percents(memAvail, 80);
|
||||
_memUsage_Compress = Calc_From_Val_Percents_Less100(memAvail, 80);
|
||||
_memUsage_Decompress = memAvail / 32 * 17;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
#ifndef Z7_ST
|
||||
UInt32 _numThreads;
|
||||
UInt32 _numProcessors;
|
||||
#ifdef _WIN32
|
||||
UInt32 _numThreadGroups;
|
||||
#endif
|
||||
bool _numThreads_WasForced;
|
||||
#endif
|
||||
|
||||
bool _memUsage_WasSet;
|
||||
UInt64 _memUsage_Compress;
|
||||
UInt64 _memUsage_Decompress;
|
||||
size_t _memAvail;
|
||||
|
||||
bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);
|
||||
|
||||
CCommonMethodProps() { InitCommon(); }
|
||||
};
|
||||
|
||||
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
|
||||
class CMultiMethodProps: public CCommonMethodProps
|
||||
{
|
||||
UInt32 _level;
|
||||
int _analysisLevel;
|
||||
|
||||
void InitMulti();
|
||||
public:
|
||||
UInt32 _crcSize;
|
||||
CObjectVector<COneMethodInfo> _methods;
|
||||
COneMethodInfo _filterMethod;
|
||||
bool _autoFilter;
|
||||
|
||||
|
||||
void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const;
|
||||
|
||||
#ifndef Z7_ST
|
||||
static void SetMethodThreadsTo_IfNotFinded(CMethodProps &props, UInt32 numThreads);
|
||||
static void SetMethodThreadsTo_Replace(CMethodProps &props, UInt32 numThreads);
|
||||
|
||||
static void Set_Method_NumThreadGroups_IfNotFinded(CMethodProps &props, UInt32 numThreadGroups);
|
||||
#endif
|
||||
|
||||
|
||||
unsigned GetNumEmptyMethods() const
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < _methods.Size(); i++)
|
||||
if (!_methods[i].IsEmpty())
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
|
||||
int GetAnalysisLevel() const { return _analysisLevel; }
|
||||
|
||||
void Init();
|
||||
CMultiMethodProps() { InitMulti(); }
|
||||
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
};
|
||||
|
||||
|
||||
class CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps
|
||||
{
|
||||
UInt32 _level;
|
||||
|
||||
void InitSingle()
|
||||
{
|
||||
_level = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
public:
|
||||
void Init();
|
||||
CSingleMethodProps() { InitSingle(); }
|
||||
|
||||
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &values);
|
||||
HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct CHandlerTimeOptions
|
||||
{
|
||||
CBoolPair Write_MTime;
|
||||
CBoolPair Write_ATime;
|
||||
CBoolPair Write_CTime;
|
||||
UInt32 Prec;
|
||||
|
||||
void Init()
|
||||
{
|
||||
Write_MTime.Init();
|
||||
Write_MTime.Val = true;
|
||||
Write_ATime.Init();
|
||||
Write_CTime.Init();
|
||||
Prec = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
CHandlerTimeOptions()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
HRESULT Parse(const UString &name, const PROPVARIANT &prop, bool &processed);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// InStreamWithCRC.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "InStreamWithCRC.h"
|
||||
|
||||
Z7_COM7F_IMF(CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT result = S_OK;
|
||||
if (size != 0)
|
||||
{
|
||||
if (_stream)
|
||||
result = _stream->Read(data, size, &realProcessed);
|
||||
_size += realProcessed;
|
||||
if (realProcessed == 0)
|
||||
_wasFinished = true;
|
||||
else
|
||||
_crc = CrcUpdate(_crc, data, realProcessed);
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
return result;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CSequentialInStreamWithCRC::GetSize(UInt64 *size))
|
||||
{
|
||||
*size = _fullSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Read(data, size, &realProcessed);
|
||||
_size += realProcessed;
|
||||
/*
|
||||
if (size != 0 && realProcessed == 0)
|
||||
_wasFinished = true;
|
||||
*/
|
||||
_crc = CrcUpdate(_crc, data, realProcessed);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
return result;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
if (seekOrigin != STREAM_SEEK_SET || offset != 0)
|
||||
return E_FAIL;
|
||||
_size = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
return _stream->Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// InStreamWithCRC.h
|
||||
|
||||
#ifndef ZIP7_INC_IN_STREAM_WITH_CRC_H
|
||||
#define ZIP7_INC_IN_STREAM_WITH_CRC_H
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_2(
|
||||
CSequentialInStreamWithCRC
|
||||
, ISequentialInStream
|
||||
, IStreamGetSize
|
||||
)
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
UInt32 _crc;
|
||||
bool _wasFinished;
|
||||
UInt64 _fullSize;
|
||||
public:
|
||||
|
||||
CSequentialInStreamWithCRC():
|
||||
_fullSize((UInt64)(Int64)-1)
|
||||
{}
|
||||
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void SetFullSize(UInt64 fullSize) { _fullSize = fullSize; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_wasFinished = false;
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CInStreamWithCRC
|
||||
)
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _size;
|
||||
UInt32 _crc;
|
||||
// bool _wasFinished;
|
||||
public:
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
// _wasFinished = false;
|
||||
_crc = CRC_INIT_VAL;
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
// bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
// Archive/Common/ItemNameUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ItemNameUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR;
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
static const wchar_t kUnixPathSepar = L'/';
|
||||
#endif
|
||||
|
||||
void ReplaceSlashes_OsToUnix
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
(UString &name)
|
||||
{
|
||||
name.Replace(kOsPathSepar, kUnixPathSepar);
|
||||
}
|
||||
#else
|
||||
(UString &) {}
|
||||
#endif
|
||||
|
||||
|
||||
UString GetOsPath(const UString &name)
|
||||
{
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
UString newName = name;
|
||||
newName.Replace(kUnixPathSepar, kOsPathSepar);
|
||||
return newName;
|
||||
#else
|
||||
return name;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
UString GetOsPath_Remove_TailSlash(const UString &name)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return UString();
|
||||
UString newName = GetOsPath(name);
|
||||
if (newName.Back() == kOsPathSepar)
|
||||
newName.DeleteBack();
|
||||
return newName;
|
||||
}
|
||||
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
void ReplaceToWinSlashes(UString &name, bool useBackslashReplacement)
|
||||
{
|
||||
// name.Replace(kUnixPathSepar, kOsPathSepar);
|
||||
const unsigned len = name.Len();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = name[i];
|
||||
if (c == L'/')
|
||||
c = WCHAR_PATH_SEPARATOR;
|
||||
else if (useBackslashReplacement && c == L'\\')
|
||||
c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
|
||||
else
|
||||
continue;
|
||||
name.ReplaceOneCharAtPos(i, c);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
useBackslashReplacement
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return;
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
ReplaceToWinSlashes(name, useBackslashReplacement);
|
||||
#endif
|
||||
|
||||
if (name.Back() == kOsPathSepar)
|
||||
name.DeleteBack();
|
||||
}
|
||||
|
||||
|
||||
void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *name, unsigned len)
|
||||
{
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = name[i];
|
||||
if (c == L'/')
|
||||
c = L'_';
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
else if (c == L'\\')
|
||||
c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
|
||||
#endif
|
||||
else
|
||||
continue;
|
||||
name[i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
void NormalizeSlashes_in_FileName_for_OsPath(UString &name)
|
||||
{
|
||||
NormalizeSlashes_in_FileName_for_OsPath(name.GetBuf(), name.Len());
|
||||
}
|
||||
|
||||
|
||||
bool HasTailSlash(const AString &name, UINT
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
codePage
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return false;
|
||||
char c;
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (codePage != CP_UTF8)
|
||||
c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
c = name.Back();
|
||||
}
|
||||
return (c == '/');
|
||||
}
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
UString WinPathToOsPath(const UString &name)
|
||||
{
|
||||
UString newName = name;
|
||||
newName.Replace(L'\\', WCHAR_PATH_SEPARATOR);
|
||||
return newName;
|
||||
}
|
||||
#endif
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Archive/Common/ItemNameUtils.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_ITEM_NAME_UTILS_H
|
||||
#define ZIP7_INC_ARCHIVE_ITEM_NAME_UTILS_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
void ReplaceSlashes_OsToUnix(UString &name);
|
||||
|
||||
UString GetOsPath(const UString &name);
|
||||
UString GetOsPath_Remove_TailSlash(const UString &name);
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
void ReplaceToWinSlashes(UString &name, bool useBackslashReplacement);
|
||||
#endif
|
||||
void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false);
|
||||
void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *s, unsigned len);
|
||||
void NormalizeSlashes_in_FileName_for_OsPath(UString &name);
|
||||
|
||||
bool HasTailSlash(const AString &name, UINT codePage);
|
||||
|
||||
#ifdef _WIN32
|
||||
inline UString WinPathToOsPath(const UString &name) { return name; }
|
||||
#else
|
||||
UString WinPathToOsPath(const UString &name);
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
// MultiStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "MultiStream.h"
|
||||
|
||||
Z7_COM7F_IMF(CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= _totalLength)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
unsigned left = 0, mid = _streamIndex, right = Streams.Size();
|
||||
for (;;)
|
||||
{
|
||||
CSubStreamInfo &m = Streams[mid];
|
||||
if (_pos < m.GlobalOffset)
|
||||
right = mid;
|
||||
else if (_pos >= m.GlobalOffset + m.Size)
|
||||
left = mid + 1;
|
||||
else
|
||||
break;
|
||||
mid = (left + right) / 2;
|
||||
}
|
||||
_streamIndex = mid;
|
||||
}
|
||||
|
||||
CSubStreamInfo &s = Streams[_streamIndex];
|
||||
UInt64 localPos = _pos - s.GlobalOffset;
|
||||
if (localPos != s.LocalPos)
|
||||
{
|
||||
RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos))
|
||||
}
|
||||
{
|
||||
const UInt64 rem = s.Size - localPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
const HRESULT result = s.Stream->Read(data, size, &size);
|
||||
_pos += size;
|
||||
s.LocalPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += _totalLength; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = (UInt64)offset;
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
class COutVolumeStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_UNKNOWN_IMP_0
|
||||
Z7_IFACE_COM7_IMP(ISequentialOutStream)
|
||||
|
||||
unsigned _volIndex;
|
||||
UInt64 _volSize;
|
||||
UInt64 _curPos;
|
||||
CMyComPtr<ISequentialOutStream> _volumeStream;
|
||||
COutArchive _archive;
|
||||
CCRC _crc;
|
||||
|
||||
public:
|
||||
CFileItem _file;
|
||||
CUpdateOptions _options;
|
||||
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
|
||||
void Init(IArchiveUpdateCallback2 *volumeCallback,
|
||||
const UString &name)
|
||||
{
|
||||
_file.Name = name;
|
||||
_file.IsStartPosDefined = true;
|
||||
_file.StartPos = 0;
|
||||
|
||||
VolumeCallback = volumeCallback;
|
||||
_volIndex = 0;
|
||||
_volSize = 0;
|
||||
}
|
||||
|
||||
HRESULT Flush();
|
||||
};
|
||||
|
||||
HRESULT COutVolumeStream::Flush()
|
||||
{
|
||||
if (_volumeStream)
|
||||
{
|
||||
_file.UnPackSize = _curPos;
|
||||
_file.FileCRC = _crc.GetDigest();
|
||||
RINOK(WriteVolumeHeader(_archive, _file, _options))
|
||||
_archive.Close();
|
||||
_volumeStream.Release();
|
||||
_file.StartPos += _file.UnPackSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
#include "../../../Common/Defs.h"
|
||||
|
||||
Z7_COM7F_IMF(COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
while (size > 0)
|
||||
{
|
||||
if (_streamIndex >= Streams.Size())
|
||||
{
|
||||
CSubStreamInfo subStream;
|
||||
RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size))
|
||||
RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream))
|
||||
subStream.Pos = 0;
|
||||
Streams.Add(subStream);
|
||||
continue;
|
||||
}
|
||||
CSubStreamInfo &subStream = Streams[_streamIndex];
|
||||
if (_offsetPos >= subStream.Size)
|
||||
{
|
||||
_offsetPos -= subStream.Size;
|
||||
_streamIndex++;
|
||||
continue;
|
||||
}
|
||||
if (_offsetPos != subStream.Pos)
|
||||
{
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream))
|
||||
RINOK(outStream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL))
|
||||
subStream.Pos = _offsetPos;
|
||||
}
|
||||
|
||||
const UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
|
||||
UInt32 realProcessed;
|
||||
RINOK(subStream.Stream->Write(data, curSize, &realProcessed))
|
||||
data = (const void *)((const Byte *)data + realProcessed);
|
||||
size -= realProcessed;
|
||||
subStream.Pos += realProcessed;
|
||||
_offsetPos += realProcessed;
|
||||
_absPos += realProcessed;
|
||||
if (_absPos > _length)
|
||||
_length = _absPos;
|
||||
if (processedSize)
|
||||
*processedSize += realProcessed;
|
||||
if (subStream.Pos == subStream.Size)
|
||||
{
|
||||
_streamIndex++;
|
||||
_offsetPos = 0;
|
||||
}
|
||||
if (realProcessed != curSize && realProcessed == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _absPos; break;
|
||||
case STREAM_SEEK_END: offset += _length; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_absPos = (UInt64)offset;
|
||||
_offsetPos = _absPos;
|
||||
_streamIndex = 0;
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)offset;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,86 @@
|
||||
// MultiStream.h
|
||||
|
||||
#ifndef ZIP7_INC_MULTI_STREAM_H
|
||||
#define ZIP7_INC_MULTI_STREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CMultiStream
|
||||
)
|
||||
|
||||
unsigned _streamIndex;
|
||||
UInt64 _pos;
|
||||
UInt64 _totalLength;
|
||||
|
||||
public:
|
||||
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Size;
|
||||
UInt64 GlobalOffset;
|
||||
UInt64 LocalPos;
|
||||
CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {}
|
||||
};
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallbackFile> updateCallbackFile;
|
||||
CObjectVector<CSubStreamInfo> Streams;
|
||||
|
||||
HRESULT Init()
|
||||
{
|
||||
UInt64 total = 0;
|
||||
FOR_VECTOR (i, Streams)
|
||||
{
|
||||
CSubStreamInfo &s = Streams[i];
|
||||
s.GlobalOffset = total;
|
||||
total += s.Size;
|
||||
s.LocalPos = 0;
|
||||
{
|
||||
// it was already set to start
|
||||
// RINOK(InStream_GetPos(s.Stream, s.LocalPos));
|
||||
}
|
||||
}
|
||||
_totalLength = total;
|
||||
_pos = 0;
|
||||
_streamIndex = 0;
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
COutMultiStream,
|
||||
IOutStream
|
||||
)
|
||||
Z7_IFACE_COM7_IMP(ISequentialOutStream)
|
||||
|
||||
unsigned _streamIndex; // required stream
|
||||
UInt64 _offsetPos; // offset from start of _streamIndex index
|
||||
UInt64 _absPos;
|
||||
UInt64 _length;
|
||||
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> Stream;
|
||||
UInt64 Size;
|
||||
UInt64 Pos;
|
||||
};
|
||||
CObjectVector<CSubStreamInfo> Streams;
|
||||
public:
|
||||
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
|
||||
void Init()
|
||||
{
|
||||
_streamIndex = 0;
|
||||
_offsetPos = 0;
|
||||
_absPos = 0;
|
||||
_length = 0;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
// OutStreamWithCRC.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OutStreamWithCRC.h"
|
||||
|
||||
Z7_COM7F_IMF(COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
if (_calculate)
|
||||
_crc = CrcUpdate(_crc, data, size);
|
||||
_size += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// OutStreamWithCRC.h
|
||||
|
||||
#ifndef ZIP7_INC_OUT_STREAM_WITH_CRC_H
|
||||
#define ZIP7_INC_OUT_STREAM_WITH_CRC_H
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
COutStreamWithCRC
|
||||
, ISequentialOutStream
|
||||
)
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
UInt32 _crc;
|
||||
bool _calculate;
|
||||
public:
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(bool calculate = true)
|
||||
{
|
||||
_size = 0;
|
||||
_calculate = calculate;
|
||||
_crc = CRC_INIT_VAL;
|
||||
}
|
||||
void EnableCalc(bool calculate) { _calculate = calculate; }
|
||||
void InitCRC() { _crc = CRC_INIT_VAL; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
// OutStreamWithSha1.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OutStreamWithSha1.h"
|
||||
|
||||
Z7_COM7F_IMF(COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
if (_calculate)
|
||||
Sha1_Update(Sha(), (const Byte *)data, size);
|
||||
_size += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
const HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
Sha1_Update(Sha(), (const Byte *)data, realProcessedSize);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// OutStreamWithSha1.h
|
||||
|
||||
#ifndef ZIP7_INC_OUT_STREAM_WITH_SHA1_H
|
||||
#define ZIP7_INC_OUT_STREAM_WITH_SHA1_H
|
||||
|
||||
#include "../../../../C/Sha1.h"
|
||||
|
||||
#include "../../../Common/MyBuffer2.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
COutStreamWithSha1
|
||||
, ISequentialOutStream
|
||||
)
|
||||
bool _calculate;
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
CAlignedBuffer1 _sha;
|
||||
UInt64 _size;
|
||||
|
||||
CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }
|
||||
public:
|
||||
COutStreamWithSha1(): _sha(sizeof(CSha1)) {}
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(bool calculate = true)
|
||||
{
|
||||
_calculate = calculate;
|
||||
_size = 0;
|
||||
Sha1_Init(Sha());
|
||||
}
|
||||
void InitSha1() { Sha1_Init(Sha()); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
void Final(Byte *digest) { Sha1_Final(Sha(), digest); }
|
||||
};
|
||||
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
CInStreamWithSha1
|
||||
, ISequentialInStream
|
||||
)
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
CAlignedBuffer1 _sha;
|
||||
UInt64 _size;
|
||||
|
||||
CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }
|
||||
public:
|
||||
CInStreamWithSha1(): _sha(sizeof(CSha1)) {}
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
Sha1_Init(Sha());
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
void Final(Byte *digest) { Sha1_Final(Sha(), digest); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
// ParseProperties.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,6 @@
|
||||
// ParseProperties.h
|
||||
|
||||
#ifndef ZIP7_INC_PARSE_PROPERTIES_H
|
||||
#define ZIP7_INC_PARSE_PROPERTIES_H
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,784 @@
|
||||
// CramfsHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/LzmaDec.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyLinux.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
|
||||
#include "../../Windows/PropVariantUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamObjects.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
#include "../Compress/ZlibDecoder.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCramfs {
|
||||
|
||||
static const Byte kSignature[] =
|
||||
{ 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' };
|
||||
|
||||
static const UInt32 kArcSizeMax = (256 + 16) << 20;
|
||||
static const UInt32 kNumFilesMax = (1 << 19);
|
||||
static const unsigned kNumDirLevelsMax = (1 << 8);
|
||||
|
||||
static const UInt32 kHeaderSize = 0x40;
|
||||
static const unsigned kHeaderNameSize = 16;
|
||||
static const UInt32 kNodeSize = 12;
|
||||
|
||||
static const UInt32 kFlag_FsVer2 = (1 << 0);
|
||||
|
||||
static const unsigned k_Flags_BlockSize_Shift = 11;
|
||||
static const unsigned k_Flags_BlockSize_Mask = 7;
|
||||
static const unsigned k_Flags_Method_Shift = 14;
|
||||
static const unsigned k_Flags_Method_Mask = 3;
|
||||
|
||||
/*
|
||||
There is possible collision in flags:
|
||||
- Original CramFS writes 0 in method field. But it uses ZLIB.
|
||||
- Modified CramFS writes 0 in method field for "NONE" compression?
|
||||
How to solve that collision?
|
||||
*/
|
||||
|
||||
#define k_Flags_Method_NONE 0
|
||||
#define k_Flags_Method_ZLIB 1
|
||||
#define k_Flags_Method_LZMA 2
|
||||
|
||||
static const char * const k_Methods[] =
|
||||
{
|
||||
"Copy"
|
||||
, "ZLIB"
|
||||
, "LZMA"
|
||||
, "Unknown"
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair k_Flags[] =
|
||||
{
|
||||
{ 0, "Ver2" },
|
||||
{ 1, "SortedDirs" },
|
||||
{ 8, "Holes" },
|
||||
{ 9, "WrongSignature" },
|
||||
{ 10, "ShiftedRootOffset" }
|
||||
};
|
||||
|
||||
static const unsigned kBlockSizeLog = 12;
|
||||
|
||||
/*
|
||||
struct CNode
|
||||
{
|
||||
UInt16 Mode;
|
||||
UInt16 Uid;
|
||||
UInt32 Size;
|
||||
Byte Gid;
|
||||
UInt32 NameLen;
|
||||
UInt32 Offset;
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
Mode = GetUi16(p);
|
||||
Uid = GetUi16(p + 2);
|
||||
Size = Get32(p + 4) & 0xFFFFFF;
|
||||
Gid = p[7];
|
||||
NameLen = p[8] & 0x3F;
|
||||
Offset = Get32(p + 8) >> 6;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
#define Get32(p) (be ? GetBe32(p) : GetUi32(p))
|
||||
|
||||
static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
|
||||
static bool IsDir(const Byte *p, bool be) { return MY_LIN_S_ISDIR(GetMode(p, be)); }
|
||||
|
||||
static UInt32 GetSize(const Byte *p, bool be)
|
||||
{
|
||||
if (be)
|
||||
return GetBe32(p + 4) >> 8;
|
||||
else
|
||||
return GetUi32(p + 4) & 0xFFFFFF;
|
||||
}
|
||||
|
||||
static UInt32 GetNameLen(const Byte *p, bool be)
|
||||
{
|
||||
if (be)
|
||||
return (p[8] & 0xFC);
|
||||
else
|
||||
return ((UInt32)p[8] & (UInt32)0x3F) << 2;
|
||||
}
|
||||
|
||||
static UInt32 GetOffset(const Byte *p, bool be)
|
||||
{
|
||||
if (be)
|
||||
return (GetBe32(p + 8) & 0x03FFFFFF) << 2;
|
||||
else
|
||||
return GetUi32(p + 8) >> 6 << 2;
|
||||
}
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 Offset;
|
||||
int Parent;
|
||||
};
|
||||
|
||||
struct CHeader
|
||||
{
|
||||
bool be;
|
||||
UInt32 Size;
|
||||
UInt32 Flags;
|
||||
// UInt32 Future;
|
||||
UInt32 Crc;
|
||||
// UInt32 Edition;
|
||||
UInt32 NumBlocks;
|
||||
UInt32 NumFiles;
|
||||
char Name[kHeaderNameSize];
|
||||
|
||||
bool Parse(const Byte *p)
|
||||
{
|
||||
if (memcmp(p + 16, kSignature, Z7_ARRAY_SIZE(kSignature)) != 0)
|
||||
return false;
|
||||
switch (GetUi32(p))
|
||||
{
|
||||
case 0x28CD3D45: be = false; break;
|
||||
case 0x453DCD28: be = true; break;
|
||||
default: return false;
|
||||
}
|
||||
Size = Get32(p + 4);
|
||||
Flags = Get32(p + 8);
|
||||
// Future = Get32(p + 0xC);
|
||||
Crc = Get32(p + 0x20);
|
||||
// Edition = Get32(p + 0x24);
|
||||
NumBlocks = Get32(p + 0x28);
|
||||
NumFiles = Get32(p + 0x2C);
|
||||
memcpy(Name, p + 0x30, kHeaderNameSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; }
|
||||
unsigned GetBlockSizeShift() const { return (unsigned)(Flags >> k_Flags_BlockSize_Shift) & k_Flags_BlockSize_Mask; }
|
||||
unsigned GetMethod() const { return (unsigned)(Flags >> k_Flags_Method_Shift) & k_Flags_Method_Mask; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_1(
|
||||
IInArchiveGetStream
|
||||
)
|
||||
CRecordVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
Byte *_data;
|
||||
UInt32 _size;
|
||||
UInt32 _headersSize;
|
||||
|
||||
UInt32 _errorFlags;
|
||||
bool _isArc;
|
||||
|
||||
CHeader _h;
|
||||
UInt32 _phySize;
|
||||
|
||||
unsigned _method;
|
||||
unsigned _blockSizeLog;
|
||||
|
||||
// Current file
|
||||
|
||||
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
|
||||
CMyComPtr<ICompressCoder> _zlibDecoder;
|
||||
|
||||
CBufInStream *_inStreamSpec;
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
|
||||
CBufPtrSeqOutStream *_outStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _outStream;
|
||||
|
||||
UInt32 _curBlocksOffset;
|
||||
UInt32 _curNumBlocks;
|
||||
|
||||
HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level);
|
||||
HRESULT Open2(IInStream *inStream);
|
||||
AString GetPath(unsigned index) const;
|
||||
bool GetPackSize(unsigned index, UInt32 &res) const;
|
||||
void Free();
|
||||
|
||||
UInt32 GetNumBlocks(UInt32 size) const
|
||||
{
|
||||
return (size + ((UInt32)1 << _blockSizeLog) - 1) >> _blockSizeLog;
|
||||
}
|
||||
|
||||
void UpdatePhySize(UInt32 s)
|
||||
{
|
||||
if (_phySize < s)
|
||||
_phySize = s;
|
||||
}
|
||||
|
||||
public:
|
||||
CHandler(): _data(NULL) {}
|
||||
~CHandler() { Free(); }
|
||||
HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidIsDir,
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
kpidPosixAttrib
|
||||
// kpidOffset
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidVolumeName,
|
||||
kpidBigEndian,
|
||||
kpidCharacts,
|
||||
kpidClusterSize,
|
||||
kpidMethod,
|
||||
kpidHeadersSize,
|
||||
kpidNumSubFiles,
|
||||
kpidNumBlocks
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)
|
||||
{
|
||||
const Byte *p = _data + baseOffset;
|
||||
bool be = _h.be;
|
||||
if (!IsDir(p, be))
|
||||
return S_OK;
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
UInt32 size = GetSize(p, be);
|
||||
if (offset == 0 && size == 0)
|
||||
return S_OK;
|
||||
UInt32 end = offset + size;
|
||||
if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax)
|
||||
return S_FALSE;
|
||||
UpdatePhySize(end);
|
||||
if (end > _headersSize)
|
||||
_headersSize = end;
|
||||
|
||||
unsigned startIndex = _items.Size();
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax)
|
||||
return S_FALSE;
|
||||
CItem item;
|
||||
item.Parent = parent;
|
||||
item.Offset = offset;
|
||||
_items.Add(item);
|
||||
UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be);
|
||||
if (size < nodeLen)
|
||||
return S_FALSE;
|
||||
offset += nodeLen;
|
||||
size -= nodeLen;
|
||||
}
|
||||
|
||||
unsigned endIndex = _items.Size();
|
||||
for (unsigned i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
RINOK(OpenDir((int)i, _items[i].Offset, level + 1))
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *inStream)
|
||||
{
|
||||
Byte buf[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize))
|
||||
if (!_h.Parse(buf))
|
||||
return S_FALSE;
|
||||
_method = k_Flags_Method_ZLIB;
|
||||
_blockSizeLog = kBlockSizeLog;
|
||||
_phySize = kHeaderSize;
|
||||
if (_h.IsVer2())
|
||||
{
|
||||
_method = _h.GetMethod();
|
||||
// FIT IT. Now we don't know correct way to work with collision in method field.
|
||||
if (_method == k_Flags_Method_NONE)
|
||||
_method = k_Flags_Method_ZLIB;
|
||||
_blockSizeLog = kBlockSizeLog + _h.GetBlockSizeShift();
|
||||
if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax)
|
||||
return S_FALSE;
|
||||
_phySize = _h.Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 size;
|
||||
RINOK(InStream_GetSize_SeekToEnd(inStream, size))
|
||||
if (size > kArcSizeMax)
|
||||
size = kArcSizeMax;
|
||||
_h.Size = (UInt32)size;
|
||||
RINOK(InStream_SeekSet(inStream, kHeaderSize))
|
||||
}
|
||||
_data = (Byte *)MidAlloc(_h.Size);
|
||||
if (!_data)
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy(_data, buf, kHeaderSize);
|
||||
size_t processed = _h.Size - kHeaderSize;
|
||||
RINOK(ReadStream(inStream, _data + kHeaderSize, &processed))
|
||||
if (processed < kNodeSize)
|
||||
return S_FALSE;
|
||||
_size = kHeaderSize + (UInt32)processed;
|
||||
if (_h.IsVer2())
|
||||
{
|
||||
if (_size != _h.Size)
|
||||
_errorFlags = kpv_ErrorFlags_UnexpectedEnd;
|
||||
else
|
||||
{
|
||||
SetUi32(_data + 0x20, 0)
|
||||
if (CrcCalc(_data, _h.Size) != _h.Crc)
|
||||
{
|
||||
_errorFlags = kpv_ErrorFlags_HeadersError;
|
||||
// _errorMessage = "CRC error";
|
||||
}
|
||||
}
|
||||
if (_h.NumFiles >= 1)
|
||||
_items.ClearAndReserve(_h.NumFiles - 1);
|
||||
}
|
||||
|
||||
RINOK(OpenDir(-1, kHeaderSize, 0))
|
||||
|
||||
if (!_h.IsVer2())
|
||||
{
|
||||
FOR_VECTOR (i, _items)
|
||||
{
|
||||
const CItem &item = _items[i];
|
||||
const Byte *p = _data + item.Offset;
|
||||
bool be = _h.be;
|
||||
if (IsDir(p, be))
|
||||
continue;
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
continue;
|
||||
UInt32 numBlocks = GetNumBlocks(GetSize(p, be));
|
||||
if (numBlocks == 0)
|
||||
continue;
|
||||
UInt32 start = offset + numBlocks * 4;
|
||||
if (start > _size)
|
||||
continue;
|
||||
UInt32 end = Get32(_data + start - 4);
|
||||
if (end >= start)
|
||||
UpdatePhySize(end);
|
||||
}
|
||||
|
||||
// Read tailing zeros. Most cramfs archives use 4096-bytes aligned zeros
|
||||
const UInt32 kTailSize_MAX = 1 << 12;
|
||||
UInt32 endPos = (_phySize + kTailSize_MAX - 1) & ~(kTailSize_MAX - 1);
|
||||
if (endPos > _size)
|
||||
endPos = _size;
|
||||
UInt32 pos;
|
||||
for (pos = _phySize; pos < endPos && _data[pos] == 0; pos++);
|
||||
if (pos == endPos)
|
||||
_phySize = endPos;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
AString CHandler::GetPath(unsigned index) const
|
||||
{
|
||||
unsigned len = 0;
|
||||
unsigned indexMem = index;
|
||||
for (;;)
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
unsigned size = GetNameLen(p, _h.be);
|
||||
p += kNodeSize;
|
||||
unsigned i;
|
||||
for (i = 0; i < size && p[i]; i++);
|
||||
len += i + 1;
|
||||
index = (unsigned)item.Parent;
|
||||
if (item.Parent < 0)
|
||||
break;
|
||||
}
|
||||
len--;
|
||||
|
||||
AString path;
|
||||
char *dest = path.GetBuf_SetEnd(len) + len;
|
||||
index = indexMem;
|
||||
for (;;)
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
unsigned size = GetNameLen(p, _h.be);
|
||||
p += kNodeSize;
|
||||
unsigned i;
|
||||
for (i = 0; i < size && p[i]; i++);
|
||||
dest -= i;
|
||||
memcpy(dest, p, i);
|
||||
index = (unsigned)item.Parent;
|
||||
if (item.Parent < 0)
|
||||
break;
|
||||
*(--dest) = CHAR_PATH_SEPARATOR;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
bool CHandler::GetPackSize(unsigned index, UInt32 &res) const
|
||||
{
|
||||
res = 0;
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
const bool be = _h.be;
|
||||
const UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
return false;
|
||||
const UInt32 numBlocks = GetNumBlocks(GetSize(p, be));
|
||||
if (numBlocks == 0)
|
||||
return true;
|
||||
const UInt32 start = offset + numBlocks * 4;
|
||||
if (start > _size)
|
||||
return false;
|
||||
const UInt32 end = Get32(_data + start - 4);
|
||||
if (end < start)
|
||||
return false;
|
||||
res = end - start;
|
||||
return true;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
Close();
|
||||
RINOK(Open2(stream))
|
||||
_isArc = true;
|
||||
_stream = stream;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
void CHandler::Free()
|
||||
{
|
||||
MidFree(_data);
|
||||
_data = NULL;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_isArc = false;
|
||||
_phySize = 0;
|
||||
_errorFlags = 0;
|
||||
_headersSize = 0;
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
Free();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidVolumeName:
|
||||
{
|
||||
char dest[kHeaderNameSize + 4];
|
||||
memcpy(dest, _h.Name, kHeaderNameSize);
|
||||
dest[kHeaderNameSize] = 0;
|
||||
prop = dest;
|
||||
break;
|
||||
}
|
||||
case kpidBigEndian: prop = _h.be; break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
|
||||
case kpidMethod: prop = k_Methods[_method]; break;
|
||||
case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
|
||||
case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break;
|
||||
case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break;
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidHeadersSize: prop = _headersSize; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = _errorFlags;
|
||||
if (!_isArc)
|
||||
v |= kpv_ErrorFlags_IsNotArc;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
bool be = _h.be;
|
||||
bool isDir = IsDir(p, be);
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;
|
||||
case kpidIsDir: prop = isDir; break;
|
||||
// case kpidOffset: prop = (UInt32)GetOffset(p, be); break;
|
||||
case kpidSize: if (!isDir) prop = GetSize(p, be); break;
|
||||
case kpidPackSize:
|
||||
if (!isDir)
|
||||
{
|
||||
UInt32 size;
|
||||
if (GetPackSize(index, size))
|
||||
prop = size;
|
||||
}
|
||||
break;
|
||||
case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
class CCramfsInStream: public CCachedInStream
|
||||
{
|
||||
HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) Z7_override;
|
||||
public:
|
||||
CHandler *Handler;
|
||||
};
|
||||
|
||||
HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
{
|
||||
return Handler->ReadBlock(blockIndex, dest, blockSize);
|
||||
}
|
||||
|
||||
HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
{
|
||||
if (_method == k_Flags_Method_ZLIB)
|
||||
{
|
||||
if (!_zlibDecoder)
|
||||
{
|
||||
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
|
||||
_zlibDecoder = _zlibDecoderSpec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_method != k_Flags_Method_LZMA)
|
||||
{
|
||||
// probably we must support no-compression archives here.
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
const bool be = _h.be;
|
||||
const Byte *p2 = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);
|
||||
const UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p2 - 4));
|
||||
const UInt32 end = Get32(p2);
|
||||
if (end < start || end > _size)
|
||||
return S_FALSE;
|
||||
const UInt32 inSize = end - start;
|
||||
|
||||
if (_method == k_Flags_Method_LZMA)
|
||||
{
|
||||
const unsigned kLzmaHeaderSize = LZMA_PROPS_SIZE + 4;
|
||||
if (inSize < kLzmaHeaderSize)
|
||||
return S_FALSE;
|
||||
const Byte *p = _data + start;
|
||||
UInt32 destSize32 = GetUi32(p + LZMA_PROPS_SIZE);
|
||||
if (destSize32 > blockSize)
|
||||
return S_FALSE;
|
||||
SizeT destLen = destSize32;
|
||||
SizeT srcLen = inSize - kLzmaHeaderSize;
|
||||
ELzmaStatus status;
|
||||
SRes res = LzmaDecode(dest, &destLen, p + kLzmaHeaderSize, &srcLen,
|
||||
p, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc);
|
||||
if (res != SZ_OK
|
||||
|| (status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
|| destLen != destSize32
|
||||
|| srcLen != inSize - kLzmaHeaderSize)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!_inStream)
|
||||
{
|
||||
_inStreamSpec = new CBufInStream();
|
||||
_inStream = _inStreamSpec;
|
||||
}
|
||||
if (!_outStream)
|
||||
{
|
||||
_outStreamSpec = new CBufPtrSeqOutStream();
|
||||
_outStream = _outStreamSpec;
|
||||
}
|
||||
_inStreamSpec->Init(_data + start, inSize);
|
||||
_outStreamSpec->Init(dest, blockSize);
|
||||
RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL))
|
||||
return (inSize == _zlibDecoderSpec->GetInputProcessedSize() &&
|
||||
_outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
bool be = _h.be;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset;
|
||||
if (!IsDir(p, be))
|
||||
totalSize += GetSize(p, be);
|
||||
}
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
UInt64 totalPackSize;
|
||||
totalSize = totalPackSize = 0;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
lps->InSize = totalPackSize;
|
||||
lps->OutSize = totalSize;
|
||||
RINOK(lps->SetCur())
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &outStream, askMode))
|
||||
const Byte *p = _data + item.Offset;
|
||||
|
||||
if (IsDir(p, be))
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
continue;
|
||||
}
|
||||
UInt32 curSize = GetSize(p, be);
|
||||
totalSize += curSize;
|
||||
UInt32 packSize;
|
||||
if (GetPackSize(index, packSize))
|
||||
totalPackSize += packSize;
|
||||
|
||||
if (!testMode && !outStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
curSize = 0;
|
||||
|
||||
int res = NExtract::NOperationResult::kDataError;
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> inSeqStream;
|
||||
HRESULT hres = GetStream(index, &inSeqStream);
|
||||
if (hres == E_OUTOFMEMORY)
|
||||
return E_OUTOFMEMORY;
|
||||
if (hres == S_FALSE || !inSeqStream)
|
||||
res = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
{
|
||||
RINOK(hres)
|
||||
{
|
||||
hres = copyCoder->Code(inSeqStream, outStream, NULL, NULL, progress);
|
||||
if (hres == S_OK)
|
||||
{
|
||||
if (copyCoderSpec->TotalSize == curSize)
|
||||
res = NExtract::NOperationResult::kOK;
|
||||
}
|
||||
else if (hres == E_NOTIMPL)
|
||||
res = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else if (hres != S_FALSE)
|
||||
return hres;
|
||||
}
|
||||
}
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(res))
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
|
||||
bool be = _h.be;
|
||||
if (IsDir(p, be))
|
||||
return E_FAIL;
|
||||
|
||||
UInt32 size = GetSize(p, be);
|
||||
UInt32 numBlocks = GetNumBlocks(size);
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
{
|
||||
if (offset != 0)
|
||||
return S_FALSE;
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<IInStream> streamTemp = streamSpec;
|
||||
streamSpec->Init(NULL, 0);
|
||||
*stream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (offset + numBlocks * 4 > _size)
|
||||
return S_FALSE;
|
||||
UInt32 prev = offset;
|
||||
for (UInt32 i = 0; i < numBlocks; i++)
|
||||
{
|
||||
UInt32 next = Get32(_data + offset + i * 4);
|
||||
if (next < prev || next > _size)
|
||||
return S_FALSE;
|
||||
prev = next;
|
||||
}
|
||||
|
||||
CCramfsInStream *streamSpec = new CCramfsInStream;
|
||||
CMyComPtr<IInStream> streamTemp = streamSpec;
|
||||
_curNumBlocks = numBlocks;
|
||||
_curBlocksOffset = offset;
|
||||
streamSpec->Handler = this;
|
||||
if (!streamSpec->Alloc(_blockSizeLog, 21 - _blockSizeLog))
|
||||
return E_OUTOFMEMORY;
|
||||
streamSpec->Init(size);
|
||||
*stream = streamTemp.Detach();
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"CramFS", "cramfs", NULL, 0xD3,
|
||||
kSignature,
|
||||
16,
|
||||
0,
|
||||
NULL)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,3 @@
|
||||
// DeflateProps.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,6 @@
|
||||
// DeflateProps.h
|
||||
|
||||
#ifndef ZIP7_INC_DEFLATE_PROPS_H
|
||||
#define ZIP7_INC_DEFLATE_PROPS_H
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
// DLLExports.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#if defined(Z7_LARGE_PAGES)
|
||||
#include "../../../C/Alloc.h"
|
||||
#endif
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
#include "../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../../Windows/NtCheck.h"
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IPassword.h"
|
||||
|
||||
#include "../Common/CreateCoder.h"
|
||||
|
||||
#include "IArchive.h"
|
||||
|
||||
static
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
#define NT_CHECK_FAIL_ACTION return FALSE;
|
||||
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/);
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
g_hInstance = hInstance;
|
||||
NT_CHECK
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Z7_DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
k_7zip_GUID_Data1,
|
||||
k_7zip_GUID_Data2,
|
||||
k_7zip_GUID_Data3_Common,
|
||||
0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
|
||||
|
||||
STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
|
||||
|
||||
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
return CreateArchiver(clsid, iid, outObject);
|
||||
}
|
||||
|
||||
STDAPI SetLargePageMode()
|
||||
{
|
||||
#if defined(Z7_LARGE_PAGES)
|
||||
SetLargePageSize();
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
extern bool g_CaseSensitive;
|
||||
|
||||
STDAPI SetCaseSensitive(Int32 caseSensitive)
|
||||
{
|
||||
g_CaseSensitive = (caseSensitive != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
// OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");
|
||||
if (compressCodecsInfo)
|
||||
{
|
||||
g_ExternalCodecs.GetCodecs = compressCodecsInfo;
|
||||
return g_ExternalCodecs.Load();
|
||||
}
|
||||
g_ExternalCodecs.ClearAndRelease();
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
// DLLExports2.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
#include "../../Common/MyInitGuid.h"
|
||||
|
||||
#if defined(Z7_LARGE_PAGES)
|
||||
#include "../../../C/Alloc.h"
|
||||
#endif
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../../Windows/NtCheck.h"
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IPassword.h"
|
||||
|
||||
#include "../Common/CreateCoder.h"
|
||||
|
||||
#include "IArchive.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
|
||||
#define NT_CHECK_FAIL_ACTION return FALSE;
|
||||
#endif
|
||||
|
||||
static
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(
|
||||
#ifdef UNDER_CE
|
||||
HANDLE
|
||||
#else
|
||||
HINSTANCE
|
||||
#endif
|
||||
hInstance, DWORD dwReason, LPVOID /*lpReserved*/);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(
|
||||
#ifdef UNDER_CE
|
||||
HANDLE
|
||||
#else
|
||||
HINSTANCE
|
||||
#endif
|
||||
hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
// OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH");
|
||||
g_hInstance = (HINSTANCE)hInstance;
|
||||
NT_CHECK
|
||||
}
|
||||
/*
|
||||
if (dwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
OutputDebugStringA("7z.dll DLL_PROCESS_DETACH");
|
||||
}
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#include "../../Common/StringConvert.h"
|
||||
// #include <stdio.h>
|
||||
|
||||
// STDAPI LibStartup();
|
||||
static __attribute__((constructor)) void Init_ForceToUTF8();
|
||||
static __attribute__((constructor)) void Init_ForceToUTF8()
|
||||
{
|
||||
g_ForceToUTF8 = IsNativeUTF8();
|
||||
// printf("\nDLLExports2.cpp::Init_ForceToUTF8 =%d\n", g_ForceToUTF8 ? 1 : 0);
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
Z7_DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
k_7zip_GUID_Data1,
|
||||
k_7zip_GUID_Data2,
|
||||
k_7zip_GUID_Data3_Common,
|
||||
0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
|
||||
|
||||
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
STDAPI CreateHasher(const GUID *clsid, IHasher **hasher);
|
||||
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
|
||||
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
// COM_TRY_BEGIN
|
||||
*outObject = NULL;
|
||||
if (*iid == IID_ICompressCoder ||
|
||||
*iid == IID_ICompressCoder2 ||
|
||||
*iid == IID_ICompressFilter)
|
||||
return CreateCoder(clsid, iid, outObject);
|
||||
if (*iid == IID_IHasher)
|
||||
return CreateHasher(clsid, (IHasher **)outObject);
|
||||
return CreateArchiver(clsid, iid, outObject);
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
STDAPI SetLargePageMode();
|
||||
STDAPI SetLargePageMode()
|
||||
{
|
||||
#if defined(Z7_LARGE_PAGES)
|
||||
#ifdef _WIN32
|
||||
SetLargePageSize();
|
||||
#endif
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
extern bool g_CaseSensitive;
|
||||
|
||||
STDAPI SetCaseSensitive(Int32 caseSensitive);
|
||||
STDAPI SetCaseSensitive(Int32 caseSensitive)
|
||||
{
|
||||
g_CaseSensitive = (caseSensitive != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
UInt32 g_ClientVersion;
|
||||
STDAPI SetClientVersion(UInt32 version);
|
||||
STDAPI SetClientVersion(UInt32 version)
|
||||
{
|
||||
g_ClientVersion = version;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
STDAPI SetProperty(Int32 id, const PROPVARIANT *value);
|
||||
STDAPI SetProperty(Int32 id, const PROPVARIANT *value)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo);
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
// OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");
|
||||
if (compressCodecsInfo)
|
||||
{
|
||||
g_ExternalCodecs.GetCodecs = compressCodecsInfo;
|
||||
return g_ExternalCodecs.Load();
|
||||
}
|
||||
g_ExternalCodecs.ClearAndRelease();
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *);
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,521 @@
|
||||
// FlvHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/InBuffer.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamObjects.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#define GetBe24(p) ( \
|
||||
((UInt32)((const Byte *)(p))[0] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||
((const Byte *)(p))[2] )
|
||||
|
||||
// #define Get16(p) GetBe16(p)
|
||||
#define Get24(p) GetBe24(p)
|
||||
#define Get32(p) GetBe32(p)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NFlv {
|
||||
|
||||
// static const UInt32 kFileSizeMax = (UInt32)1 << 30;
|
||||
static const UInt32 kNumChunksMax = (UInt32)1 << 23;
|
||||
|
||||
static const UInt32 kTagHeaderSize = 11;
|
||||
|
||||
static const Byte kFlag_Video = 1;
|
||||
static const Byte kFlag_Audio = 4;
|
||||
|
||||
static const Byte kType_Audio = 8;
|
||||
static const Byte kType_Video = 9;
|
||||
static const Byte kType_Meta = 18;
|
||||
static const unsigned kNumTypes = 19;
|
||||
|
||||
struct CItem
|
||||
{
|
||||
CByteBuffer Data;
|
||||
Byte Type;
|
||||
};
|
||||
|
||||
struct CItem2
|
||||
{
|
||||
Byte Type;
|
||||
Byte SubType;
|
||||
Byte Props;
|
||||
bool SameSubTypes;
|
||||
unsigned NumChunks;
|
||||
size_t Size;
|
||||
|
||||
CReferenceBuf *BufSpec;
|
||||
CMyComPtr<IUnknown> RefBuf;
|
||||
|
||||
bool IsAudio() const { return Type == kType_Audio; }
|
||||
};
|
||||
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_1(
|
||||
IInArchiveGetStream
|
||||
)
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CObjectVector<CItem2> _items2;
|
||||
CByteBuffer _metadata;
|
||||
bool _isRaw;
|
||||
UInt64 _phySize;
|
||||
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
|
||||
// AString GetComment();
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidSize,
|
||||
kpidNumBlocks,
|
||||
kpidComment
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
static const char * const g_AudioTypes[16] =
|
||||
{
|
||||
"pcm"
|
||||
, "adpcm"
|
||||
, "mp3"
|
||||
, "pcm_le"
|
||||
, "nellymoser16"
|
||||
, "nellymoser8"
|
||||
, "nellymoser"
|
||||
, "g711a"
|
||||
, "g711m"
|
||||
, "audio9"
|
||||
, "aac"
|
||||
, "speex"
|
||||
, "audio12"
|
||||
, "audio13"
|
||||
, "mp3"
|
||||
, "audio15"
|
||||
};
|
||||
|
||||
static const char * const g_VideoTypes[16] =
|
||||
{
|
||||
"video0"
|
||||
, "jpeg"
|
||||
, "h263"
|
||||
, "screen"
|
||||
, "vp6"
|
||||
, "vp6alpha"
|
||||
, "screen2"
|
||||
, "avc"
|
||||
, "video8"
|
||||
, "video9"
|
||||
, "video10"
|
||||
, "video11"
|
||||
, "video12"
|
||||
, "video13"
|
||||
, "video14"
|
||||
, "video15"
|
||||
};
|
||||
|
||||
static const char * const g_Rates[4] =
|
||||
{
|
||||
"5.5 kHz"
|
||||
, "11 kHz"
|
||||
, "22 kHz"
|
||||
, "44 kHz"
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CItem2 &item = _items2[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidExtension:
|
||||
prop = _isRaw ?
|
||||
(item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) :
|
||||
(item.IsAudio() ? "audio.flv" : "video.flv");
|
||||
break;
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
prop = (UInt64)item.Size;
|
||||
break;
|
||||
case kpidNumBlocks: prop = (UInt32)item.NumChunks; break;
|
||||
case kpidComment:
|
||||
{
|
||||
char sz[64];
|
||||
char *s = MyStpCpy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) );
|
||||
if (item.IsAudio())
|
||||
{
|
||||
*s++ = ' ';
|
||||
s = MyStpCpy(s, g_Rates[(item.Props >> 2) & 3]);
|
||||
s = MyStpCpy(s, (item.Props & 2) ? " 16-bit" : " 8-bit");
|
||||
s = MyStpCpy(s, (item.Props & 1) ? " stereo" : " mono");
|
||||
}
|
||||
prop = sz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
AString CHandler::GetComment()
|
||||
{
|
||||
const Byte *p = _metadata;
|
||||
size_t size = _metadata.Size();
|
||||
AString res;
|
||||
if (size > 0)
|
||||
{
|
||||
p++;
|
||||
size--;
|
||||
for (;;)
|
||||
{
|
||||
if (size < 2)
|
||||
break;
|
||||
int len = Get16(p);
|
||||
p += 2;
|
||||
size -= 2;
|
||||
if (len == 0 || (size_t)len > size)
|
||||
break;
|
||||
{
|
||||
AString temp;
|
||||
temp.SetFrom_CalcLen((const char *)p, len);
|
||||
if (!res.IsEmpty())
|
||||
res += '\n';
|
||||
res += temp;
|
||||
}
|
||||
p += len;
|
||||
size -= len;
|
||||
if (size < 1)
|
||||
break;
|
||||
Byte type = *p++;
|
||||
size--;
|
||||
bool ok = false;
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (size < 8)
|
||||
break;
|
||||
ok = true;
|
||||
Byte reverse[8];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
bool little_endian = 1;
|
||||
if (little_endian)
|
||||
reverse[i] = p[7 - i];
|
||||
else
|
||||
reverse[i] = p[i];
|
||||
}
|
||||
double d = *(double *)reverse;
|
||||
char temp[32];
|
||||
sprintf(temp, " = %.3f", d);
|
||||
res += temp;
|
||||
p += 8;
|
||||
size -= 8;
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
if (size < 4)
|
||||
break;
|
||||
ok = true;
|
||||
// UInt32 numItems = Get32(p);
|
||||
p += 4;
|
||||
size -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
*/
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
// COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
// case kpidComment: prop = GetComment(); break;
|
||||
case kpidPhySize: prop = (UInt64)_phySize; break;
|
||||
case kpidIsNotArcType: prop = true; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
const UInt32 kHeaderSize = 13;
|
||||
Byte header[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(stream, header, kHeaderSize))
|
||||
if (header[0] != 'F' ||
|
||||
header[1] != 'L' ||
|
||||
header[2] != 'V' ||
|
||||
header[3] != 1 ||
|
||||
(header[4] & 0xFA) != 0)
|
||||
return S_FALSE;
|
||||
UInt64 offset = Get32(header + 5);
|
||||
if (offset != 9 || Get32(header + 9) != 0)
|
||||
return S_FALSE;
|
||||
offset = kHeaderSize;
|
||||
|
||||
CInBuffer inBuf;
|
||||
if (!inBuf.Create(1 << 15))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuf.SetStream(stream);
|
||||
|
||||
CObjectVector<CItem> items;
|
||||
int lasts[kNumTypes];
|
||||
unsigned i;
|
||||
for (i = 0; i < kNumTypes; i++)
|
||||
lasts[i] = -1;
|
||||
|
||||
_phySize = offset;
|
||||
for (;;)
|
||||
{
|
||||
Byte buf[kTagHeaderSize];
|
||||
CItem item;
|
||||
if (inBuf.ReadBytes(buf, kTagHeaderSize) != kTagHeaderSize)
|
||||
break;
|
||||
item.Type = buf[0];
|
||||
UInt32 size = Get24(buf + 1);
|
||||
if (size < 1)
|
||||
break;
|
||||
// item.Time = Get24(buf + 4);
|
||||
// item.Time |= (UInt32)buf[7] << 24;
|
||||
if (Get24(buf + 8) != 0) // streamID
|
||||
break;
|
||||
|
||||
UInt32 curSize = kTagHeaderSize + size + 4;
|
||||
item.Data.Alloc(curSize);
|
||||
memcpy(item.Data, buf, kTagHeaderSize);
|
||||
if (inBuf.ReadBytes(item.Data + kTagHeaderSize, size) != size)
|
||||
break;
|
||||
if (inBuf.ReadBytes(item.Data + kTagHeaderSize + size, 4) != 4)
|
||||
break;
|
||||
|
||||
if (Get32(item.Data + kTagHeaderSize + size) != kTagHeaderSize + size)
|
||||
break;
|
||||
|
||||
offset += curSize;
|
||||
|
||||
// printf("\noffset = %6X type = %2d time = %6d size = %6d", (UInt32)offset, item.Type, item.Time, item.Size);
|
||||
|
||||
if (item.Type == kType_Meta)
|
||||
{
|
||||
// _metadata = item.Buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.Type != kType_Audio && item.Type != kType_Video)
|
||||
break;
|
||||
if (items.Size() >= kNumChunksMax)
|
||||
return S_FALSE;
|
||||
Byte firstByte = item.Data[kTagHeaderSize];
|
||||
Byte subType, props;
|
||||
if (item.Type == kType_Audio)
|
||||
{
|
||||
subType = (Byte)(firstByte >> 4);
|
||||
props = (Byte)(firstByte & 0xF);
|
||||
}
|
||||
else
|
||||
{
|
||||
subType = (Byte)(firstByte & 0xF);
|
||||
props = (Byte)(firstByte >> 4);
|
||||
}
|
||||
int last = lasts[item.Type];
|
||||
if (last < 0)
|
||||
{
|
||||
CItem2 item2;
|
||||
item2.RefBuf = item2.BufSpec = new CReferenceBuf;
|
||||
item2.Size = curSize;
|
||||
item2.Type = item.Type;
|
||||
item2.SubType = subType;
|
||||
item2.Props = props;
|
||||
item2.NumChunks = 1;
|
||||
item2.SameSubTypes = true;
|
||||
lasts[item.Type] = (int)_items2.Add(item2);
|
||||
}
|
||||
else
|
||||
{
|
||||
CItem2 &item2 = _items2[last];
|
||||
if (subType != item2.SubType)
|
||||
item2.SameSubTypes = false;
|
||||
item2.Size += curSize;
|
||||
item2.NumChunks++;
|
||||
}
|
||||
items.Add(item);
|
||||
}
|
||||
_phySize = offset;
|
||||
if (callback && (items.Size() & 0xFF) == 0)
|
||||
{
|
||||
RINOK(callback->SetCompleted(NULL, &offset))
|
||||
}
|
||||
}
|
||||
if (items.IsEmpty())
|
||||
return S_FALSE;
|
||||
|
||||
_isRaw = (_items2.Size() == 1);
|
||||
for (i = 0; i < _items2.Size(); i++)
|
||||
{
|
||||
CItem2 &item2 = _items2[i];
|
||||
CByteBuffer &itemBuf = item2.BufSpec->Buf;
|
||||
if (_isRaw)
|
||||
{
|
||||
if (!item2.SameSubTypes)
|
||||
return S_FALSE;
|
||||
itemBuf.Alloc((size_t)item2.Size - (size_t)(kTagHeaderSize + 4 + 1) * item2.NumChunks);
|
||||
item2.Size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemBuf.Alloc(kHeaderSize + (size_t)item2.Size);
|
||||
memcpy(itemBuf, header, kHeaderSize);
|
||||
itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video;
|
||||
item2.Size = kHeaderSize;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < items.Size(); i++)
|
||||
{
|
||||
const CItem &item = items[i];
|
||||
CItem2 &item2 = _items2[lasts[item.Type]];
|
||||
size_t size = item.Data.Size();
|
||||
const Byte *src = item.Data;
|
||||
if (_isRaw)
|
||||
{
|
||||
src += kTagHeaderSize + 1;
|
||||
size -= (kTagHeaderSize + 4 + 1);
|
||||
}
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(item2.BufSpec->Buf + item2.Size, src, size);
|
||||
item2.Size += size;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
HRESULT res;
|
||||
try
|
||||
{
|
||||
res = Open2(inStream, callback);
|
||||
if (res == S_OK)
|
||||
_stream = inStream;
|
||||
}
|
||||
catch(...) { res = S_FALSE; }
|
||||
if (res != S_OK)
|
||||
{
|
||||
Close();
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_phySize = 0;
|
||||
_stream.Release();
|
||||
_items2.Clear();
|
||||
// _metadata.SetCapacity(0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = _items2.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items2.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
totalSize += _items2[allFilesMode ? i : indices[i]].Size;
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
totalSize = 0;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
lps->InSize = lps->OutSize = totalSize;
|
||||
RINOK(lps->SetCur())
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
const CItem2 &item = _items2[index];
|
||||
RINOK(extractCallback->GetStream(index, &outStream, askMode))
|
||||
totalSize += item.Size;
|
||||
if (!testMode && !outStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
if (outStream)
|
||||
{
|
||||
RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.Size()))
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*stream = NULL;
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
|
||||
streamSpec->Init(_items2[index].BufSpec);
|
||||
*stream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = { 'F', 'L', 'V', 1, };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"FLV", "flv", NULL, 0xD6,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
NULL)
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,473 @@
|
||||
// GptHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Windows/PropVariantUtils.h"
|
||||
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "HandlerCont.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
#define Get64(p) GetUi64(p)
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
namespace NMbr {
|
||||
const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);
|
||||
}
|
||||
|
||||
namespace NFat {
|
||||
API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);
|
||||
}
|
||||
|
||||
namespace NGpt {
|
||||
|
||||
static const unsigned k_SignatureSize = 12;
|
||||
static const Byte k_Signature[k_SignatureSize] =
|
||||
{ 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };
|
||||
|
||||
static const CUInt32PCharPair g_PartitionFlags[] =
|
||||
{
|
||||
{ 0, "Sys" },
|
||||
{ 1, "Ignore" },
|
||||
{ 2, "Legacy" },
|
||||
{ 60, "Win-Read-only" },
|
||||
{ 62, "Win-Hidden" },
|
||||
{ 63, "Win-Not-Automount" }
|
||||
};
|
||||
|
||||
static const unsigned kNameLen = 36;
|
||||
|
||||
struct CPartition
|
||||
{
|
||||
Byte Type[16];
|
||||
Byte Id[16];
|
||||
UInt64 FirstLba;
|
||||
UInt64 LastLba;
|
||||
UInt64 Flags;
|
||||
const char *Ext; // detected later
|
||||
Byte Name[kNameLen * 2];
|
||||
|
||||
bool IsUnused() const
|
||||
{
|
||||
for (unsigned i = 0; i < 16; i++)
|
||||
if (Type[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt64 GetSize(unsigned sectorSizeLog) const { return (LastLba - FirstLba + 1) << sectorSizeLog; }
|
||||
UInt64 GetPos(unsigned sectorSizeLog) const { return FirstLba << sectorSizeLog; }
|
||||
UInt64 GetEnd(unsigned sectorSizeLog) const { return (LastLba + 1) << sectorSizeLog; }
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
memcpy(Type, p, 16);
|
||||
memcpy(Id, p + 16, 16);
|
||||
FirstLba = Get64(p + 32);
|
||||
LastLba = Get64(p + 40);
|
||||
Flags = Get64(p + 48);
|
||||
memcpy(Name, p + 56, kNameLen * 2);
|
||||
Ext = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CPartType
|
||||
{
|
||||
UInt32 Id;
|
||||
const char *Ext;
|
||||
const char *Type;
|
||||
};
|
||||
|
||||
static const CPartType kPartTypes[] =
|
||||
{
|
||||
// { 0x0, NULL, "Unused" },
|
||||
|
||||
{ 0x21686148, NULL, "BIOS Boot" },
|
||||
|
||||
{ 0xC12A7328, NULL, "EFI System" },
|
||||
{ 0x024DEE41, NULL, "MBR" },
|
||||
|
||||
{ 0xE3C9E316, NULL, "Windows MSR" },
|
||||
{ 0xEBD0A0A2, NULL, "Windows BDP" },
|
||||
{ 0x5808C8AA, NULL, "Windows LDM Metadata" },
|
||||
{ 0xAF9B60A0, NULL, "Windows LDM Data" },
|
||||
{ 0xDE94BBA4, NULL, "Windows Recovery" },
|
||||
// { 0x37AFFC90, NULL, "IBM GPFS" },
|
||||
// { 0xE75CAF8F, NULL, "Windows Storage Spaces" },
|
||||
|
||||
{ 0x0FC63DAF, NULL, "Linux Data" },
|
||||
{ 0x0657FD6D, NULL, "Linux Swap" },
|
||||
{ 0x44479540, NULL, "Linux root (x86)" },
|
||||
{ 0x4F68BCE3, NULL, "Linux root (x86-64)" },
|
||||
{ 0x69DAD710, NULL, "Linux root (ARM)" },
|
||||
{ 0xB921B045, NULL, "Linux root (ARM64)" },
|
||||
{ 0x993D8D3D, NULL, "Linux root (IA-64)" },
|
||||
|
||||
|
||||
{ 0x83BD6B9D, NULL, "FreeBSD Boot" },
|
||||
{ 0x516E7CB4, NULL, "FreeBSD Data" },
|
||||
{ 0x516E7CB5, NULL, "FreeBSD Swap" },
|
||||
{ 0x516E7CB6, "ufs", "FreeBSD UFS" },
|
||||
{ 0x516E7CB8, NULL, "FreeBSD Vinum" },
|
||||
{ 0x516E7CB8, "zfs", "FreeBSD ZFS" },
|
||||
|
||||
{ 0x48465300, "hfsx", "HFS+" },
|
||||
{ 0x7C3457EF, "apfs", "APFS" },
|
||||
};
|
||||
|
||||
static int FindPartType(const Byte *guid)
|
||||
{
|
||||
const UInt32 val = Get32(guid);
|
||||
for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPartTypes); i++)
|
||||
if (kPartTypes[i].Id == val)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void RawLeGuidToString_Upper(const Byte *g, char *s)
|
||||
{
|
||||
RawLeGuidToString(g, s);
|
||||
// MyStringUpper_Ascii(s);
|
||||
}
|
||||
|
||||
|
||||
Z7_class_CHandler_final: public CHandlerCont
|
||||
{
|
||||
Z7_IFACE_COM7_IMP(IInArchive_Cont)
|
||||
|
||||
CRecordVector<CPartition> _items;
|
||||
UInt64 _totalSize;
|
||||
unsigned _sectorSizeLog;
|
||||
Byte Guid[16];
|
||||
|
||||
CByteBuffer _buffer;
|
||||
|
||||
HRESULT Open2(IInStream *stream);
|
||||
|
||||
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
|
||||
{
|
||||
const CPartition &item = _items[index];
|
||||
pos = item.GetPos(_sectorSizeLog);
|
||||
size = item.GetSize(_sectorSizeLog);
|
||||
return NExtract::NOperationResult::kOK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream)
|
||||
{
|
||||
const unsigned kBufSize = 2 << 12;
|
||||
_buffer.Alloc(kBufSize);
|
||||
RINOK(ReadStream_FALSE(stream, _buffer, kBufSize))
|
||||
const Byte *buf = _buffer;
|
||||
if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
|
||||
return S_FALSE;
|
||||
{
|
||||
for (unsigned sectorSizeLog = 9;; sectorSizeLog += 3)
|
||||
{
|
||||
if (sectorSizeLog > 12)
|
||||
return S_FALSE;
|
||||
if (memcmp(buf + ((size_t)1 << sectorSizeLog), k_Signature, k_SignatureSize) == 0)
|
||||
{
|
||||
buf += ((size_t)1 << sectorSizeLog);
|
||||
_sectorSizeLog = sectorSizeLog;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const UInt32 kSectorSize = 1u << _sectorSizeLog;
|
||||
{
|
||||
// if (Get32(buf + 8) != 0x10000) return S_FALSE; // revision
|
||||
const UInt32 headerSize = Get32(buf + 12); // = 0x5C usually
|
||||
if (headerSize > kSectorSize)
|
||||
return S_FALSE;
|
||||
const UInt32 crc = Get32(buf + 0x10);
|
||||
SetUi32(_buffer + kSectorSize + 0x10, 0)
|
||||
if (CrcCalc(_buffer + kSectorSize, headerSize) != crc)
|
||||
return S_FALSE;
|
||||
}
|
||||
// UInt32 reserved = Get32(buf + 0x14);
|
||||
const UInt64 curLba = Get64(buf + 0x18);
|
||||
if (curLba != 1)
|
||||
return S_FALSE;
|
||||
const UInt64 backupLba = Get64(buf + 0x20);
|
||||
// UInt64 firstUsableLba = Get64(buf + 0x28);
|
||||
// UInt64 lastUsableLba = Get64(buf + 0x30);
|
||||
memcpy(Guid, buf + 0x38, 16);
|
||||
const UInt64 tableLba = Get64(buf + 0x48);
|
||||
if (tableLba < 2 || (tableLba >> (63 - _sectorSizeLog)) != 0)
|
||||
return S_FALSE;
|
||||
const UInt32 numEntries = Get32(buf + 0x50);
|
||||
if (numEntries > (1 << 16))
|
||||
return S_FALSE;
|
||||
const UInt32 entrySize = Get32(buf + 0x54); // = 128 usually
|
||||
if (entrySize < 128 || entrySize > (1 << 12))
|
||||
return S_FALSE;
|
||||
const UInt32 entriesCrc = Get32(buf + 0x58);
|
||||
|
||||
const UInt32 tableSize = entrySize * numEntries;
|
||||
const UInt32 tableSizeAligned = (tableSize + kSectorSize - 1) & ~(kSectorSize - 1);
|
||||
_buffer.Alloc(tableSizeAligned);
|
||||
const UInt64 tableOffset = tableLba * kSectorSize;
|
||||
RINOK(InStream_SeekSet(stream, tableOffset))
|
||||
RINOK(ReadStream_FALSE(stream, _buffer, tableSizeAligned))
|
||||
|
||||
if (CrcCalc(_buffer, tableSize) != entriesCrc)
|
||||
return S_FALSE;
|
||||
|
||||
_totalSize = tableOffset + tableSizeAligned;
|
||||
|
||||
for (UInt32 i = 0; i < numEntries; i++)
|
||||
{
|
||||
CPartition item;
|
||||
item.Parse(_buffer + i * entrySize);
|
||||
if (item.IsUnused())
|
||||
continue;
|
||||
if (item.LastLba < item.FirstLba)
|
||||
return S_FALSE;
|
||||
if ((item.LastLba >> (63 - _sectorSizeLog)) != 0)
|
||||
return S_FALSE;
|
||||
const UInt64 endPos = item.GetEnd(_sectorSizeLog);
|
||||
if (_totalSize < endPos)
|
||||
_totalSize = endPos;
|
||||
_items.Add(item);
|
||||
}
|
||||
|
||||
_buffer.Free();
|
||||
{
|
||||
if ((backupLba >> (63 - _sectorSizeLog)) != 0)
|
||||
return S_FALSE;
|
||||
const UInt64 end = (backupLba + 1) * kSectorSize;
|
||||
if (_totalSize < end)
|
||||
_totalSize = end;
|
||||
}
|
||||
{
|
||||
UInt64 fileEnd;
|
||||
RINOK(InStream_GetSize_SeekToEnd(stream, fileEnd))
|
||||
|
||||
if (_totalSize < fileEnd)
|
||||
{
|
||||
const UInt64 rem = fileEnd - _totalSize;
|
||||
const UInt64 kRemMax = 1 << 22;
|
||||
if (rem <= kRemMax)
|
||||
{
|
||||
RINOK(InStream_SeekSet(stream, _totalSize))
|
||||
bool areThereNonZeros = false;
|
||||
UInt64 numZeros = 0;
|
||||
if (ReadZeroTail(stream, areThereNonZeros, numZeros, kRemMax) == S_OK)
|
||||
if (!areThereNonZeros)
|
||||
_totalSize += numZeros;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
RINOK(Open2(stream))
|
||||
_stream = stream;
|
||||
|
||||
FOR_VECTOR (fileIndex, _items)
|
||||
{
|
||||
CPartition &item = _items[fileIndex];
|
||||
const int typeIndex = FindPartType(item.Type);
|
||||
if (typeIndex < 0)
|
||||
continue;
|
||||
const CPartType &t = kPartTypes[(unsigned)typeIndex];
|
||||
if (t.Ext)
|
||||
{
|
||||
item.Ext = t.Ext;
|
||||
continue;
|
||||
}
|
||||
if (t.Type && IsString1PrefixedByString2_NoCase_Ascii(t.Type, "Windows"))
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
if (
|
||||
// ((IInArchiveGetStream *)this)->
|
||||
GetStream(fileIndex, &inStream) == S_OK && inStream)
|
||||
{
|
||||
const char *fs = NMbr::GetFileSystem(inStream, item.GetSize(_sectorSizeLog));
|
||||
if (fs)
|
||||
item.Ext = fs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::Close())
|
||||
{
|
||||
_sectorSizeLog = 0;
|
||||
_totalSize = 0;
|
||||
memset(Guid, 0, sizeof(Guid));
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidFileSystem,
|
||||
kpidCharacts,
|
||||
kpidOffset,
|
||||
kpidId
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidSectorSize,
|
||||
kpidId
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidMainSubfile:
|
||||
{
|
||||
if (_items.Size() == 1)
|
||||
prop = (UInt32)0;
|
||||
break;
|
||||
}
|
||||
case kpidPhySize: prop = _totalSize; break;
|
||||
case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;
|
||||
case kpidId:
|
||||
{
|
||||
char s[48];
|
||||
RawLeGuidToString_Upper(Guid, s);
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
const CPartition &item = _items[index];
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
// Windows BDP partitions can have identical names.
|
||||
// So we add the partition number at front
|
||||
UString s;
|
||||
s.Add_UInt32(index);
|
||||
{
|
||||
UString s2;
|
||||
for (unsigned i = 0; i < kNameLen; i++)
|
||||
{
|
||||
wchar_t c = (wchar_t)Get16(item.Name + i * 2);
|
||||
if (c == 0)
|
||||
break;
|
||||
s2 += c;
|
||||
}
|
||||
if (!s2.IsEmpty())
|
||||
{
|
||||
s.Add_Dot();
|
||||
s += s2;
|
||||
}
|
||||
}
|
||||
{
|
||||
s.Add_Dot();
|
||||
if (item.Ext)
|
||||
{
|
||||
AString fs (item.Ext);
|
||||
fs.MakeLower_Ascii();
|
||||
s += fs;
|
||||
}
|
||||
else
|
||||
s += "img";
|
||||
}
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidSize:
|
||||
case kpidPackSize: prop = item.GetSize(_sectorSizeLog); break;
|
||||
case kpidOffset: prop = item.GetPos(_sectorSizeLog); break;
|
||||
|
||||
case kpidFileSystem:
|
||||
{
|
||||
char s[48];
|
||||
const char *res;
|
||||
const int typeIndex = FindPartType(item.Type);
|
||||
if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Type)
|
||||
res = kPartTypes[(unsigned)typeIndex].Type;
|
||||
else
|
||||
{
|
||||
RawLeGuidToString_Upper(item.Type, s);
|
||||
res = s;
|
||||
}
|
||||
prop = res;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidId:
|
||||
{
|
||||
char s[48];
|
||||
RawLeGuidToString_Upper(item.Id, s);
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidCharacts: FLAGS64_TO_PROP(g_PartitionFlags, item.Flags, prop); break;
|
||||
}
|
||||
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
// we suppport signature only for 512-bytes sector.
|
||||
REGISTER_ARC_I(
|
||||
"GPT", "gpt mbr", NULL, 0xCB,
|
||||
k_Signature,
|
||||
1 << 9,
|
||||
0,
|
||||
NULL)
|
||||
|
||||
}}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,321 @@
|
||||
// HandlerCont.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
#include "HandlerCont.h"
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
namespace NExt {
|
||||
API_FUNC_IsArc IsArc_Ext(const Byte *p, size_t size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
{
|
||||
RINOK(GetNumberOfItems(&numItems))
|
||||
}
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
UInt64 pos, size;
|
||||
GetItem_ExtractInfo(allFilesMode ? i : indices[i], pos, size);
|
||||
totalSize += size;
|
||||
}
|
||||
RINOK(extractCallback->SetTotal(totalSize))
|
||||
|
||||
totalSize = 0;
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||
lps->Init(extractCallback, false);
|
||||
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;
|
||||
streamSpec->SetStream(_stream);
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
|
||||
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
lps->InSize = totalSize;
|
||||
lps->OutSize = totalSize;
|
||||
RINOK(lps->SetCur())
|
||||
if (i >= numItems)
|
||||
break;
|
||||
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
|
||||
RINOK(extractCallback->GetStream(index, &outStream, askMode))
|
||||
|
||||
UInt64 pos, size;
|
||||
int opRes = GetItem_ExtractInfo(index, pos, size);
|
||||
totalSize += size;
|
||||
if (!testMode && !outStream)
|
||||
continue;
|
||||
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
|
||||
if (opRes == NExtract::NOperationResult::kOK)
|
||||
{
|
||||
RINOK(InStream_SeekSet(_stream, pos))
|
||||
streamSpec->Init(size);
|
||||
|
||||
RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, lps))
|
||||
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
if (copyCoder->TotalSize == size)
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
else if (copyCoder->TotalSize < size)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
}
|
||||
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(opRes))
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandlerCont::GetStream(UInt32 index, ISequentialInStream **stream))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*stream = NULL;
|
||||
UInt64 pos, size;
|
||||
if (GetItem_ExtractInfo(index, pos, size) != NExtract::NOperationResult::kOK)
|
||||
return S_FALSE;
|
||||
return CreateLimitedInStream(_stream, pos, size, stream);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
|
||||
CHandlerImg::CHandlerImg()
|
||||
{
|
||||
Clear_HandlerImg_Vars();
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandlerImg::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
{
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
}
|
||||
_virtPos = (UInt64)offset;
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const Byte k_GDP_Signature[] =
|
||||
{ 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };
|
||||
// static const Byte k_Ext_Signature[] = { 0x53, 0xEF };
|
||||
// static const unsigned k_Ext_Signature_offset = 0x438;
|
||||
|
||||
static const char *GetImgExt(ISequentialInStream *stream)
|
||||
{
|
||||
// const size_t kHeaderSize_for_Ext = (1 << 11); // for ext
|
||||
const size_t kHeaderSize = 2 << 12; // for 4 KB sector GPT
|
||||
Byte buf[kHeaderSize];
|
||||
size_t processed = kHeaderSize;
|
||||
if (ReadStream(stream, buf, &processed) == S_OK)
|
||||
{
|
||||
if (processed >= kHeaderSize)
|
||||
if (buf[0x1FE] == 0x55 && buf[0x1FF] == 0xAA)
|
||||
{
|
||||
for (unsigned k = (1 << 9); k <= (1u << 12); k <<= 3)
|
||||
if (memcmp(buf + k, k_GDP_Signature, sizeof(k_GDP_Signature)) == 0)
|
||||
return "gpt";
|
||||
return "mbr";
|
||||
}
|
||||
if (NExt::IsArc_Ext(buf, processed) == k_IsArc_Res_YES)
|
||||
return "ext";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CHandlerImg::CloseAtError()
|
||||
{
|
||||
Stream.Release();
|
||||
}
|
||||
|
||||
void CHandlerImg::Clear_HandlerImg_Vars()
|
||||
{
|
||||
_imgExt = NULL;
|
||||
_size = 0;
|
||||
ClearStreamVars();
|
||||
Reset_VirtPos();
|
||||
Reset_PosInArc();
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandlerImg::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * openCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
Close();
|
||||
HRESULT res;
|
||||
try
|
||||
{
|
||||
res = Open2(stream, openCallback);
|
||||
if (res == S_OK)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
const HRESULT res2 = GetStream(0, &inStream);
|
||||
if (res2 == S_OK && inStream)
|
||||
_imgExt = GetImgExt(inStream);
|
||||
// _imgExt = GetImgExt(this); // for debug
|
||||
/* we reset (_virtPos) to support cases, if some code will
|
||||
call Read() from Handler object instead of GetStream() object. */
|
||||
Reset_VirtPos();
|
||||
// optional: we reset (_posInArc). if real seek position of stream will be changed in external code
|
||||
Reset_PosInArc();
|
||||
// optional: here we could also reset seek positions in parent streams..
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
CloseAtError();
|
||||
throw;
|
||||
}
|
||||
CloseAtError();
|
||||
return res;
|
||||
}
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CHandlerImg::GetNumberOfItems(UInt32 *numItems))
|
||||
{
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
CHandlerImgProgress
|
||||
, ICompressProgressInfo
|
||||
)
|
||||
public:
|
||||
CHandlerImg &Handler;
|
||||
CMyComPtr<ICompressProgressInfo> _ratioProgress;
|
||||
|
||||
CHandlerImgProgress(CHandlerImg &handler) : Handler(handler) {}
|
||||
};
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandlerImgProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
|
||||
{
|
||||
UInt64 inSize2;
|
||||
if (Handler.Get_PackSizeProcessed(inSize2))
|
||||
inSize = &inSize2;
|
||||
return _ratioProgress->SetRatioInfo(inSize, outSize);
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
RINOK(extractCallback->SetTotal(_size))
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
const Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
RINOK(extractCallback->GetStream(0, &outStream, askMode))
|
||||
if (!testMode && !outStream)
|
||||
return S_OK;
|
||||
RINOK(extractCallback->PrepareOperation(askMode))
|
||||
|
||||
int opRes = NExtract::NOperationResult::kDataError;
|
||||
|
||||
ClearStreamVars();
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
HRESULT hres = GetStream(0, &inStream);
|
||||
if (hres == S_FALSE)
|
||||
hres = E_NOTIMPL;
|
||||
|
||||
if (hres == S_OK && inStream)
|
||||
{
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
if (Init_PackSizeProcessed())
|
||||
{
|
||||
CHandlerImgProgress *imgProgressSpec = new CHandlerImgProgress(*this);
|
||||
CMyComPtr<ICompressProgressInfo> imgProgress = imgProgressSpec;
|
||||
imgProgressSpec->_ratioProgress = progress;
|
||||
progress.Release();
|
||||
progress = imgProgress;
|
||||
}
|
||||
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
|
||||
|
||||
hres = copyCoder.Interface()->Code(inStream, outStream, NULL, &_size, progress);
|
||||
if (hres == S_OK)
|
||||
{
|
||||
if (copyCoder->TotalSize == _size)
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
|
||||
if (_stream_unavailData)
|
||||
opRes = NExtract::NOperationResult::kUnavailable;
|
||||
else if (_stream_unsupportedMethod)
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else if (_stream_dataError)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (copyCoder->TotalSize < _size)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
}
|
||||
}
|
||||
|
||||
inStream.Release();
|
||||
outStream.Release();
|
||||
|
||||
if (hres != S_OK)
|
||||
{
|
||||
if (hres == S_FALSE)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (hres == E_NOTIMPL)
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
return hres;
|
||||
}
|
||||
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// HandlerCont.h
|
||||
|
||||
#ifndef ZIP7_INC_HANDLER_CONT_H
|
||||
#define ZIP7_INC_HANDLER_CONT_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "IArchive.h"
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
#define Z7_IFACEM_IInArchive_Cont(x) \
|
||||
x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) \
|
||||
x(Close()) \
|
||||
x(GetNumberOfItems(UInt32 *numItems)) \
|
||||
x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
|
||||
/* x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) */ \
|
||||
x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \
|
||||
x(GetNumberOfProperties(UInt32 *numProps)) \
|
||||
x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
|
||||
x(GetNumberOfArchiveProperties(UInt32 *numProps)) \
|
||||
x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
|
||||
|
||||
|
||||
// #define Z7_COM7F_PUREO(f) virtual Z7_COM7F_IMF(f) Z7_override =0;
|
||||
// #define Z7_COM7F_PUREO2(t, f) virtual Z7_COM7F_IMF2(t, f) Z7_override =0;
|
||||
|
||||
class CHandlerCont:
|
||||
public IInArchive,
|
||||
public IInArchiveGetStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_UNKNOWN_IMP_2(
|
||||
IInArchive,
|
||||
IInArchiveGetStream)
|
||||
/*
|
||||
Z7_IFACEM_IInArchive_Cont(Z7_COM7F_PUREO)
|
||||
// Z7_IFACE_COM7_PURE(IInArchive_Cont)
|
||||
*/
|
||||
Z7_COM7F_IMP(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
protected:
|
||||
Z7_IFACE_COM7_IMP(IInArchiveGetStream)
|
||||
|
||||
CMyComPtr<IInStream> _stream;
|
||||
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const = 0;
|
||||
// destructor must be virtual for this class
|
||||
virtual ~CHandlerCont() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define Z7_IFACEM_IInArchive_Img(x) \
|
||||
/* x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) */ \
|
||||
x(Close()) \
|
||||
/* x(GetNumberOfItems(UInt32 *numItems)) */ \
|
||||
x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
|
||||
/* x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) */ \
|
||||
x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \
|
||||
x(GetNumberOfProperties(UInt32 *numProps)) \
|
||||
x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
|
||||
x(GetNumberOfArchiveProperties(UInt32 *numProps)) \
|
||||
x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
|
||||
|
||||
|
||||
class CHandlerImg:
|
||||
public IInArchive,
|
||||
public IInArchiveGetStream,
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_UNKNOWN_IMP_4(
|
||||
IInArchive,
|
||||
IInArchiveGetStream,
|
||||
ISequentialInStream,
|
||||
IInStream)
|
||||
|
||||
Z7_COM7F_IMP(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback))
|
||||
Z7_COM7F_IMP(GetNumberOfItems(UInt32 *numItems))
|
||||
Z7_COM7F_IMP(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback))
|
||||
Z7_IFACE_COM7_IMP(IInStream)
|
||||
// Z7_IFACEM_IInArchive_Img(Z7_COM7F_PUREO)
|
||||
|
||||
protected:
|
||||
bool _stream_unavailData;
|
||||
bool _stream_unsupportedMethod;
|
||||
bool _stream_dataError;
|
||||
// bool _stream_UsePackSize;
|
||||
// UInt64 _stream_PackSize;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _posInArc;
|
||||
UInt64 _size;
|
||||
CMyComPtr<IInStream> Stream;
|
||||
const char *_imgExt;
|
||||
|
||||
void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; }
|
||||
void Reset_VirtPos() { _virtPos = (UInt64)0; }
|
||||
|
||||
void ClearStreamVars()
|
||||
{
|
||||
_stream_unavailData = false;
|
||||
_stream_unsupportedMethod = false;
|
||||
_stream_dataError = false;
|
||||
// _stream_UsePackSize = false;
|
||||
// _stream_PackSize = 0;
|
||||
}
|
||||
|
||||
void Clear_HandlerImg_Vars(); // it doesn't Release (Stream) var.
|
||||
|
||||
virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0;
|
||||
virtual void CloseAtError();
|
||||
|
||||
// returns (true), if Get_PackSizeProcessed() is required in Extract()
|
||||
virtual bool Init_PackSizeProcessed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
virtual bool Get_PackSizeProcessed(UInt64 &size)
|
||||
{
|
||||
size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
CHandlerImg();
|
||||
// destructor must be virtual for this class
|
||||
virtual ~CHandlerImg() {}
|
||||
};
|
||||
|
||||
|
||||
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
// HfsHandler.h
|
||||
|
||||
#ifndef ZIP7_INC_HFS_HANDLER_H
|
||||
#define ZIP7_INC_HFS_HANDLER_H
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Compress/LzfseDecoder.h"
|
||||
#include "../Compress/ZlibDecoder.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NHfs {
|
||||
|
||||
static const UInt32 k_decmpfs_HeaderSize = 16;
|
||||
|
||||
struct CCompressHeader
|
||||
{
|
||||
UInt64 UnpackSize;
|
||||
UInt32 Method;
|
||||
Byte DataPos;
|
||||
bool IsCorrect;
|
||||
bool IsSupported;
|
||||
bool IsResource;
|
||||
|
||||
bool IsMethod_Compressed_Inline() const { return DataPos == k_decmpfs_HeaderSize; }
|
||||
bool IsMethod_Uncompressed_Inline() const { return DataPos == k_decmpfs_HeaderSize + 1; }
|
||||
bool IsMethod_Resource() const { return IsResource; }
|
||||
|
||||
void Parse(const Byte *p, size_t size);
|
||||
|
||||
void Clear()
|
||||
{
|
||||
UnpackSize = 0;
|
||||
Method = 0;
|
||||
DataPos = 0;
|
||||
IsCorrect = false;
|
||||
IsSupported = false;
|
||||
IsResource = false;
|
||||
}
|
||||
|
||||
CCompressHeader() { Clear(); }
|
||||
|
||||
void MethodToProp(NWindows::NCOM::CPropVariant &prop) const;
|
||||
};
|
||||
|
||||
void MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop);
|
||||
|
||||
|
||||
class CDecoder
|
||||
{
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> _zlibDecoder;
|
||||
CMyComPtr2_Create<ICompressCoder, NCompress::NLzfse::CDecoder> _lzfseDecoder;
|
||||
|
||||
CByteBuffer _tableBuf;
|
||||
CByteBuffer _buf;
|
||||
|
||||
HRESULT ExtractResourceFork_ZLIB(
|
||||
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
|
||||
UInt64 forkSize, UInt64 unpackSize,
|
||||
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
|
||||
|
||||
HRESULT ExtractResourceFork_LZFSE(
|
||||
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
|
||||
UInt64 forkSize, UInt64 unpackSize,
|
||||
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
|
||||
|
||||
HRESULT ExtractResourceFork_ZBM(
|
||||
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
|
||||
UInt64 forkSize, UInt64 unpackSize,
|
||||
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
|
||||
|
||||
public:
|
||||
|
||||
HRESULT Extract(
|
||||
ISequentialInStream *inStreamFork, ISequentialOutStream *realOutStream,
|
||||
UInt64 forkSize,
|
||||
const CCompressHeader &compressHeader,
|
||||
const CByteBuffer *data,
|
||||
UInt64 progressStart, IArchiveExtractCallback *extractCallback,
|
||||
int &opRes);
|
||||
|
||||
CDecoder(bool IsAdlerOptional);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user