mirror of
https://github.com/hashcat/hashcat
synced 2024-12-23 14:13:43 +01:00
Added UnRAR dependency (version 5.9.4)
This commit is contained in:
parent
57bef8abc9
commit
616cb9859f
279
deps/unrar/UnRAR.vcxproj
vendored
Normal file
279
deps/unrar/UnRAR.vcxproj
vendored
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{95CC809B-03FC-4EDB-BB20-FD07A698C05F}</ProjectGuid>
|
||||||
|
<RootNamespace>UnRAR</RootNamespace>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<OutDir>build\unrar32\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<OutDir>build\unrar64\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<OutDir>build\unrar32\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<OutDir>build\unrar64\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>StdCall</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>StdCall</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||||
|
<FloatingPointModel>Precise</FloatingPointModel>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>StdCall</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<LinkTimeCodeGeneration />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>MinSpace</Optimization>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>false</StringPooling>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>StdCall</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<LinkTimeCodeGeneration />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="archive.cpp" />
|
||||||
|
<ClCompile Include="arcread.cpp" />
|
||||||
|
<ClCompile Include="blake2s.cpp" />
|
||||||
|
<ClCompile Include="cmddata.cpp" />
|
||||||
|
<ClCompile Include="consio.cpp" />
|
||||||
|
<ClCompile Include="crc.cpp" />
|
||||||
|
<ClCompile Include="crypt.cpp" />
|
||||||
|
<ClCompile Include="encname.cpp" />
|
||||||
|
<ClCompile Include="errhnd.cpp" />
|
||||||
|
<ClCompile Include="extinfo.cpp" />
|
||||||
|
<ClCompile Include="extract.cpp" />
|
||||||
|
<ClCompile Include="filcreat.cpp" />
|
||||||
|
<ClCompile Include="file.cpp" />
|
||||||
|
<ClCompile Include="filefn.cpp" />
|
||||||
|
<ClCompile Include="filestr.cpp" />
|
||||||
|
<ClCompile Include="find.cpp" />
|
||||||
|
<ClCompile Include="getbits.cpp" />
|
||||||
|
<ClCompile Include="global.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="hash.cpp" />
|
||||||
|
<ClCompile Include="headers.cpp" />
|
||||||
|
<ClCompile Include="isnt.cpp" />
|
||||||
|
<ClCompile Include="list.cpp" />
|
||||||
|
<ClCompile Include="match.cpp" />
|
||||||
|
<ClCompile Include="options.cpp" />
|
||||||
|
<ClCompile Include="pathfn.cpp" />
|
||||||
|
<ClCompile Include="qopen.cpp" />
|
||||||
|
<ClCompile Include="rar.cpp" />
|
||||||
|
<ClCompile Include="rarpch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="rarvm.cpp" />
|
||||||
|
<ClCompile Include="rawread.cpp" />
|
||||||
|
<ClCompile Include="rdwrfn.cpp" />
|
||||||
|
<ClCompile Include="recvol.cpp" />
|
||||||
|
<ClCompile Include="resource.cpp" />
|
||||||
|
<ClCompile Include="rijndael.cpp" />
|
||||||
|
<ClCompile Include="rs.cpp" />
|
||||||
|
<ClCompile Include="rs16.cpp" />
|
||||||
|
<ClCompile Include="scantree.cpp" />
|
||||||
|
<ClCompile Include="secpassword.cpp" />
|
||||||
|
<ClCompile Include="sha1.cpp" />
|
||||||
|
<ClCompile Include="sha256.cpp" />
|
||||||
|
<ClCompile Include="smallfn.cpp" />
|
||||||
|
<ClCompile Include="strfn.cpp" />
|
||||||
|
<ClCompile Include="strlist.cpp" />
|
||||||
|
<ClCompile Include="system.cpp" />
|
||||||
|
<ClCompile Include="threadpool.cpp" />
|
||||||
|
<ClCompile Include="timefn.cpp" />
|
||||||
|
<ClCompile Include="ui.cpp" />
|
||||||
|
<ClCompile Include="unicode.cpp" />
|
||||||
|
<ClCompile Include="unpack.cpp" />
|
||||||
|
<ClCompile Include="volume.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
420
deps/unrar/UnRARDll.vcxproj
vendored
Normal file
420
deps/unrar/UnRARDll.vcxproj
vendored
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="release_nocrypt|Win32">
|
||||||
|
<Configuration>release_nocrypt</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="release_nocrypt|x64">
|
||||||
|
<Configuration>release_nocrypt</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectName>UnRAR</ProjectName>
|
||||||
|
<ProjectGuid>{E815C46C-36C4-499F-BBC2-E772C6B17971}</ProjectGuid>
|
||||||
|
<RootNamespace>UnRAR</RootNamespace>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<GenerateManifest>true</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<GenerateManifest>true</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<GenerateManifest>true</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<GenerateManifest>true</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
|
||||||
|
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<GenerateManifest>true</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
|
||||||
|
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<GenerateManifest>true</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>Cdecl</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||||
|
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>Cdecl</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||||
|
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||||
|
<FloatingPointModel>Precise</FloatingPointModel>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>Cdecl</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||||
|
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<LinkTimeCodeGeneration />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>false</StringPooling>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>Cdecl</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||||
|
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<LinkTimeCodeGeneration />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||||
|
<FloatingPointModel>Precise</FloatingPointModel>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>Cdecl</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||||
|
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<LinkTimeCodeGeneration />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>false</StringPooling>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CallingConvention>StdCall</CallingConvention>
|
||||||
|
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||||
|
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<LinkTimeCodeGeneration />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="archive.cpp" />
|
||||||
|
<ClCompile Include="arcread.cpp" />
|
||||||
|
<ClCompile Include="blake2s.cpp" />
|
||||||
|
<ClCompile Include="cmddata.cpp" />
|
||||||
|
<ClCompile Include="consio.cpp" />
|
||||||
|
<ClCompile Include="crc.cpp" />
|
||||||
|
<ClCompile Include="crypt.cpp" />
|
||||||
|
<ClCompile Include="dll.cpp" />
|
||||||
|
<ClCompile Include="encname.cpp" />
|
||||||
|
<ClCompile Include="errhnd.cpp" />
|
||||||
|
<ClCompile Include="extinfo.cpp" />
|
||||||
|
<ClCompile Include="extract.cpp" />
|
||||||
|
<ClCompile Include="filcreat.cpp" />
|
||||||
|
<ClCompile Include="file.cpp" />
|
||||||
|
<ClCompile Include="filefn.cpp" />
|
||||||
|
<ClCompile Include="filestr.cpp" />
|
||||||
|
<ClCompile Include="find.cpp" />
|
||||||
|
<ClCompile Include="getbits.cpp" />
|
||||||
|
<ClCompile Include="global.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
|
||||||
|
</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="hash.cpp" />
|
||||||
|
<ClCompile Include="headers.cpp" />
|
||||||
|
<ClCompile Include="isnt.cpp" />
|
||||||
|
<ClCompile Include="match.cpp" />
|
||||||
|
<ClCompile Include="options.cpp" />
|
||||||
|
<ClCompile Include="pathfn.cpp" />
|
||||||
|
<ClCompile Include="qopen.cpp" />
|
||||||
|
<ClCompile Include="rar.cpp" />
|
||||||
|
<ClCompile Include="rarpch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="rarvm.cpp" />
|
||||||
|
<ClCompile Include="rawread.cpp" />
|
||||||
|
<ClCompile Include="rdwrfn.cpp" />
|
||||||
|
<ClCompile Include="rijndael.cpp" />
|
||||||
|
<ClCompile Include="rs.cpp" />
|
||||||
|
<ClCompile Include="rs16.cpp" />
|
||||||
|
<ClCompile Include="scantree.cpp" />
|
||||||
|
<ClCompile Include="secpassword.cpp" />
|
||||||
|
<ClCompile Include="sha1.cpp" />
|
||||||
|
<ClCompile Include="sha256.cpp" />
|
||||||
|
<ClCompile Include="smallfn.cpp" />
|
||||||
|
<ClCompile Include="strfn.cpp" />
|
||||||
|
<ClCompile Include="strlist.cpp" />
|
||||||
|
<ClCompile Include="system.cpp" />
|
||||||
|
<ClCompile Include="threadpool.cpp" />
|
||||||
|
<ClCompile Include="timefn.cpp" />
|
||||||
|
<ClCompile Include="ui.cpp" />
|
||||||
|
<ClCompile Include="unicode.cpp" />
|
||||||
|
<ClCompile Include="unpack.cpp" />
|
||||||
|
<ClCompile Include="volume.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="rar.hpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="dll.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
92
deps/unrar/acknow.txt
vendored
Normal file
92
deps/unrar/acknow.txt
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
ACKNOWLEDGMENTS
|
||||||
|
|
||||||
|
* We used "Screaming Fast Galois Field Arithmetic Using Intel
|
||||||
|
SIMD Instructions" paper by James S. Plank, Kevin M. Greenan
|
||||||
|
and Ethan L. Miller to improve Reed-Solomon coding performance.
|
||||||
|
Also we are grateful to Artem Drobanov and Bulat Ziganshin
|
||||||
|
for samples and ideas allowed to make Reed-Solomon coding
|
||||||
|
more efficient.
|
||||||
|
|
||||||
|
* RAR text compression algorithm is based on Dmitry Shkarin PPMII
|
||||||
|
and Dmitry Subbotin carryless rangecoder public domain source code.
|
||||||
|
You may find it in ftp.elf.stuba.sk/pub/pc/pack.
|
||||||
|
|
||||||
|
* RAR encryption includes parts of code from Szymon Stefanek
|
||||||
|
and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
LICENSE TERMS
|
||||||
|
|
||||||
|
The free distribution and use of this software in both source and binary
|
||||||
|
form is allowed (with or without changes) provided that:
|
||||||
|
|
||||||
|
1. distributions of this source code include the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer;
|
||||||
|
|
||||||
|
2. distributions in binary form include the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other associated materials;
|
||||||
|
|
||||||
|
3. the copyright holder's name is not used to endorse products
|
||||||
|
built using this software without specific written permission.
|
||||||
|
|
||||||
|
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||||
|
may be distributed under the terms of the GNU General Public License (GPL),
|
||||||
|
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
|
||||||
|
This software is provided 'as is' with no explicit or implied warranties
|
||||||
|
in respect of its properties, including, but not limited to, correctness
|
||||||
|
and/or fitness for purpose.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Source code of this package also as other cryptographic technology
|
||||||
|
and computing project related links are available on Brian Gladman's
|
||||||
|
web site: http://www.gladman.me.uk
|
||||||
|
|
||||||
|
* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
|
||||||
|
Original Intel Slicing-by-8 code is available here:
|
||||||
|
|
||||||
|
http://sourceforge.net/projects/slicing-by-8/
|
||||||
|
|
||||||
|
Original Intel Slicing-by-8 code is licensed under BSD License
|
||||||
|
available at http://www.opensource.org/licenses/bsd-license.html
|
||||||
|
|
||||||
|
Copyright (c) 2004-2006 Intel Corporation.
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with
|
||||||
|
the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
* RAR archives may optionally include BLAKE2sp hash ( https://blake2.net ),
|
||||||
|
designed by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn
|
||||||
|
and Christian Winnerlein.
|
||||||
|
|
||||||
|
* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
|
||||||
|
to significantly improve RAR compression and speed.
|
185
deps/unrar/arccmt.cpp
vendored
Normal file
185
deps/unrar/arccmt.cpp
vendored
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
static bool IsAnsiEscComment(const wchar *Data,size_t Size);
|
||||||
|
|
||||||
|
bool Archive::GetComment(Array<wchar> *CmtData)
|
||||||
|
{
|
||||||
|
if (!MainComment)
|
||||||
|
return false;
|
||||||
|
int64 SavePos=Tell();
|
||||||
|
bool Success=DoGetComment(CmtData);
|
||||||
|
Seek(SavePos,SEEK_SET);
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Archive::DoGetComment(Array<wchar> *CmtData)
|
||||||
|
{
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
uint CmtLength;
|
||||||
|
if (Format==RARFMT14)
|
||||||
|
{
|
||||||
|
Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
|
||||||
|
CmtLength=GetByte();
|
||||||
|
CmtLength+=(GetByte()<<8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (MainHead.CommentInHeader)
|
||||||
|
{
|
||||||
|
// Old style (RAR 2.9) archive comment embedded into the main
|
||||||
|
// archive header.
|
||||||
|
Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
|
||||||
|
if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Current (RAR 3.0+) version of archive comment.
|
||||||
|
Seek(GetStartPos(),SEEK_SET);
|
||||||
|
return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
|
||||||
|
}
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
// Old style (RAR 2.9) comment header embedded into the main
|
||||||
|
// archive header.
|
||||||
|
if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
|
||||||
|
{
|
||||||
|
if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
|
||||||
|
return false;
|
||||||
|
ComprDataIO DataIO;
|
||||||
|
DataIO.SetTestMode(true);
|
||||||
|
uint UnpCmtLength;
|
||||||
|
if (Format==RARFMT14)
|
||||||
|
{
|
||||||
|
#ifdef RAR_NOCRYPT
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
UnpCmtLength=GetByte();
|
||||||
|
UnpCmtLength+=(GetByte()<<8);
|
||||||
|
if (CmtLength<2)
|
||||||
|
return false;
|
||||||
|
CmtLength-=2;
|
||||||
|
DataIO.SetCmt13Encryption();
|
||||||
|
CommHead.UnpVer=15;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
UnpCmtLength=CommHead.UnpSize;
|
||||||
|
DataIO.SetFiles(this,NULL);
|
||||||
|
DataIO.EnableShowProgress(false);
|
||||||
|
DataIO.SetPackedSizeToRead(CmtLength);
|
||||||
|
DataIO.UnpHash.Init(HASH_CRC32,1);
|
||||||
|
DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet.
|
||||||
|
|
||||||
|
Unpack CmtUnpack(&DataIO);
|
||||||
|
CmtUnpack.Init(0x10000,false);
|
||||||
|
CmtUnpack.SetDestSize(UnpCmtLength);
|
||||||
|
CmtUnpack.DoUnpack(CommHead.UnpVer,false);
|
||||||
|
|
||||||
|
if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte *UnpData;
|
||||||
|
size_t UnpDataSize;
|
||||||
|
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
|
||||||
|
if (UnpDataSize>0)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// If we ever decide to extend it to Android, we'll need to alloc
|
||||||
|
// 4x memory for OEM to UTF-8 output here.
|
||||||
|
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
|
||||||
|
#endif
|
||||||
|
CmtData->Alloc(UnpDataSize+1);
|
||||||
|
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
|
||||||
|
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
|
||||||
|
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (CmtLength==0)
|
||||||
|
return false;
|
||||||
|
Array<byte> CmtRaw(CmtLength);
|
||||||
|
int ReadSize=Read(&CmtRaw[0],CmtLength);
|
||||||
|
if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
|
||||||
|
{
|
||||||
|
CmtLength=ReadSize;
|
||||||
|
CmtRaw.Alloc(CmtLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CmtData->Alloc(CmtLength+1);
|
||||||
|
CmtRaw.Push(0);
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// If we ever decide to extend it to Android, we'll need to alloc
|
||||||
|
// 4x memory for OEM to UTF-8 output here.
|
||||||
|
OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
|
||||||
|
#endif
|
||||||
|
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
||||||
|
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return CmtData->Size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Archive::ReadCommentData(Array<wchar> *CmtData)
|
||||||
|
{
|
||||||
|
Array<byte> CmtRaw;
|
||||||
|
if (!ReadSubData(&CmtRaw,NULL,false))
|
||||||
|
return false;
|
||||||
|
size_t CmtSize=CmtRaw.Size();
|
||||||
|
CmtRaw.Push(0);
|
||||||
|
CmtData->Alloc(CmtSize+1);
|
||||||
|
if (Format==RARFMT50)
|
||||||
|
UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
||||||
|
else
|
||||||
|
if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
|
||||||
|
{
|
||||||
|
RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
|
||||||
|
(*CmtData)[CmtSize/2]=0;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
||||||
|
}
|
||||||
|
CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Archive::ViewComment()
|
||||||
|
{
|
||||||
|
if (Cmd->DisableComment)
|
||||||
|
return;
|
||||||
|
Array<wchar> CmtBuf;
|
||||||
|
if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
|
||||||
|
{
|
||||||
|
size_t CmtSize=CmtBuf.Size();
|
||||||
|
wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
|
||||||
|
if (ChPtr!=NULL)
|
||||||
|
CmtSize=ChPtr-&CmtBuf[0];
|
||||||
|
mprintf(L"\n");
|
||||||
|
OutComment(&CmtBuf[0],CmtSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
338
deps/unrar/archive.cpp
vendored
Normal file
338
deps/unrar/archive.cpp
vendored
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#include "arccmt.cpp"
|
||||||
|
|
||||||
|
|
||||||
|
Archive::Archive(RAROptions *InitCmd)
|
||||||
|
{
|
||||||
|
Cmd=NULL; // Just in case we'll have an exception in 'new' below.
|
||||||
|
|
||||||
|
DummyCmd=(InitCmd==NULL);
|
||||||
|
Cmd=DummyCmd ? (new RAROptions):InitCmd;
|
||||||
|
|
||||||
|
OpenShared=Cmd->OpenShared;
|
||||||
|
Format=RARFMT15;
|
||||||
|
Solid=false;
|
||||||
|
Volume=false;
|
||||||
|
MainComment=false;
|
||||||
|
Locked=false;
|
||||||
|
Signed=false;
|
||||||
|
FirstVolume=false;
|
||||||
|
NewNumbering=false;
|
||||||
|
SFXSize=0;
|
||||||
|
LatestTime.Reset();
|
||||||
|
Protected=false;
|
||||||
|
Encrypted=false;
|
||||||
|
FailedHeaderDecryption=false;
|
||||||
|
BrokenHeader=false;
|
||||||
|
LastReadBlock=0;
|
||||||
|
|
||||||
|
CurBlockPos=0;
|
||||||
|
NextBlockPos=0;
|
||||||
|
|
||||||
|
|
||||||
|
memset(&MainHead,0,sizeof(MainHead));
|
||||||
|
memset(&CryptHead,0,sizeof(CryptHead));
|
||||||
|
memset(&EndArcHead,0,sizeof(EndArcHead));
|
||||||
|
|
||||||
|
VolNumber=0;
|
||||||
|
VolWrite=0;
|
||||||
|
AddingFilesSize=0;
|
||||||
|
AddingHeadersSize=0;
|
||||||
|
*FirstVolumeName=0;
|
||||||
|
|
||||||
|
Splitting=false;
|
||||||
|
NewArchive=false;
|
||||||
|
|
||||||
|
SilentOpen=false;
|
||||||
|
|
||||||
|
#ifdef USE_QOPEN
|
||||||
|
ProhibitQOpen=false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Archive::~Archive()
|
||||||
|
{
|
||||||
|
if (DummyCmd)
|
||||||
|
delete Cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Archive::CheckArc(bool EnableBroken)
|
||||||
|
{
|
||||||
|
if (!IsArchive(EnableBroken))
|
||||||
|
{
|
||||||
|
// If FailedHeaderDecryption is set, we already reported that archive
|
||||||
|
// password is incorrect.
|
||||||
|
if (!FailedHeaderDecryption)
|
||||||
|
uiMsg(UIERROR_BADARCHIVE,FileName);
|
||||||
|
ErrHandler.Exit(RARX_FATAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void Archive::CheckOpen(const wchar *Name)
|
||||||
|
{
|
||||||
|
TOpen(Name);
|
||||||
|
CheckArc(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool Archive::WCheckOpen(const wchar *Name)
|
||||||
|
{
|
||||||
|
if (!WOpen(Name))
|
||||||
|
return false;
|
||||||
|
if (!IsArchive(false))
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_BADARCHIVE,FileName);
|
||||||
|
Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
|
||||||
|
{
|
||||||
|
RARFORMAT Type=RARFMT_NONE;
|
||||||
|
if (Size>=1 && D[0]==0x52)
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
|
||||||
|
Type=RARFMT14;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
|
||||||
|
{
|
||||||
|
// We check the last signature byte, so we can return a sensible
|
||||||
|
// warning in case we'll want to change the archive format
|
||||||
|
// sometimes in the future.
|
||||||
|
if (D[6]==0)
|
||||||
|
Type=RARFMT15;
|
||||||
|
else
|
||||||
|
if (D[6]==1)
|
||||||
|
Type=RARFMT50;
|
||||||
|
else
|
||||||
|
if (D[6]>1 && D[6]<5)
|
||||||
|
Type=RARFMT_FUTURE;
|
||||||
|
}
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Archive::IsArchive(bool EnableBroken)
|
||||||
|
{
|
||||||
|
Encrypted=false;
|
||||||
|
BrokenHeader=false; // Might be left from previous volume.
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
if (IsDevice())
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_INVALIDNAME,FileName,FileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
|
||||||
|
return false;
|
||||||
|
SFXSize=0;
|
||||||
|
|
||||||
|
RARFORMAT Type;
|
||||||
|
if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
|
||||||
|
{
|
||||||
|
Format=Type;
|
||||||
|
if (Format==RARFMT14)
|
||||||
|
Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Array<char> Buffer(MAXSFXSIZE);
|
||||||
|
long CurPos=(long)Tell();
|
||||||
|
int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
|
||||||
|
for (int I=0;I<ReadSize;I++)
|
||||||
|
if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE)
|
||||||
|
{
|
||||||
|
Format=Type;
|
||||||
|
if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31)
|
||||||
|
{
|
||||||
|
char *D=&Buffer[28-CurPos];
|
||||||
|
if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SFXSize=CurPos+I;
|
||||||
|
Seek(SFXSize,SEEK_SET);
|
||||||
|
if (Format==RARFMT15 || Format==RARFMT50)
|
||||||
|
Read(MarkHead.Mark,SIZEOF_MARKHEAD3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (SFXSize==0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Format==RARFMT_FUTURE)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_NEWRARFORMAT,FileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
|
||||||
|
{
|
||||||
|
if (Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1)!=1 || MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
|
||||||
|
return false;
|
||||||
|
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MarkHead.HeadSize=SIZEOF_MARKHEAD3;
|
||||||
|
|
||||||
|
#ifdef RARDLL
|
||||||
|
// If callback function is not set, we cannot get the password,
|
||||||
|
// so we skip the initial header processing for encrypted header archive.
|
||||||
|
// It leads to skipped archive comment, but the rest of archive data
|
||||||
|
// is processed correctly.
|
||||||
|
if (Cmd->Callback==NULL)
|
||||||
|
SilentOpen=true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool HeadersLeft; // Any headers left to read.
|
||||||
|
bool StartFound=false; // Main or encryption headers found.
|
||||||
|
// Skip the archive encryption header if any and read the main header.
|
||||||
|
while ((HeadersLeft=(ReadHeader()!=0))==true) // Additional parentheses to silence Clang.
|
||||||
|
{
|
||||||
|
SeekToNext();
|
||||||
|
|
||||||
|
HEADER_TYPE Type=GetHeaderType();
|
||||||
|
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
|
||||||
|
// avoid the password prompt.
|
||||||
|
StartFound=Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT;
|
||||||
|
if (StartFound)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We should not do it for EnableBroken or we'll get 'not RAR archive'
|
||||||
|
// messages when extracting encrypted archives with wrong password.
|
||||||
|
if (FailedHeaderDecryption && !EnableBroken)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing.
|
||||||
|
{
|
||||||
|
if (!FailedHeaderDecryption) // If not reported a wrong password already.
|
||||||
|
uiMsg(UIERROR_MHEADERBROKEN,FileName);
|
||||||
|
if (!EnableBroken)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainComment=MainHead.CommentInHeader;
|
||||||
|
|
||||||
|
// If we process non-encrypted archive or can request a password,
|
||||||
|
// we set 'first volume' flag based on file attributes below.
|
||||||
|
// It is necessary for RAR 2.x archives, which did not have 'first volume'
|
||||||
|
// flag in main header. Also for all RAR formats we need to scan until
|
||||||
|
// first file header to set "comment" flag when reading service header.
|
||||||
|
// Unless we are in silent mode, we need to know about presence of comment
|
||||||
|
// immediately after IsArchive call.
|
||||||
|
if (HeadersLeft && (!SilentOpen || !Encrypted))
|
||||||
|
{
|
||||||
|
int64 SavePos=Tell();
|
||||||
|
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||||
|
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
||||||
|
|
||||||
|
while (ReadHeader()!=0)
|
||||||
|
{
|
||||||
|
HEADER_TYPE HeaderType=GetHeaderType();
|
||||||
|
if (HeaderType==HEAD_SERVICE)
|
||||||
|
{
|
||||||
|
// If we have a split service headers, it surely indicates non-first
|
||||||
|
// volume. But not split service header does not guarantee the first
|
||||||
|
// volume, because we can have split file after non-split archive
|
||||||
|
// comment. So we do not quit from loop here.
|
||||||
|
FirstVolume=Volume && !SubHead.SplitBefore;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (HeaderType==HEAD_FILE)
|
||||||
|
{
|
||||||
|
FirstVolume=Volume && !FileHead.SplitBefore;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (HeaderType==HEAD_ENDARC) // Might happen if archive contains only a split service header.
|
||||||
|
break;
|
||||||
|
SeekToNext();
|
||||||
|
}
|
||||||
|
CurBlockPos=SaveCurBlockPos;
|
||||||
|
NextBlockPos=SaveNextBlockPos;
|
||||||
|
CurHeaderType=SaveCurHeaderType;
|
||||||
|
Seek(SavePos,SEEK_SET);
|
||||||
|
}
|
||||||
|
if (!Volume || FirstVolume)
|
||||||
|
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Archive::SeekToNext()
|
||||||
|
{
|
||||||
|
Seek(NextBlockPos,SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate the block size including encryption fields and padding if any.
|
||||||
|
uint Archive::FullHeaderSize(size_t Size)
|
||||||
|
{
|
||||||
|
if (Encrypted)
|
||||||
|
{
|
||||||
|
Size = ALIGN_VALUE(Size, CRYPT_BLOCK_SIZE); // Align to encryption block size.
|
||||||
|
if (Format == RARFMT50)
|
||||||
|
Size += SIZE_INITV;
|
||||||
|
else
|
||||||
|
Size += SIZE_SALT30;
|
||||||
|
}
|
||||||
|
return uint(Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_QOPEN
|
||||||
|
bool Archive::Open(const wchar *Name,uint Mode)
|
||||||
|
{
|
||||||
|
// Important if we reuse Archive object and it has virtual QOpen
|
||||||
|
// file position not matching real. For example, for 'l -v volname'.
|
||||||
|
QOpen.Unload();
|
||||||
|
|
||||||
|
return File::Open(Name,Mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Archive::Read(void *Data,size_t Size)
|
||||||
|
{
|
||||||
|
size_t Result;
|
||||||
|
if (QOpen.Read(Data,Size,Result))
|
||||||
|
return (int)Result;
|
||||||
|
return File::Read(Data,Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Archive::Seek(int64 Offset,int Method)
|
||||||
|
{
|
||||||
|
if (!QOpen.Seek(Offset,Method))
|
||||||
|
File::Seek(Offset,Method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64 Archive::Tell()
|
||||||
|
{
|
||||||
|
int64 QPos;
|
||||||
|
if (QOpen.Tell(&QPos))
|
||||||
|
return QPos;
|
||||||
|
return File::Tell();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
148
deps/unrar/archive.hpp
vendored
Normal file
148
deps/unrar/archive.hpp
vendored
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#ifndef _RAR_ARCHIVE_
|
||||||
|
#define _RAR_ARCHIVE_
|
||||||
|
|
||||||
|
class PPack;
|
||||||
|
class RawRead;
|
||||||
|
class RawWrite;
|
||||||
|
|
||||||
|
enum NOMODIFY_FLAGS
|
||||||
|
{
|
||||||
|
NMDF_ALLOWLOCK=1,NMDF_ALLOWANYVOLUME=2,NMDF_ALLOWFIRSTVOLUME=4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RARFORMAT {RARFMT_NONE,RARFMT14,RARFMT15,RARFMT50,RARFMT_FUTURE};
|
||||||
|
|
||||||
|
enum ADDSUBDATA_FLAGS
|
||||||
|
{
|
||||||
|
ASDF_SPLIT = 1, // Allow to split archive just before header if necessary.
|
||||||
|
ASDF_COMPRESS = 2, // Allow to compress data following subheader.
|
||||||
|
ASDF_CRYPT = 4, // Encrypt data after subheader if password is set.
|
||||||
|
ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode.
|
||||||
|
};
|
||||||
|
|
||||||
|
// RAR5 headers must not exceed 2 MB.
|
||||||
|
#define MAX_HEADER_SIZE_RAR5 0x200000
|
||||||
|
|
||||||
|
class Archive:public File
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void UpdateLatestTime(FileHeader *CurBlock);
|
||||||
|
void ConvertNameCase(wchar *Name);
|
||||||
|
void ConvertFileHeader(FileHeader *hd);
|
||||||
|
size_t ReadHeader14();
|
||||||
|
size_t ReadHeader15();
|
||||||
|
size_t ReadHeader50();
|
||||||
|
void ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb);
|
||||||
|
void RequestArcPassword();
|
||||||
|
void UnexpEndArcMsg();
|
||||||
|
void BrokenHeaderMsg();
|
||||||
|
void UnkEncVerMsg(const wchar *Name,const wchar *Info);
|
||||||
|
bool DoGetComment(Array<wchar> *CmtData);
|
||||||
|
bool ReadCommentData(Array<wchar> *CmtData);
|
||||||
|
|
||||||
|
#if !defined(RAR_NOCRYPT)
|
||||||
|
CryptData HeadersCrypt;
|
||||||
|
#endif
|
||||||
|
ComprDataIO SubDataIO;
|
||||||
|
bool DummyCmd;
|
||||||
|
RAROptions *Cmd;
|
||||||
|
|
||||||
|
|
||||||
|
RarTime LatestTime;
|
||||||
|
int LastReadBlock;
|
||||||
|
HEADER_TYPE CurHeaderType;
|
||||||
|
|
||||||
|
bool SilentOpen;
|
||||||
|
#ifdef USE_QOPEN
|
||||||
|
QuickOpen QOpen;
|
||||||
|
bool ProhibitQOpen;
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
Archive(RAROptions *InitCmd=NULL);
|
||||||
|
~Archive();
|
||||||
|
static RARFORMAT IsSignature(const byte *D,size_t Size);
|
||||||
|
bool IsArchive(bool EnableBroken);
|
||||||
|
size_t SearchBlock(HEADER_TYPE HeaderType);
|
||||||
|
size_t SearchSubBlock(const wchar *Type);
|
||||||
|
size_t SearchRR();
|
||||||
|
size_t ReadHeader();
|
||||||
|
void CheckArc(bool EnableBroken);
|
||||||
|
void CheckOpen(const wchar *Name);
|
||||||
|
bool WCheckOpen(const wchar *Name);
|
||||||
|
bool GetComment(Array<wchar> *CmtData);
|
||||||
|
void ViewComment();
|
||||||
|
void SetLatestTime(RarTime *NewTime);
|
||||||
|
void SeekToNext();
|
||||||
|
bool CheckAccess();
|
||||||
|
bool IsArcDir();
|
||||||
|
void ConvertAttributes();
|
||||||
|
void VolSubtractHeaderSize(size_t SubSize);
|
||||||
|
uint FullHeaderSize(size_t Size);
|
||||||
|
int64 GetStartPos();
|
||||||
|
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
|
||||||
|
const wchar *Name,uint Flags);
|
||||||
|
bool ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode);
|
||||||
|
HEADER_TYPE GetHeaderType() {return CurHeaderType;}
|
||||||
|
RAROptions* GetRAROptions() {return Cmd;}
|
||||||
|
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
|
||||||
|
#if 0
|
||||||
|
void GetRecoveryInfo(bool Required,int64 *Size,int *Percent);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_QOPEN
|
||||||
|
bool Open(const wchar *Name,uint Mode=FMF_READ);
|
||||||
|
int Read(void *Data,size_t Size);
|
||||||
|
void Seek(int64 Offset,int Method);
|
||||||
|
int64 Tell();
|
||||||
|
void QOpenUnload() {QOpen.Unload();}
|
||||||
|
void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BaseBlock ShortBlock;
|
||||||
|
MarkHeader MarkHead;
|
||||||
|
MainHeader MainHead;
|
||||||
|
CryptHeader CryptHead;
|
||||||
|
FileHeader FileHead;
|
||||||
|
EndArcHeader EndArcHead;
|
||||||
|
SubBlockHeader SubBlockHead;
|
||||||
|
FileHeader SubHead;
|
||||||
|
CommentHeader CommHead;
|
||||||
|
ProtectHeader ProtectHead;
|
||||||
|
UnixOwnersHeader UOHead;
|
||||||
|
EAHeader EAHead;
|
||||||
|
StreamHeader StreamHead;
|
||||||
|
|
||||||
|
int64 CurBlockPos;
|
||||||
|
int64 NextBlockPos;
|
||||||
|
|
||||||
|
RARFORMAT Format;
|
||||||
|
bool Solid;
|
||||||
|
bool Volume;
|
||||||
|
bool MainComment;
|
||||||
|
bool Locked;
|
||||||
|
bool Signed;
|
||||||
|
bool FirstVolume;
|
||||||
|
bool NewNumbering;
|
||||||
|
bool Protected;
|
||||||
|
bool Encrypted;
|
||||||
|
size_t SFXSize;
|
||||||
|
bool BrokenHeader;
|
||||||
|
bool FailedHeaderDecryption;
|
||||||
|
|
||||||
|
#if !defined(RAR_NOCRYPT)
|
||||||
|
byte ArcSalt[SIZE_SALT50];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Splitting;
|
||||||
|
|
||||||
|
uint VolNumber;
|
||||||
|
int64 VolWrite;
|
||||||
|
uint64 AddingFilesSize;
|
||||||
|
uint64 AddingHeadersSize;
|
||||||
|
|
||||||
|
bool NewArchive;
|
||||||
|
|
||||||
|
wchar FirstVolumeName[NM];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
1485
deps/unrar/arcread.cpp
vendored
Normal file
1485
deps/unrar/arcread.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
191
deps/unrar/array.hpp
vendored
Normal file
191
deps/unrar/array.hpp
vendored
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
#ifndef _RAR_ARRAY_
|
||||||
|
#define _RAR_ARRAY_
|
||||||
|
|
||||||
|
extern ErrorHandler ErrHandler;
|
||||||
|
|
||||||
|
template <class T> class Array
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
T *Buffer;
|
||||||
|
size_t BufSize;
|
||||||
|
size_t AllocSize;
|
||||||
|
size_t MaxSize;
|
||||||
|
bool Secure; // Clean memory if true.
|
||||||
|
public:
|
||||||
|
Array();
|
||||||
|
Array(size_t Size);
|
||||||
|
Array(const Array &Src); // Copy constructor.
|
||||||
|
~Array();
|
||||||
|
inline void CleanData();
|
||||||
|
inline T& operator [](size_t Item) const;
|
||||||
|
inline T* operator + (size_t Pos);
|
||||||
|
inline size_t Size(); // Returns the size in items, not in bytes.
|
||||||
|
void Add(size_t Items);
|
||||||
|
void Alloc(size_t Items);
|
||||||
|
void Reset();
|
||||||
|
void SoftReset();
|
||||||
|
void operator = (Array<T> &Src);
|
||||||
|
void Push(T Item);
|
||||||
|
void Append(T *Item,size_t Count);
|
||||||
|
T* Addr(size_t Item) {return Buffer+Item;}
|
||||||
|
void SetMaxSize(size_t Size) {MaxSize=Size;}
|
||||||
|
T* Begin() {return Buffer;}
|
||||||
|
T* End() {return Buffer==NULL ? NULL:Buffer+BufSize;}
|
||||||
|
void SetSecure() {Secure=true;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> void Array<T>::CleanData()
|
||||||
|
{
|
||||||
|
Buffer=NULL;
|
||||||
|
BufSize=0;
|
||||||
|
AllocSize=0;
|
||||||
|
MaxSize=0;
|
||||||
|
Secure=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> Array<T>::Array()
|
||||||
|
{
|
||||||
|
CleanData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> Array<T>::Array(size_t Size)
|
||||||
|
{
|
||||||
|
CleanData();
|
||||||
|
Add(Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Copy constructor in case we need to pass an object as value.
|
||||||
|
template <class T> Array<T>::Array(const Array &Src)
|
||||||
|
{
|
||||||
|
CleanData();
|
||||||
|
Alloc(Src.BufSize);
|
||||||
|
if (Src.BufSize!=0)
|
||||||
|
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> Array<T>::~Array()
|
||||||
|
{
|
||||||
|
if (Buffer!=NULL)
|
||||||
|
{
|
||||||
|
if (Secure)
|
||||||
|
cleandata(Buffer,AllocSize*sizeof(T));
|
||||||
|
free(Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> inline T& Array<T>::operator [](size_t Item) const
|
||||||
|
{
|
||||||
|
return Buffer[Item];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> inline T* Array<T>::operator +(size_t Pos)
|
||||||
|
{
|
||||||
|
return Buffer+Pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> inline size_t Array<T>::Size()
|
||||||
|
{
|
||||||
|
return BufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> void Array<T>::Add(size_t Items)
|
||||||
|
{
|
||||||
|
BufSize+=Items;
|
||||||
|
if (BufSize>AllocSize)
|
||||||
|
{
|
||||||
|
if (MaxSize!=0 && BufSize>MaxSize)
|
||||||
|
{
|
||||||
|
ErrHandler.GeneralErrMsg(L"Maximum allowed array size (%u) is exceeded",MaxSize);
|
||||||
|
ErrHandler.MemoryError();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Suggested=AllocSize+AllocSize/4+32;
|
||||||
|
size_t NewSize=Max(BufSize,Suggested);
|
||||||
|
|
||||||
|
T *NewBuffer;
|
||||||
|
if (Secure)
|
||||||
|
{
|
||||||
|
NewBuffer=(T *)malloc(NewSize*sizeof(T));
|
||||||
|
if (NewBuffer==NULL)
|
||||||
|
ErrHandler.MemoryError();
|
||||||
|
if (Buffer!=NULL)
|
||||||
|
{
|
||||||
|
memcpy(NewBuffer,Buffer,AllocSize*sizeof(T));
|
||||||
|
cleandata(Buffer,AllocSize*sizeof(T));
|
||||||
|
free(Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T));
|
||||||
|
if (NewBuffer==NULL)
|
||||||
|
ErrHandler.MemoryError();
|
||||||
|
}
|
||||||
|
Buffer=NewBuffer;
|
||||||
|
AllocSize=NewSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> void Array<T>::Alloc(size_t Items)
|
||||||
|
{
|
||||||
|
if (Items>AllocSize)
|
||||||
|
Add(Items-BufSize);
|
||||||
|
else
|
||||||
|
BufSize=Items;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> void Array<T>::Reset()
|
||||||
|
{
|
||||||
|
if (Buffer!=NULL)
|
||||||
|
{
|
||||||
|
free(Buffer);
|
||||||
|
Buffer=NULL;
|
||||||
|
}
|
||||||
|
BufSize=0;
|
||||||
|
AllocSize=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset buffer size, but preserve already allocated memory if any,
|
||||||
|
// so we can reuse it without wasting time to allocation.
|
||||||
|
template <class T> void Array<T>::SoftReset()
|
||||||
|
{
|
||||||
|
BufSize=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> void Array<T>::operator =(Array<T> &Src)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
Alloc(Src.BufSize);
|
||||||
|
if (Src.BufSize!=0)
|
||||||
|
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> void Array<T>::Push(T Item)
|
||||||
|
{
|
||||||
|
Add(1);
|
||||||
|
(*this)[Size()-1]=Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> void Array<T>::Append(T *Items,size_t Count)
|
||||||
|
{
|
||||||
|
size_t CurSize=Size();
|
||||||
|
Add(Count);
|
||||||
|
memcpy(Buffer+CurSize,Items,Count*sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
183
deps/unrar/blake2s.cpp
vendored
Normal file
183
deps/unrar/blake2s.cpp
vendored
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
// Based on public domain code written in 2012 by Samuel Neves
|
||||||
|
|
||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#ifdef USE_SSE
|
||||||
|
#include "blake2s_sse.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth);
|
||||||
|
static void blake2s_update( blake2s_state *S, const byte *in, size_t inlen );
|
||||||
|
static void blake2s_final( blake2s_state *S, byte *digest );
|
||||||
|
|
||||||
|
#include "blake2sp.cpp"
|
||||||
|
|
||||||
|
static const uint32 blake2s_IV[8] =
|
||||||
|
{
|
||||||
|
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||||
|
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const byte blake2s_sigma[10][16] =
|
||||||
|
{
|
||||||
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||||
|
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||||
|
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||||
|
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||||
|
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||||
|
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||||
|
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||||
|
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||||
|
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||||
|
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void blake2s_set_lastnode( blake2s_state *S )
|
||||||
|
{
|
||||||
|
S->f[1] = ~0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Some helper functions, not necessarily useful */
|
||||||
|
static inline void blake2s_set_lastblock( blake2s_state *S )
|
||||||
|
{
|
||||||
|
if( S->last_node ) blake2s_set_lastnode( S );
|
||||||
|
|
||||||
|
S->f[0] = ~0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void blake2s_increment_counter( blake2s_state *S, const uint32 inc )
|
||||||
|
{
|
||||||
|
S->t[0] += inc;
|
||||||
|
S->t[1] += ( S->t[0] < inc );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* init2 xors IV with input parameter block */
|
||||||
|
void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth)
|
||||||
|
{
|
||||||
|
#ifdef USE_SSE
|
||||||
|
if (_SSE_Version>=SSE_SSE2)
|
||||||
|
blake2s_init_sse();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
S->init(); // Clean data.
|
||||||
|
for( int i = 0; i < 8; ++i )
|
||||||
|
S->h[i] = blake2s_IV[i];
|
||||||
|
|
||||||
|
S->h[0] ^= 0x02080020; // We use BLAKE2sp parameters block.
|
||||||
|
S->h[2] ^= node_offset;
|
||||||
|
S->h[3] ^= (node_depth<<16)|0x20000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define G(r,i,m,a,b,c,d) \
|
||||||
|
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
|
||||||
|
d = rotr32(d ^ a, 16); \
|
||||||
|
c = c + d; \
|
||||||
|
b = rotr32(b ^ c, 12); \
|
||||||
|
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
|
||||||
|
d = rotr32(d ^ a, 8); \
|
||||||
|
c = c + d; \
|
||||||
|
b = rotr32(b ^ c, 7);
|
||||||
|
|
||||||
|
|
||||||
|
static void blake2s_compress( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
|
||||||
|
{
|
||||||
|
uint32 m[16];
|
||||||
|
uint32 v[16];
|
||||||
|
|
||||||
|
for( size_t i = 0; i < 16; ++i )
|
||||||
|
m[i] = RawGet4( block + i * 4 );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < 8; ++i )
|
||||||
|
v[i] = S->h[i];
|
||||||
|
|
||||||
|
v[ 8] = blake2s_IV[0];
|
||||||
|
v[ 9] = blake2s_IV[1];
|
||||||
|
v[10] = blake2s_IV[2];
|
||||||
|
v[11] = blake2s_IV[3];
|
||||||
|
v[12] = S->t[0] ^ blake2s_IV[4];
|
||||||
|
v[13] = S->t[1] ^ blake2s_IV[5];
|
||||||
|
v[14] = S->f[0] ^ blake2s_IV[6];
|
||||||
|
v[15] = S->f[1] ^ blake2s_IV[7];
|
||||||
|
|
||||||
|
for ( uint r = 0; r <= 9; ++r ) // No gain on i7 if unrolled, but exe size grows.
|
||||||
|
{
|
||||||
|
G(r,0,m,v[ 0],v[ 4],v[ 8],v[12]);
|
||||||
|
G(r,1,m,v[ 1],v[ 5],v[ 9],v[13]);
|
||||||
|
G(r,2,m,v[ 2],v[ 6],v[10],v[14]);
|
||||||
|
G(r,3,m,v[ 3],v[ 7],v[11],v[15]);
|
||||||
|
G(r,4,m,v[ 0],v[ 5],v[10],v[15]);
|
||||||
|
G(r,5,m,v[ 1],v[ 6],v[11],v[12]);
|
||||||
|
G(r,6,m,v[ 2],v[ 7],v[ 8],v[13]);
|
||||||
|
G(r,7,m,v[ 3],v[ 4],v[ 9],v[14]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for( size_t i = 0; i < 8; ++i )
|
||||||
|
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void blake2s_update( blake2s_state *S, const byte *in, size_t inlen )
|
||||||
|
{
|
||||||
|
while( inlen > 0 )
|
||||||
|
{
|
||||||
|
size_t left = S->buflen;
|
||||||
|
size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
|
||||||
|
|
||||||
|
if( inlen > fill )
|
||||||
|
{
|
||||||
|
memcpy( S->buf + left, in, fill ); // Fill buffer
|
||||||
|
S->buflen += fill;
|
||||||
|
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
|
#ifdef USE_SSE
|
||||||
|
#ifdef _WIN_32 // We use SSSE3 _mm_shuffle_epi8 only in x64 mode.
|
||||||
|
if (_SSE_Version>=SSE_SSE2)
|
||||||
|
#else
|
||||||
|
if (_SSE_Version>=SSE_SSSE3)
|
||||||
|
#endif
|
||||||
|
blake2s_compress_sse( S, S->buf );
|
||||||
|
else
|
||||||
|
blake2s_compress( S, S->buf ); // Compress
|
||||||
|
#else
|
||||||
|
blake2s_compress( S, S->buf ); // Compress
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
|
||||||
|
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||||
|
in += fill;
|
||||||
|
inlen -= fill;
|
||||||
|
}
|
||||||
|
else // inlen <= fill
|
||||||
|
{
|
||||||
|
memcpy( S->buf + left, in, (size_t)inlen );
|
||||||
|
S->buflen += (size_t)inlen; // Be lazy, do not compress
|
||||||
|
in += inlen;
|
||||||
|
inlen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void blake2s_final( blake2s_state *S, byte *digest )
|
||||||
|
{
|
||||||
|
if( S->buflen > BLAKE2S_BLOCKBYTES )
|
||||||
|
{
|
||||||
|
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||||
|
blake2s_compress( S, S->buf );
|
||||||
|
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||||
|
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
|
||||||
|
}
|
||||||
|
|
||||||
|
blake2s_increment_counter( S, ( uint32 )S->buflen );
|
||||||
|
blake2s_set_lastblock( S );
|
||||||
|
memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
|
||||||
|
blake2s_compress( S, S->buf );
|
||||||
|
|
||||||
|
for( int i = 0; i < 8; ++i ) /* Output full hash */
|
||||||
|
RawPut4( S->h[i], digest + 4 * i );
|
||||||
|
}
|
||||||
|
|
102
deps/unrar/blake2s.hpp
vendored
Normal file
102
deps/unrar/blake2s.hpp
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Based on public domain code written in 2012 by Samuel Neves
|
||||||
|
#ifndef _RAR_BLAKE2_
|
||||||
|
#define _RAR_BLAKE2_
|
||||||
|
|
||||||
|
#define BLAKE2_DIGEST_SIZE 32
|
||||||
|
#define BLAKE2_THREADS_NUMBER 8
|
||||||
|
|
||||||
|
enum blake2s_constant
|
||||||
|
{
|
||||||
|
BLAKE2S_BLOCKBYTES = 64,
|
||||||
|
BLAKE2S_OUTBYTES = 32
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Alignment to 64 improves performance of both SSE and non-SSE versions.
|
||||||
|
// Alignment to n*16 is required for SSE version, so we selected 64.
|
||||||
|
// We use the custom alignment scheme instead of __declspec(align(x)),
|
||||||
|
// because it is less compiler dependent. Also the compiler directive
|
||||||
|
// does not help if structure is a member of class allocated through
|
||||||
|
// 'new' operator.
|
||||||
|
struct blake2s_state
|
||||||
|
{
|
||||||
|
enum { BLAKE_ALIGNMENT = 64 };
|
||||||
|
|
||||||
|
// buffer and uint32 h[8], t[2], f[2];
|
||||||
|
enum { BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES };
|
||||||
|
|
||||||
|
byte ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT];
|
||||||
|
|
||||||
|
byte *buf; // byte buf[2 * BLAKE2S_BLOCKBYTES].
|
||||||
|
uint32 *h, *t, *f; // uint32 h[8], t[2], f[2].
|
||||||
|
|
||||||
|
size_t buflen;
|
||||||
|
byte last_node;
|
||||||
|
|
||||||
|
blake2s_state()
|
||||||
|
{
|
||||||
|
set_pointers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required when we declare and assign in the same command.
|
||||||
|
blake2s_state(blake2s_state &st)
|
||||||
|
{
|
||||||
|
set_pointers();
|
||||||
|
*this=st;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pointers()
|
||||||
|
{
|
||||||
|
// Set aligned pointers. Must be done in constructor, not in Init(),
|
||||||
|
// so assignments like 'blake2sp_state res=blake2ctx' work correctly
|
||||||
|
// even if blake2sp_init is not called for 'res'.
|
||||||
|
buf = (byte *) ALIGN_VALUE(ubuf, BLAKE_ALIGNMENT);
|
||||||
|
h = (uint32 *) (buf + 2 * BLAKE2S_BLOCKBYTES);
|
||||||
|
t = h + 8;
|
||||||
|
f = t + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
memset( ubuf, 0, sizeof( ubuf ) );
|
||||||
|
buflen = 0;
|
||||||
|
last_node = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we use pointers, the default = would work incorrectly.
|
||||||
|
blake2s_state& operator = (blake2s_state &st)
|
||||||
|
{
|
||||||
|
if (this != &st)
|
||||||
|
{
|
||||||
|
memcpy(buf, st.buf, BLAKE_DATA_SIZE);
|
||||||
|
buflen = st.buflen;
|
||||||
|
last_node = st.last_node;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
class ThreadPool;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct blake2sp_state
|
||||||
|
{
|
||||||
|
blake2s_state S[8];
|
||||||
|
blake2s_state R;
|
||||||
|
byte buf[8 * BLAKE2S_BLOCKBYTES];
|
||||||
|
size_t buflen;
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
ThreadPool *ThPool;
|
||||||
|
uint MaxThreads;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
void blake2sp_init( blake2sp_state *S );
|
||||||
|
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen );
|
||||||
|
void blake2sp_final( blake2sp_state *S, byte *digest );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
129
deps/unrar/blake2s_sse.cpp
vendored
Normal file
129
deps/unrar/blake2s_sse.cpp
vendored
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
// Based on public domain code written in 2012 by Samuel Neves
|
||||||
|
|
||||||
|
extern const byte blake2s_sigma[10][16];
|
||||||
|
|
||||||
|
// Initialization vector.
|
||||||
|
static __m128i blake2s_IV_0_3, blake2s_IV_4_7;
|
||||||
|
|
||||||
|
#ifdef _WIN_64
|
||||||
|
// Constants for cyclic rotation. Used in 64-bit mode in mm_rotr_epi32 macro.
|
||||||
|
static __m128i crotr8, crotr16;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void blake2s_init_sse()
|
||||||
|
{
|
||||||
|
// We cannot initialize these 128 bit variables in place when declaring
|
||||||
|
// them globally, because global scope initialization is performed before
|
||||||
|
// our SSE check and it would make code incompatible with older non-SSE2
|
||||||
|
// CPUs. Also we cannot initialize them as static inside of function
|
||||||
|
// using these variables, because SSE static initialization is not thread
|
||||||
|
// safe: first thread starts initialization and sets "init done" flag even
|
||||||
|
// if it is not done yet, second thread can attempt to access half-init
|
||||||
|
// SSE data. So we moved init code here.
|
||||||
|
|
||||||
|
blake2s_IV_0_3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );
|
||||||
|
blake2s_IV_4_7 = _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 );
|
||||||
|
|
||||||
|
#ifdef _WIN_64
|
||||||
|
crotr8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 );
|
||||||
|
crotr16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
|
||||||
|
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
|
||||||
|
|
||||||
|
#ifdef _WIN_32
|
||||||
|
// 32-bit mode has less SSE2 registers and in MSVC2008 it is more efficient
|
||||||
|
// to not use _mm_shuffle_epi8 here.
|
||||||
|
#define mm_rotr_epi32(r, c) ( \
|
||||||
|
_mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
|
||||||
|
#else
|
||||||
|
#define mm_rotr_epi32(r, c) ( \
|
||||||
|
c==8 ? _mm_shuffle_epi8(r,crotr8) \
|
||||||
|
: c==16 ? _mm_shuffle_epi8(r,crotr16) \
|
||||||
|
: _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define G1(row1,row2,row3,row4,buf) \
|
||||||
|
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
|
||||||
|
row4 = _mm_xor_si128( row4, row1 ); \
|
||||||
|
row4 = mm_rotr_epi32(row4, 16); \
|
||||||
|
row3 = _mm_add_epi32( row3, row4 ); \
|
||||||
|
row2 = _mm_xor_si128( row2, row3 ); \
|
||||||
|
row2 = mm_rotr_epi32(row2, 12);
|
||||||
|
|
||||||
|
#define G2(row1,row2,row3,row4,buf) \
|
||||||
|
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
|
||||||
|
row4 = _mm_xor_si128( row4, row1 ); \
|
||||||
|
row4 = mm_rotr_epi32(row4, 8); \
|
||||||
|
row3 = _mm_add_epi32( row3, row4 ); \
|
||||||
|
row2 = _mm_xor_si128( row2, row3 ); \
|
||||||
|
row2 = mm_rotr_epi32(row2, 7);
|
||||||
|
|
||||||
|
#define DIAGONALIZE(row1,row2,row3,row4) \
|
||||||
|
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \
|
||||||
|
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
|
||||||
|
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) );
|
||||||
|
|
||||||
|
#define UNDIAGONALIZE(row1,row2,row3,row4) \
|
||||||
|
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \
|
||||||
|
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
|
||||||
|
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) );
|
||||||
|
|
||||||
|
#ifdef _WIN_64
|
||||||
|
// MSVC 2008 in x64 mode expands _mm_set_epi32 to store to stack and load
|
||||||
|
// from stack operations, which are slower than this code.
|
||||||
|
#define _mm_set_epi32(i3,i2,i1,i0) \
|
||||||
|
_mm_unpacklo_epi32(_mm_unpacklo_epi32(_mm_cvtsi32_si128(i0),_mm_cvtsi32_si128(i2)), \
|
||||||
|
_mm_unpacklo_epi32(_mm_cvtsi32_si128(i1),_mm_cvtsi32_si128(i3)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Original BLAKE2 SSE4.1 message loading code was a little slower in x86 mode
|
||||||
|
// and about the same in x64 mode in our test. Perhaps depends on compiler.
|
||||||
|
// We also tried _mm_i32gather_epi32 and _mm256_i32gather_epi32 AVX2 gather
|
||||||
|
// instructions here, but they did not show any speed gain on i7-6700K.
|
||||||
|
#define SSE_ROUND(m,row,r) \
|
||||||
|
{ \
|
||||||
|
__m128i buf; \
|
||||||
|
buf=_mm_set_epi32(m[blake2s_sigma[r][6]],m[blake2s_sigma[r][4]],m[blake2s_sigma[r][2]],m[blake2s_sigma[r][0]]); \
|
||||||
|
G1(row[0],row[1],row[2],row[3],buf); \
|
||||||
|
buf=_mm_set_epi32(m[blake2s_sigma[r][7]],m[blake2s_sigma[r][5]],m[blake2s_sigma[r][3]],m[blake2s_sigma[r][1]]); \
|
||||||
|
G2(row[0],row[1],row[2],row[3],buf); \
|
||||||
|
DIAGONALIZE(row[0],row[1],row[2],row[3]); \
|
||||||
|
buf=_mm_set_epi32(m[blake2s_sigma[r][14]],m[blake2s_sigma[r][12]],m[blake2s_sigma[r][10]],m[blake2s_sigma[r][8]]); \
|
||||||
|
G1(row[0],row[1],row[2],row[3],buf); \
|
||||||
|
buf=_mm_set_epi32(m[blake2s_sigma[r][15]],m[blake2s_sigma[r][13]],m[blake2s_sigma[r][11]],m[blake2s_sigma[r][9]]); \
|
||||||
|
G2(row[0],row[1],row[2],row[3],buf); \
|
||||||
|
UNDIAGONALIZE(row[0],row[1],row[2],row[3]); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int blake2s_compress_sse( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
|
||||||
|
{
|
||||||
|
__m128i row[4];
|
||||||
|
__m128i ff0, ff1;
|
||||||
|
|
||||||
|
const uint32 *m = ( uint32 * )block;
|
||||||
|
|
||||||
|
row[0] = ff0 = LOAD( &S->h[0] );
|
||||||
|
row[1] = ff1 = LOAD( &S->h[4] );
|
||||||
|
|
||||||
|
row[2] = blake2s_IV_0_3;
|
||||||
|
row[3] = _mm_xor_si128( blake2s_IV_4_7, LOAD( &S->t[0] ) );
|
||||||
|
SSE_ROUND( m, row, 0 );
|
||||||
|
SSE_ROUND( m, row, 1 );
|
||||||
|
SSE_ROUND( m, row, 2 );
|
||||||
|
SSE_ROUND( m, row, 3 );
|
||||||
|
SSE_ROUND( m, row, 4 );
|
||||||
|
SSE_ROUND( m, row, 5 );
|
||||||
|
SSE_ROUND( m, row, 6 );
|
||||||
|
SSE_ROUND( m, row, 7 );
|
||||||
|
SSE_ROUND( m, row, 8 );
|
||||||
|
SSE_ROUND( m, row, 9 );
|
||||||
|
STORE( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row[0], row[2] ) ) );
|
||||||
|
STORE( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row[1], row[3] ) ) );
|
||||||
|
return 0;
|
||||||
|
}
|
153
deps/unrar/blake2sp.cpp
vendored
Normal file
153
deps/unrar/blake2sp.cpp
vendored
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
BLAKE2 reference source code package - reference C implementations
|
||||||
|
|
||||||
|
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||||
|
|
||||||
|
To the extent possible under law, the author(s) have dedicated all copyright
|
||||||
|
and related and neighboring rights to this software to the public domain
|
||||||
|
worldwide. This software is distributed without any warranty.
|
||||||
|
|
||||||
|
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||||
|
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PARALLELISM_DEGREE 8
|
||||||
|
|
||||||
|
void blake2sp_init( blake2sp_state *S )
|
||||||
|
{
|
||||||
|
memset( S->buf, 0, sizeof( S->buf ) );
|
||||||
|
S->buflen = 0;
|
||||||
|
|
||||||
|
blake2s_init_param( &S->R, 0, 1 ); // Init root.
|
||||||
|
|
||||||
|
for( uint i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
|
blake2s_init_param( &S->S[i], i, 0 ); // Init leaf.
|
||||||
|
|
||||||
|
S->R.last_node = 1;
|
||||||
|
S->S[PARALLELISM_DEGREE - 1].last_node = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Blake2ThreadData
|
||||||
|
{
|
||||||
|
void Update();
|
||||||
|
blake2s_state *S;
|
||||||
|
const byte *in;
|
||||||
|
size_t inlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void Blake2ThreadData::Update()
|
||||||
|
{
|
||||||
|
size_t inlen__ = inlen;
|
||||||
|
const byte *in__ = ( const byte * )in;
|
||||||
|
|
||||||
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||||
|
{
|
||||||
|
#ifdef USE_SSE
|
||||||
|
// We gain 5% in i7 SSE mode by prefetching next data block.
|
||||||
|
if (_SSE_Version>=SSE_SSE && inlen__ >= 2 * PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES)
|
||||||
|
_mm_prefetch((char*)(in__ + PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES), _MM_HINT_T0);
|
||||||
|
#endif
|
||||||
|
blake2s_update( S, in__, BLAKE2S_BLOCKBYTES );
|
||||||
|
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
THREAD_PROC(Blake2Thread)
|
||||||
|
{
|
||||||
|
Blake2ThreadData *td=(Blake2ThreadData *)Data;
|
||||||
|
td->Update();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen )
|
||||||
|
{
|
||||||
|
size_t left = S->buflen;
|
||||||
|
size_t fill = sizeof( S->buf ) - left;
|
||||||
|
|
||||||
|
if( left && inlen >= fill )
|
||||||
|
{
|
||||||
|
memcpy( S->buf + left, in, fill );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
|
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
|
in += fill;
|
||||||
|
inlen -= fill;
|
||||||
|
left = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Blake2ThreadData btd_array[PARALLELISM_DEGREE];
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
uint ThreadNumber = inlen < 0x1000 ? 1 : S->MaxThreads;
|
||||||
|
|
||||||
|
if (ThreadNumber==6 || ThreadNumber==7) // 6 and 7 threads work slower than 4 here.
|
||||||
|
ThreadNumber=4;
|
||||||
|
#else
|
||||||
|
uint ThreadNumber=1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t id__=0;id__<PARALLELISM_DEGREE;)
|
||||||
|
{
|
||||||
|
for (uint Thread=0;Thread<ThreadNumber && id__<PARALLELISM_DEGREE;Thread++)
|
||||||
|
{
|
||||||
|
Blake2ThreadData *btd=btd_array+Thread;
|
||||||
|
|
||||||
|
btd->inlen = inlen;
|
||||||
|
btd->in = in + id__ * BLAKE2S_BLOCKBYTES;
|
||||||
|
btd->S = &S->S[id__];
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
if (ThreadNumber>1)
|
||||||
|
S->ThPool->AddTask(Blake2Thread,(void*)btd);
|
||||||
|
else
|
||||||
|
btd->Update();
|
||||||
|
#else
|
||||||
|
btd->Update();
|
||||||
|
#endif
|
||||||
|
id__++;
|
||||||
|
}
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
if (S->ThPool!=NULL) // Can be NULL in -mt1 mode.
|
||||||
|
S->ThPool->WaitDone();
|
||||||
|
#endif // RAR_SMP
|
||||||
|
}
|
||||||
|
|
||||||
|
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
|
||||||
|
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
|
|
||||||
|
if( inlen > 0 )
|
||||||
|
memcpy( S->buf + left, in, (size_t)inlen );
|
||||||
|
|
||||||
|
S->buflen = left + (size_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void blake2sp_final( blake2sp_state *S, byte *digest )
|
||||||
|
{
|
||||||
|
byte hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||||
|
|
||||||
|
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
|
{
|
||||||
|
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
|
||||||
|
{
|
||||||
|
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
|
||||||
|
|
||||||
|
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
||||||
|
|
||||||
|
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
||||||
|
}
|
||||||
|
|
||||||
|
blake2s_final( &S->S[i], hash[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
|
blake2s_update( &S->R, hash[i], BLAKE2S_OUTBYTES );
|
||||||
|
|
||||||
|
blake2s_final( &S->R, digest );
|
||||||
|
}
|
1082
deps/unrar/cmddata.cpp
vendored
Normal file
1082
deps/unrar/cmddata.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
70
deps/unrar/cmddata.hpp
vendored
Normal file
70
deps/unrar/cmddata.hpp
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef _RAR_CMDDATA_
|
||||||
|
#define _RAR_CMDDATA_
|
||||||
|
|
||||||
|
|
||||||
|
#define DefaultStoreList L"7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lz;lzh;mp3;rar;taz;tgz;xz;z;zip;zipx"
|
||||||
|
|
||||||
|
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
|
||||||
|
|
||||||
|
enum IS_PROCESS_FILE_FLAGS {IPFF_EXCLUDE_PARENT=1};
|
||||||
|
|
||||||
|
class CommandData:public RAROptions
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void ProcessSwitchesString(const wchar *Str);
|
||||||
|
void ProcessSwitch(const wchar *Switch);
|
||||||
|
void BadSwitch(const wchar *Switch);
|
||||||
|
uint GetExclAttr(const wchar *Str,bool &Dir);
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void SetTimeFilters(const wchar *Mod,bool Before,bool Age);
|
||||||
|
void SetStoreTimeMode(const wchar *S);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool FileLists;
|
||||||
|
bool NoMoreSwitches;
|
||||||
|
RAR_CMD_LIST_MODE ListMode;
|
||||||
|
bool BareOutput;
|
||||||
|
public:
|
||||||
|
CommandData();
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void ParseCommandLine(bool Preprocess,int argc, char *argv[]);
|
||||||
|
void ParseArg(wchar *ArgW);
|
||||||
|
void ParseDone();
|
||||||
|
void ParseEnvVar();
|
||||||
|
void ReadConfig();
|
||||||
|
void PreprocessArg(const wchar *Arg);
|
||||||
|
void OutTitle();
|
||||||
|
void OutHelp(RAR_EXIT ExitCode);
|
||||||
|
bool IsSwitch(int Ch);
|
||||||
|
bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
|
||||||
|
static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode);
|
||||||
|
bool ExclDirByAttr(uint FileAttr);
|
||||||
|
bool TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta);
|
||||||
|
bool SizeCheck(int64 Size);
|
||||||
|
bool AnyFiltersActive();
|
||||||
|
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
|
||||||
|
bool Flags,wchar *MatchedArg,uint MatchedArgSize);
|
||||||
|
void ProcessCommand();
|
||||||
|
void AddArcName(const wchar *Name);
|
||||||
|
bool GetArcName(wchar *Name,int MaxSize);
|
||||||
|
bool CheckWinSize();
|
||||||
|
|
||||||
|
int GetRecoverySize(const wchar *Str,int DefSize);
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
void ReportWrongSwitches(RARFORMAT Format);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wchar Command[NM+16];
|
||||||
|
|
||||||
|
wchar ArcName[NM];
|
||||||
|
|
||||||
|
StringList FileArgs;
|
||||||
|
StringList ExclArgs;
|
||||||
|
StringList InclArgs;
|
||||||
|
StringList ArcNames;
|
||||||
|
StringList StoreArgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
352
deps/unrar/cmdfilter.cpp
vendored
Normal file
352
deps/unrar/cmdfilter.cpp
vendored
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
// Return 'true' if we need to exclude the file from processing as result
|
||||||
|
// of -x switch. If CheckInclList is true, we also check the file against
|
||||||
|
// the include list created with -n switch.
|
||||||
|
bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList)
|
||||||
|
{
|
||||||
|
if (CheckArgs(&ExclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
|
||||||
|
return true;
|
||||||
|
if (!CheckInclList || InclArgs.ItemsCount()==0)
|
||||||
|
return false;
|
||||||
|
if (CheckArgs(&InclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode)
|
||||||
|
{
|
||||||
|
wchar *Name=ConvertPath(CheckName,NULL,0);
|
||||||
|
wchar FullName[NM];
|
||||||
|
wchar CurMask[NM];
|
||||||
|
*FullName=0;
|
||||||
|
Args->Rewind();
|
||||||
|
while (Args->GetString(CurMask,ASIZE(CurMask)))
|
||||||
|
{
|
||||||
|
wchar *LastMaskChar=PointToLastChar(CurMask);
|
||||||
|
bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only.
|
||||||
|
|
||||||
|
if (Dir)
|
||||||
|
{
|
||||||
|
// CheckName is a directory.
|
||||||
|
if (DirMask)
|
||||||
|
{
|
||||||
|
// We process the directory and have the directory exclusion mask.
|
||||||
|
// So let's convert "mask\" to "mask" and process it normally.
|
||||||
|
|
||||||
|
*LastMaskChar=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// REMOVED, we want -npath\* to match empty folders too.
|
||||||
|
// If mask has wildcards in name part and does not have the trailing
|
||||||
|
// '\' character, we cannot use it for directories.
|
||||||
|
|
||||||
|
// if (IsWildcard(PointToName(CurMask)))
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we process a file inside of directory excluded by "dirmask\".
|
||||||
|
// we want to exclude such file too. So we convert "dirmask\" to
|
||||||
|
// "dirmask\*". It is important for operations other than archiving
|
||||||
|
// with -x. When archiving with -x, directory matched by "dirmask\"
|
||||||
|
// is excluded from further scanning.
|
||||||
|
|
||||||
|
if (DirMask)
|
||||||
|
wcsncatz(CurMask,L"*",ASIZE(CurMask));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
if (CheckFullPath && IsFullPath(CurMask))
|
||||||
|
{
|
||||||
|
// We do not need to do the special "*\" processing here, because
|
||||||
|
// unlike the "else" part of this "if", now we convert names to full
|
||||||
|
// format, so they all include the path, which is matched by "*\"
|
||||||
|
// correctly. Moreover, removing "*\" from mask would break
|
||||||
|
// the comparison, because now all names have the path.
|
||||||
|
|
||||||
|
if (*FullName==0)
|
||||||
|
ConvertNameToFull(CheckName,FullName,ASIZE(FullName));
|
||||||
|
if (CmpName(CurMask,FullName,MatchMode))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
wchar NewName[NM+2],*CurName=Name;
|
||||||
|
|
||||||
|
// Important to convert before "*\" check below, so masks like
|
||||||
|
// d:*\something are processed properly.
|
||||||
|
wchar *CmpMask=ConvertPath(CurMask,NULL,0);
|
||||||
|
|
||||||
|
if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1]))
|
||||||
|
{
|
||||||
|
// We want "*\name" to match 'name' not only in subdirectories,
|
||||||
|
// but also in the current directory. We convert the name
|
||||||
|
// from 'name' to '.\name' to be matched by "*\" part even if it is
|
||||||
|
// in current directory.
|
||||||
|
NewName[0]='.';
|
||||||
|
NewName[1]=CPATHDIVIDER;
|
||||||
|
wcsncpyz(NewName+2,Name,ASIZE(NewName)-2);
|
||||||
|
CurName=NewName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CmpName(CmpMask,CurName,MatchMode))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
// Now this function performs only one task and only in Windows version:
|
||||||
|
// it skips symlinks to directories if -e1024 switch is specified.
|
||||||
|
// Symlinks are skipped in ScanTree class, so their entire contents
|
||||||
|
// is skipped too. Without this function we would check the attribute
|
||||||
|
// only directly before archiving, so we would skip the symlink record,
|
||||||
|
// but not the contents of symlinked directory.
|
||||||
|
bool CommandData::ExclDirByAttr(uint FileAttr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 &&
|
||||||
|
(ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void CommandData::SetTimeFilters(const wchar *Mod,bool Before,bool Age)
|
||||||
|
{
|
||||||
|
bool ModeOR=false,TimeMods=false;
|
||||||
|
const wchar *S=Mod;
|
||||||
|
// Check if any 'mca' modifiers are present, set OR mode if 'o' is present,
|
||||||
|
// skip modifiers and set S to beginning of time string. Be sure to check
|
||||||
|
// *S!=0, because termination 0 is a part of string for wcschr.
|
||||||
|
for (;*S!=0 && wcschr(L"MCAOmcao",*S)!=NULL;S++)
|
||||||
|
if (*S=='o' || *S=='O')
|
||||||
|
ModeOR=true;
|
||||||
|
else
|
||||||
|
TimeMods=true;
|
||||||
|
|
||||||
|
if (!TimeMods) // Assume 'm' if no modifiers are specified.
|
||||||
|
Mod=L"m";
|
||||||
|
|
||||||
|
// Set the specified time for every modifier. Be sure to check *Mod!=0,
|
||||||
|
// because termination 0 is a part of string for wcschr. This check is
|
||||||
|
// important when we set Mod to "m" above.
|
||||||
|
for (;*Mod!=0 && wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++)
|
||||||
|
switch(toupperw(*Mod))
|
||||||
|
{
|
||||||
|
case 'M':
|
||||||
|
if (Before)
|
||||||
|
{
|
||||||
|
Age ? FileMtimeBefore.SetAgeText(S):FileMtimeBefore.SetIsoText(S);
|
||||||
|
FileMtimeBeforeOR=ModeOR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Age ? FileMtimeAfter.SetAgeText(S):FileMtimeAfter.SetIsoText(S);
|
||||||
|
FileMtimeAfterOR=ModeOR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
if (Before)
|
||||||
|
{
|
||||||
|
Age ? FileCtimeBefore.SetAgeText(S):FileCtimeBefore.SetIsoText(S);
|
||||||
|
FileCtimeBeforeOR=ModeOR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Age ? FileCtimeAfter.SetAgeText(S):FileCtimeAfter.SetIsoText(S);
|
||||||
|
FileCtimeAfterOR=ModeOR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
if (Before)
|
||||||
|
{
|
||||||
|
Age ? FileAtimeBefore.SetAgeText(S):FileAtimeBefore.SetIsoText(S);
|
||||||
|
FileAtimeBeforeOR=ModeOR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Age ? FileAtimeAfter.SetAgeText(S):FileAtimeAfter.SetIsoText(S);
|
||||||
|
FileAtimeAfterOR=ModeOR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
// Return 'true' if we need to exclude the file from processing.
|
||||||
|
bool CommandData::TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta)
|
||||||
|
{
|
||||||
|
bool FilterOR=false;
|
||||||
|
|
||||||
|
if (FileMtimeBefore.IsSet()) // Filter present.
|
||||||
|
if (ftm>=FileMtimeBefore) // Condition not matched.
|
||||||
|
if (FileMtimeBeforeOR)
|
||||||
|
FilterOR=true; // Not matched OR filter is present.
|
||||||
|
else
|
||||||
|
return true; // Exclude file in AND mode.
|
||||||
|
else // Condition matched.
|
||||||
|
if (FileMtimeBeforeOR)
|
||||||
|
return false; // Include file in OR mode.
|
||||||
|
|
||||||
|
if (FileMtimeAfter.IsSet()) // Filter present.
|
||||||
|
if (ftm<FileMtimeAfter) // Condition not matched.
|
||||||
|
if (FileMtimeAfterOR)
|
||||||
|
FilterOR=true; // Not matched OR filter is present.
|
||||||
|
else
|
||||||
|
return true; // Exclude file in AND mode.
|
||||||
|
else // Condition matched.
|
||||||
|
if (FileMtimeAfterOR)
|
||||||
|
return false; // Include file in OR mode.
|
||||||
|
|
||||||
|
if (FileCtimeBefore.IsSet()) // Filter present.
|
||||||
|
if (ftc>=FileCtimeBefore) // Condition not matched.
|
||||||
|
if (FileCtimeBeforeOR)
|
||||||
|
FilterOR=true; // Not matched OR filter is present.
|
||||||
|
else
|
||||||
|
return true; // Exclude file in AND mode.
|
||||||
|
else // Condition matched.
|
||||||
|
if (FileCtimeBeforeOR)
|
||||||
|
return false; // Include file in OR mode.
|
||||||
|
|
||||||
|
if (FileCtimeAfter.IsSet()) // Filter present.
|
||||||
|
if (ftc<FileCtimeAfter) // Condition not matched.
|
||||||
|
if (FileCtimeAfterOR)
|
||||||
|
FilterOR=true; // Not matched OR filter is present.
|
||||||
|
else
|
||||||
|
return true; // Exclude file in AND mode.
|
||||||
|
else // Condition matched.
|
||||||
|
if (FileCtimeAfterOR)
|
||||||
|
return false; // Include file in OR mode.
|
||||||
|
|
||||||
|
if (FileAtimeBefore.IsSet()) // Filter present.
|
||||||
|
if (fta>=FileAtimeBefore) // Condition not matched.
|
||||||
|
if (FileAtimeBeforeOR)
|
||||||
|
FilterOR=true; // Not matched OR filter is present.
|
||||||
|
else
|
||||||
|
return true; // Exclude file in AND mode.
|
||||||
|
else // Condition matched.
|
||||||
|
if (FileAtimeBeforeOR)
|
||||||
|
return false; // Include file in OR mode.
|
||||||
|
|
||||||
|
if (FileAtimeAfter.IsSet()) // Filter present.
|
||||||
|
if (fta<FileAtimeAfter) // Condition not matched.
|
||||||
|
if (FileAtimeAfterOR)
|
||||||
|
FilterOR=true; // Not matched OR filter is present.
|
||||||
|
else
|
||||||
|
return true; // Exclude file in AND mode.
|
||||||
|
else // Condition matched.
|
||||||
|
if (FileAtimeAfterOR)
|
||||||
|
return false; // Include file in OR mode.
|
||||||
|
|
||||||
|
return FilterOR; // Exclude if all OR filters are not matched.
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
// Return 'true' if we need to exclude the file from processing.
|
||||||
|
bool CommandData::SizeCheck(int64 Size)
|
||||||
|
{
|
||||||
|
if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
|
||||||
|
return true;
|
||||||
|
if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Return 0 if file must not be processed or a number of matched parameter otherwise.
|
||||||
|
int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
|
||||||
|
bool Flags,wchar *MatchedArg,uint MatchedArgSize)
|
||||||
|
{
|
||||||
|
if (MatchedArg!=NULL && MatchedArgSize>0)
|
||||||
|
*MatchedArg=0;
|
||||||
|
bool Dir=FileHead.Dir;
|
||||||
|
if (ExclCheck(FileHead.FileName,Dir,false,true))
|
||||||
|
return 0;
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
if (TimeCheck(FileHead.mtime,FileHead.ctime,FileHead.atime))
|
||||||
|
return 0;
|
||||||
|
if ((FileHead.FileAttr & ExclFileAttr)!=0 || FileHead.Dir && ExclDir)
|
||||||
|
return 0;
|
||||||
|
if (InclAttrSet && (!FileHead.Dir && (FileHead.FileAttr & InclFileAttr)==0 ||
|
||||||
|
FileHead.Dir && !InclDir))
|
||||||
|
return 0;
|
||||||
|
if (!Dir && SizeCheck(FileHead.UnpSize))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
wchar *ArgName;
|
||||||
|
FileArgs.Rewind();
|
||||||
|
for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++)
|
||||||
|
if (CmpName(ArgName,FileHead.FileName,MatchType))
|
||||||
|
{
|
||||||
|
if (ExactMatch!=NULL)
|
||||||
|
*ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0;
|
||||||
|
if (MatchedArg!=NULL)
|
||||||
|
wcsncpyz(MatchedArg,ArgName,MatchedArgSize);
|
||||||
|
return StringCount;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void CommandData::SetStoreTimeMode(const wchar *S)
|
||||||
|
{
|
||||||
|
if (*S==0 || IsDigit(*S) || *S=='-' || *S=='+')
|
||||||
|
{
|
||||||
|
// Apply -ts, -ts1, -ts-, -ts+ to all 3 times.
|
||||||
|
// Handle obsolete -ts[2,3,4] as ts+.
|
||||||
|
EXTTIME_MODE Mode=EXTTIME_MAX;
|
||||||
|
if (*S=='-')
|
||||||
|
Mode=EXTTIME_NONE;
|
||||||
|
if (*S=='1')
|
||||||
|
Mode=EXTTIME_1S;
|
||||||
|
xmtime=xctime=xatime=Mode;
|
||||||
|
S++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*S!=0)
|
||||||
|
{
|
||||||
|
EXTTIME_MODE Mode=EXTTIME_MAX;
|
||||||
|
if (S[1]=='-')
|
||||||
|
Mode=EXTTIME_NONE;
|
||||||
|
if (S[1]=='1')
|
||||||
|
Mode=EXTTIME_1S;
|
||||||
|
switch(toupperw(*S))
|
||||||
|
{
|
||||||
|
case 'M':
|
||||||
|
xmtime=Mode;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
xctime=Mode;
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
xatime=Mode;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
PreserveAtime=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
S++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
118
deps/unrar/cmdmix.cpp
vendored
Normal file
118
deps/unrar/cmdmix.cpp
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
void CommandData::OutTitle()
|
||||||
|
{
|
||||||
|
if (BareOutput || DisableCopyright)
|
||||||
|
return;
|
||||||
|
#if defined(__GNUC__) && defined(SFX_MODULE)
|
||||||
|
mprintf(St(MCopyrightS));
|
||||||
|
#else
|
||||||
|
#ifndef SILENT
|
||||||
|
static bool TitleShown=false;
|
||||||
|
if (TitleShown)
|
||||||
|
return;
|
||||||
|
TitleShown=true;
|
||||||
|
|
||||||
|
wchar Version[80];
|
||||||
|
if (RARVER_BETA!=0)
|
||||||
|
swprintf(Version,ASIZE(Version),L"%d.%02d %ls %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA);
|
||||||
|
else
|
||||||
|
swprintf(Version,ASIZE(Version),L"%d.%02d",RARVER_MAJOR,RARVER_MINOR);
|
||||||
|
#if defined(_WIN_32) || defined(_WIN_64)
|
||||||
|
wcsncatz(Version,L" ",ASIZE(Version));
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN_32
|
||||||
|
wcsncatz(Version,St(Mx86),ASIZE(Version));
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN_64
|
||||||
|
wcsncatz(Version,St(Mx64),ASIZE(Version));
|
||||||
|
#endif
|
||||||
|
if (PrintVersion)
|
||||||
|
{
|
||||||
|
mprintf(L"%s",Version);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
mprintf(St(MUCopyright),Version,RARVER_YEAR);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool CmpMSGID(MSGID i1,MSGID i2)
|
||||||
|
{
|
||||||
|
#ifdef MSGID_INT
|
||||||
|
return i1==i2;
|
||||||
|
#else
|
||||||
|
// If MSGID is const char*, we cannot compare pointers only.
|
||||||
|
// Pointers to different instances of same string can differ,
|
||||||
|
// so we need to compare complete strings.
|
||||||
|
return wcscmp(i1,i2)==0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandData::OutHelp(RAR_EXIT ExitCode)
|
||||||
|
{
|
||||||
|
#if !defined(SILENT)
|
||||||
|
OutTitle();
|
||||||
|
static MSGID Help[]={
|
||||||
|
#ifdef SFX_MODULE
|
||||||
|
// Console SFX switches definition.
|
||||||
|
MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV
|
||||||
|
#else
|
||||||
|
// UnRAR switches definition.
|
||||||
|
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
|
||||||
|
MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,
|
||||||
|
MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP,
|
||||||
|
MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
|
||||||
|
MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
|
||||||
|
MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,
|
||||||
|
MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
|
||||||
|
MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM,
|
||||||
|
MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,
|
||||||
|
MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,
|
||||||
|
MCHelpSwY
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint I=0;I<ASIZE(Help);I++)
|
||||||
|
{
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
if (CmpMSGID(Help[I],MCHelpSwV))
|
||||||
|
continue;
|
||||||
|
#ifndef _WIN_ALL
|
||||||
|
static MSGID Win32Only[]={
|
||||||
|
MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
|
||||||
|
MCHelpSwEP2,MCHelpSwOC,MCHelpSwONI,MCHelpSwDR,MCHelpSwRI
|
||||||
|
};
|
||||||
|
bool Found=false;
|
||||||
|
for (uint J=0;J<ASIZE(Win32Only);J++)
|
||||||
|
if (CmpMSGID(Help[I],Win32Only[J]))
|
||||||
|
{
|
||||||
|
Found=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (Found)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
#if !defined(_UNIX) && !defined(_WIN_ALL)
|
||||||
|
if (CmpMSGID(Help[I],MCHelpSwOW))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
#if !defined(_WIN_ALL) && !defined(_EMX)
|
||||||
|
if (CmpMSGID(Help[I],MCHelpSwAC))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
#ifndef SAVE_LINKS
|
||||||
|
if (CmpMSGID(Help[I],MCHelpSwOL))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
#ifndef RAR_SMP
|
||||||
|
if (CmpMSGID(Help[I],MCHelpSwMT))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
mprintf(St(Help[I]));
|
||||||
|
}
|
||||||
|
mprintf(L"\n");
|
||||||
|
ErrHandler.Exit(ExitCode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
48
deps/unrar/coder.cpp
vendored
Normal file
48
deps/unrar/coder.cpp
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
|
||||||
|
inline unsigned int RangeCoder::GetChar()
|
||||||
|
{
|
||||||
|
return(UnpackRead->GetChar());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RangeCoder::InitDecoder(Unpack *UnpackRead)
|
||||||
|
{
|
||||||
|
RangeCoder::UnpackRead=UnpackRead;
|
||||||
|
|
||||||
|
low=code=0;
|
||||||
|
range=uint(-1);
|
||||||
|
for (int i=0;i < 4;i++)
|
||||||
|
code=(code << 8) | GetChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// (int) cast before "low" added only to suppress compiler warnings.
|
||||||
|
#define ARI_DEC_NORMALIZE(code,low,range,read) \
|
||||||
|
{ \
|
||||||
|
while ((low^(low+range))<TOP || range<BOT && ((range=-(int)low&(BOT-1)),1)) \
|
||||||
|
{ \
|
||||||
|
code=(code << 8) | read->GetChar(); \
|
||||||
|
range <<= 8; \
|
||||||
|
low <<= 8; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline int RangeCoder::GetCurrentCount()
|
||||||
|
{
|
||||||
|
return (code-low)/(range /= SubRange.scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint RangeCoder::GetCurrentShiftCount(uint SHIFT)
|
||||||
|
{
|
||||||
|
return (code-low)/(range >>= SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RangeCoder::Decode()
|
||||||
|
{
|
||||||
|
low += range*SubRange.LowCount;
|
||||||
|
range *= SubRange.HighCount-SubRange.LowCount;
|
||||||
|
}
|
23
deps/unrar/coder.hpp
vendored
Normal file
23
deps/unrar/coder.hpp
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
class RangeCoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void InitDecoder(Unpack *UnpackRead);
|
||||||
|
inline int GetCurrentCount();
|
||||||
|
inline uint GetCurrentShiftCount(uint SHIFT);
|
||||||
|
inline void Decode();
|
||||||
|
inline void PutChar(unsigned int c);
|
||||||
|
inline unsigned int GetChar();
|
||||||
|
|
||||||
|
uint low, code, range;
|
||||||
|
struct SUBRANGE
|
||||||
|
{
|
||||||
|
uint LowCount, HighCount, scale;
|
||||||
|
} SubRange;
|
||||||
|
|
||||||
|
Unpack *UnpackRead;
|
||||||
|
};
|
59
deps/unrar/compress.hpp
vendored
Normal file
59
deps/unrar/compress.hpp
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#ifndef _RAR_COMPRESS_
|
||||||
|
#define _RAR_COMPRESS_
|
||||||
|
|
||||||
|
// Combine pack and unpack constants to class to avoid polluting global
|
||||||
|
// namespace with numerous short names.
|
||||||
|
class PackDef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Maximum LZ match length we can encode even for short distances.
|
||||||
|
static const uint MAX_LZ_MATCH = 0x1001;
|
||||||
|
|
||||||
|
// We increment LZ match length for longer distances, because shortest
|
||||||
|
// matches are not allowed for them. Maximum length increment is 3
|
||||||
|
// for distances larger than 256KB (0x40000). Here we define the maximum
|
||||||
|
// incremented LZ match. Normally packer does not use it, but we must be
|
||||||
|
// ready to process it in corrupt archives.
|
||||||
|
static const uint MAX_INC_LZ_MATCH = MAX_LZ_MATCH + 3;
|
||||||
|
|
||||||
|
static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
|
||||||
|
static const uint LOW_DIST_REP_COUNT = 16;
|
||||||
|
|
||||||
|
static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||||
|
static const uint DC = 64;
|
||||||
|
static const uint LDC = 16;
|
||||||
|
static const uint RC = 44;
|
||||||
|
static const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
|
||||||
|
static const uint BC = 20;
|
||||||
|
|
||||||
|
static const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||||
|
static const uint DC30 = 60;
|
||||||
|
static const uint LDC30 = 17;
|
||||||
|
static const uint RC30 = 28;
|
||||||
|
static const uint BC30 = 20;
|
||||||
|
static const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
|
||||||
|
|
||||||
|
static const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||||
|
static const uint DC20 = 48;
|
||||||
|
static const uint RC20 = 28;
|
||||||
|
static const uint BC20 = 19;
|
||||||
|
static const uint MC20 = 257;
|
||||||
|
|
||||||
|
// Largest alphabet size among all values listed above.
|
||||||
|
static const uint LARGEST_TABLE_SIZE = 306;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
|
||||||
|
CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum FilterType {
|
||||||
|
// These values must not be changed, because we use them directly
|
||||||
|
// in RAR5 compression and decompression code.
|
||||||
|
FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
|
||||||
|
FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
357
deps/unrar/consio.cpp
vendored
Normal file
357
deps/unrar/consio.cpp
vendored
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
#include "log.cpp"
|
||||||
|
|
||||||
|
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
|
||||||
|
static RAR_CHARSET RedirectCharset=RCH_DEFAULT;
|
||||||
|
|
||||||
|
const int MaxMsgSize=2*NM+2048;
|
||||||
|
|
||||||
|
static bool StdoutRedirected=false,StderrRedirected=false,StdinRedirected=false;
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
static bool IsRedirected(DWORD nStdHandle)
|
||||||
|
{
|
||||||
|
HANDLE hStd=GetStdHandle(nStdHandle);
|
||||||
|
DWORD Mode;
|
||||||
|
return GetFileType(hStd)!=FILE_TYPE_CHAR || GetConsoleMode(hStd,&Mode)==0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void InitConsole()
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// We want messages like file names or progress percent to be printed
|
||||||
|
// immediately. Use only in Windows, in Unix they can cause wprintf %ls
|
||||||
|
// to fail with non-English strings.
|
||||||
|
setbuf(stdout,NULL);
|
||||||
|
setbuf(stderr,NULL);
|
||||||
|
|
||||||
|
// Detect if output is redirected and set output mode properly.
|
||||||
|
// We do not want to send Unicode output to files and especially to pipes
|
||||||
|
// like '|more', which cannot handle them correctly in Windows.
|
||||||
|
// In Unix console output is UTF-8 and it is handled correctly
|
||||||
|
// when redirecting, so no need to perform any adjustments.
|
||||||
|
StdoutRedirected=IsRedirected(STD_OUTPUT_HANDLE);
|
||||||
|
StderrRedirected=IsRedirected(STD_ERROR_HANDLE);
|
||||||
|
StdinRedirected=IsRedirected(STD_INPUT_HANDLE);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
if (!StdoutRedirected)
|
||||||
|
_setmode(_fileno(stdout), _O_U16TEXT);
|
||||||
|
if (!StderrRedirected)
|
||||||
|
_setmode(_fileno(stderr), _O_U16TEXT);
|
||||||
|
#endif
|
||||||
|
#elif defined(_UNIX)
|
||||||
|
StdoutRedirected=!isatty(fileno(stdout));
|
||||||
|
StderrRedirected=!isatty(fileno(stderr));
|
||||||
|
StdinRedirected=!isatty(fileno(stdin));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream)
|
||||||
|
{
|
||||||
|
::MsgStream=MsgStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset)
|
||||||
|
{
|
||||||
|
::RedirectCharset=RedirectCharset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist)
|
||||||
|
{
|
||||||
|
// This buffer is for format string only, not for entire output,
|
||||||
|
// so it can be short enough.
|
||||||
|
wchar fmtw[1024];
|
||||||
|
PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
safebuf wchar Msg[MaxMsgSize];
|
||||||
|
if (dest==stdout && StdoutRedirected || dest==stderr && StderrRedirected)
|
||||||
|
{
|
||||||
|
HANDLE hOut=GetStdHandle(dest==stdout ? STD_OUTPUT_HANDLE:STD_ERROR_HANDLE);
|
||||||
|
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
|
||||||
|
DWORD Written;
|
||||||
|
if (RedirectCharset==RCH_UNICODE)
|
||||||
|
WriteFile(hOut,Msg,(DWORD)wcslen(Msg)*sizeof(*Msg),&Written,NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Avoid Unicode for redirect in Windows, it does not work with pipes.
|
||||||
|
safebuf char MsgA[MaxMsgSize];
|
||||||
|
if (RedirectCharset==RCH_UTF8)
|
||||||
|
WideToUtf(Msg,MsgA,ASIZE(MsgA));
|
||||||
|
else
|
||||||
|
WideToChar(Msg,MsgA,ASIZE(MsgA));
|
||||||
|
if (RedirectCharset==RCH_DEFAULT || RedirectCharset==RCH_OEM)
|
||||||
|
CharToOemA(MsgA,MsgA); // Console tools like 'more' expect OEM encoding.
|
||||||
|
|
||||||
|
// We already converted \n to \r\n above, so we use WriteFile instead
|
||||||
|
// of C library to avoid unnecessary additional conversion.
|
||||||
|
WriteFile(hOut,MsgA,(DWORD)strlen(MsgA),&Written,NULL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// MSVC2008 vfwprintf writes every character to console separately
|
||||||
|
// and it is too slow. We use direct WriteConsole call instead.
|
||||||
|
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
|
||||||
|
HANDLE hOut=GetStdHandle(dest==stderr ? STD_ERROR_HANDLE:STD_OUTPUT_HANDLE);
|
||||||
|
DWORD Written;
|
||||||
|
WriteConsole(hOut,Msg,(DWORD)wcslen(Msg),&Written,NULL);
|
||||||
|
#else
|
||||||
|
vfwprintf(dest,fmtw,arglist);
|
||||||
|
// We do not use setbuf(NULL) in Unix (see comments in InitConsole).
|
||||||
|
fflush(dest);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mprintf(const wchar *fmt,...)
|
||||||
|
{
|
||||||
|
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fflush(stderr); // Ensure proper message order.
|
||||||
|
|
||||||
|
va_list arglist;
|
||||||
|
va_start(arglist,fmt);
|
||||||
|
FILE *dest=MsgStream==MSG_STDERR ? stderr:stdout;
|
||||||
|
cvt_wprintf(dest,fmt,arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
void eprintf(const wchar *fmt,...)
|
||||||
|
{
|
||||||
|
if (MsgStream==MSG_NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fflush(stdout); // Ensure proper message order.
|
||||||
|
|
||||||
|
va_list arglist;
|
||||||
|
va_start(arglist,fmt);
|
||||||
|
cvt_wprintf(stderr,fmt,arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
static void GetPasswordText(wchar *Str,uint MaxLength)
|
||||||
|
{
|
||||||
|
if (MaxLength==0)
|
||||||
|
return;
|
||||||
|
if (StdinRedirected)
|
||||||
|
getwstr(Str,MaxLength); // Read from pipe or redirected file.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
DWORD ConInMode,ConOutMode;
|
||||||
|
DWORD Read=0;
|
||||||
|
GetConsoleMode(hConIn,&ConInMode);
|
||||||
|
GetConsoleMode(hConOut,&ConOutMode);
|
||||||
|
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
|
||||||
|
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
|
||||||
|
|
||||||
|
ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL);
|
||||||
|
Str[Read]=0;
|
||||||
|
SetConsoleMode(hConIn,ConInMode);
|
||||||
|
SetConsoleMode(hConOut,ConOutMode);
|
||||||
|
#else
|
||||||
|
char StrA[MAXPASSWORD];
|
||||||
|
#if defined(_EMX) || defined (__VMS)
|
||||||
|
fgets(StrA,ASIZE(StrA)-1,stdin);
|
||||||
|
#elif defined(__sun)
|
||||||
|
strncpyz(StrA,getpassphrase(""),ASIZE(StrA));
|
||||||
|
#else
|
||||||
|
strncpyz(StrA,getpass(""),ASIZE(StrA));
|
||||||
|
#endif
|
||||||
|
CharToWide(StrA,Str,MaxLength);
|
||||||
|
cleandata(StrA,sizeof(StrA));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
Str[MaxLength-1]=0;
|
||||||
|
RemoveLF(Str);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
|
||||||
|
{
|
||||||
|
if (!StdinRedirected)
|
||||||
|
uiAlarm(UIALARM_QUESTION);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!StdinRedirected)
|
||||||
|
if (Type==UIPASSWORD_GLOBAL)
|
||||||
|
eprintf(L"\n%s: ",St(MAskPsw));
|
||||||
|
else
|
||||||
|
eprintf(St(MAskPswFor),FileName);
|
||||||
|
|
||||||
|
wchar PlainPsw[MAXPASSWORD];
|
||||||
|
GetPasswordText(PlainPsw,ASIZE(PlainPsw));
|
||||||
|
if (*PlainPsw==0 && Type==UIPASSWORD_GLOBAL)
|
||||||
|
return false;
|
||||||
|
if (!StdinRedirected && Type==UIPASSWORD_GLOBAL)
|
||||||
|
{
|
||||||
|
eprintf(St(MReAskPsw));
|
||||||
|
wchar CmpStr[MAXPASSWORD];
|
||||||
|
GetPasswordText(CmpStr,ASIZE(CmpStr));
|
||||||
|
if (*CmpStr==0 || wcscmp(PlainPsw,CmpStr)!=0)
|
||||||
|
{
|
||||||
|
eprintf(St(MNotMatchPsw));
|
||||||
|
cleandata(PlainPsw,sizeof(PlainPsw));
|
||||||
|
cleandata(CmpStr,sizeof(CmpStr));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cleandata(CmpStr,sizeof(CmpStr));
|
||||||
|
}
|
||||||
|
Password->Set(PlainPsw);
|
||||||
|
cleandata(PlainPsw,sizeof(PlainPsw));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
bool getwstr(wchar *str,size_t n)
|
||||||
|
{
|
||||||
|
// Print buffered prompt title function before waiting for input.
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
*str=0;
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
// fgetws does not work well with non-English text in Windows,
|
||||||
|
// so we do not use it.
|
||||||
|
if (StdinRedirected) // ReadConsole does not work if redirected.
|
||||||
|
{
|
||||||
|
// fgets does not work well with pipes in Windows in our test.
|
||||||
|
// Let's use files.
|
||||||
|
Array<char> StrA(n*4); // Up to 4 UTF-8 characters per wchar_t.
|
||||||
|
File SrcFile;
|
||||||
|
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||||
|
int ReadSize=SrcFile.Read(&StrA[0],StrA.Size()-1);
|
||||||
|
if (ReadSize<=0)
|
||||||
|
{
|
||||||
|
// Looks like stdin is a null device. We can enter to infinite loop
|
||||||
|
// calling Ask(), so let's better exit.
|
||||||
|
ErrHandler.Exit(RARX_USERBREAK);
|
||||||
|
}
|
||||||
|
StrA[ReadSize]=0;
|
||||||
|
CharToWide(&StrA[0],str,n);
|
||||||
|
cleandata(&StrA[0],StrA.Size()); // We can use this function to enter passwords.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWORD ReadSize=0;
|
||||||
|
if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),str,DWORD(n-1),&ReadSize,NULL)==0)
|
||||||
|
return false;
|
||||||
|
str[ReadSize]=0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (fgetws(str,n,stdin)==NULL)
|
||||||
|
ErrHandler.Exit(RARX_USERBREAK); // Avoid infinite Ask() loop.
|
||||||
|
#endif
|
||||||
|
RemoveLF(str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
// We allow this function to return 0 in case of invalid input,
|
||||||
|
// because it might be convenient to press Enter to some not dangerous
|
||||||
|
// prompts like "insert disk with next volume". We should call this function
|
||||||
|
// again in case of 0 in dangerous prompt such as overwriting file.
|
||||||
|
int Ask(const wchar *AskStr)
|
||||||
|
{
|
||||||
|
uiAlarm(UIALARM_QUESTION);
|
||||||
|
|
||||||
|
const int MaxItems=10;
|
||||||
|
wchar Item[MaxItems][40];
|
||||||
|
int ItemKeyPos[MaxItems],NumItems=0;
|
||||||
|
|
||||||
|
for (const wchar *NextItem=AskStr;NextItem!=NULL;NextItem=wcschr(NextItem+1,'_'))
|
||||||
|
{
|
||||||
|
wchar *CurItem=Item[NumItems];
|
||||||
|
wcsncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
|
||||||
|
wchar *EndItem=wcschr(CurItem,'_');
|
||||||
|
if (EndItem!=NULL)
|
||||||
|
*EndItem=0;
|
||||||
|
int KeyPos=0,CurKey;
|
||||||
|
while ((CurKey=CurItem[KeyPos])!=0)
|
||||||
|
{
|
||||||
|
bool Found=false;
|
||||||
|
for (int I=0;I<NumItems && !Found;I++)
|
||||||
|
if (toupperw(Item[I][ItemKeyPos[I]])==toupperw(CurKey))
|
||||||
|
Found=true;
|
||||||
|
if (!Found && CurKey!=' ')
|
||||||
|
break;
|
||||||
|
KeyPos++;
|
||||||
|
}
|
||||||
|
ItemKeyPos[NumItems]=KeyPos;
|
||||||
|
NumItems++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int I=0;I<NumItems;I++)
|
||||||
|
{
|
||||||
|
eprintf(I==0 ? (NumItems>4 ? L"\n":L" "):L", ");
|
||||||
|
int KeyPos=ItemKeyPos[I];
|
||||||
|
for (int J=0;J<KeyPos;J++)
|
||||||
|
eprintf(L"%c",Item[I][J]);
|
||||||
|
eprintf(L"[%c]%ls",Item[I][KeyPos],&Item[I][KeyPos+1]);
|
||||||
|
}
|
||||||
|
eprintf(L" ");
|
||||||
|
wchar Str[50];
|
||||||
|
getwstr(Str,ASIZE(Str));
|
||||||
|
wchar Ch=toupperw(Str[0]);
|
||||||
|
for (int I=0;I<NumItems;I++)
|
||||||
|
if (Ch==Item[I][ItemKeyPos[I]])
|
||||||
|
return I+1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static bool IsCommentUnsafe(const wchar *Data,size_t Size)
|
||||||
|
{
|
||||||
|
for (size_t I=0;I<Size;I++)
|
||||||
|
if (Data[I]==27 && Data[I+1]=='[')
|
||||||
|
for (size_t J=I+2;J<Size;J++)
|
||||||
|
{
|
||||||
|
// Return true for <ESC>[{key};"{string}"p used to redefine
|
||||||
|
// a keyboard key on some terminals.
|
||||||
|
if (Data[J]=='\"')
|
||||||
|
return true;
|
||||||
|
if (!IsDigit(Data[J]) && Data[J]!=';')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OutComment(const wchar *Comment,size_t Size)
|
||||||
|
{
|
||||||
|
if (IsCommentUnsafe(Comment,Size))
|
||||||
|
return;
|
||||||
|
const size_t MaxOutSize=0x400;
|
||||||
|
for (size_t I=0;I<Size;I+=MaxOutSize)
|
||||||
|
{
|
||||||
|
wchar Msg[MaxOutSize+1];
|
||||||
|
size_t CopySize=Min(MaxOutSize,Size-I);
|
||||||
|
wcsncpy(Msg,Comment+I,CopySize);
|
||||||
|
Msg[CopySize]=0;
|
||||||
|
mprintf(L"%s",Msg);
|
||||||
|
}
|
||||||
|
mprintf(L"\n");
|
||||||
|
}
|
27
deps/unrar/consio.hpp
vendored
Normal file
27
deps/unrar/consio.hpp
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _RAR_CONSIO_
|
||||||
|
#define _RAR_CONSIO_
|
||||||
|
|
||||||
|
void InitConsole();
|
||||||
|
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream);
|
||||||
|
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset);
|
||||||
|
void OutComment(const wchar *Comment,size_t Size);
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SILENT
|
||||||
|
inline void mprintf(const wchar *fmt,...) {}
|
||||||
|
inline void eprintf(const wchar *fmt,...) {}
|
||||||
|
inline void Alarm() {}
|
||||||
|
inline int Ask(const wchar *AskStr) {return 0;}
|
||||||
|
inline bool getwstr(wchar *str,size_t n) {return false;}
|
||||||
|
#else
|
||||||
|
void mprintf(const wchar *fmt,...);
|
||||||
|
void eprintf(const wchar *fmt,...);
|
||||||
|
void Alarm();
|
||||||
|
int Ask(const wchar *AskStr);
|
||||||
|
bool getwstr(wchar *str,size_t n);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
102
deps/unrar/crc.cpp
vendored
Normal file
102
deps/unrar/crc.cpp
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// This CRC function is based on Intel Slicing-by-8 algorithm.
|
||||||
|
//
|
||||||
|
// Original Intel Slicing-by-8 code is available here:
|
||||||
|
//
|
||||||
|
// http://sourceforge.net/projects/slicing-by-8/
|
||||||
|
//
|
||||||
|
// Original Intel Slicing-by-8 code is licensed as:
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
|
||||||
|
//
|
||||||
|
// This software program is licensed subject to the BSD License,
|
||||||
|
// available at http://www.opensource.org/licenses/bsd-license.html
|
||||||
|
|
||||||
|
|
||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
|
||||||
|
|
||||||
|
|
||||||
|
// Build the classic CRC32 lookup table.
|
||||||
|
// We also provide this function to legacy RAR and ZIP decryption code.
|
||||||
|
void InitCRC32(uint *CRCTab)
|
||||||
|
{
|
||||||
|
if (CRCTab[1]!=0)
|
||||||
|
return;
|
||||||
|
for (uint I=0;I<256;I++)
|
||||||
|
{
|
||||||
|
uint C=I;
|
||||||
|
for (uint J=0;J<8;J++)
|
||||||
|
C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
|
||||||
|
CRCTab[I]=C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void InitTables()
|
||||||
|
{
|
||||||
|
InitCRC32(crc_tables[0]);
|
||||||
|
|
||||||
|
for (uint I=0;I<256;I++) // Build additional lookup tables.
|
||||||
|
{
|
||||||
|
uint C=crc_tables[0][I];
|
||||||
|
for (uint J=1;J<8;J++)
|
||||||
|
{
|
||||||
|
C=crc_tables[0][(byte)C]^(C>>8);
|
||||||
|
crc_tables[J][I]=C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32;
|
||||||
|
|
||||||
|
uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
||||||
|
{
|
||||||
|
byte *Data=(byte *)Addr;
|
||||||
|
|
||||||
|
// Align Data to 8 for better performance.
|
||||||
|
for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
|
||||||
|
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||||
|
|
||||||
|
for (;Size>=8;Size-=8,Data+=8)
|
||||||
|
{
|
||||||
|
#ifdef BIG_ENDIAN
|
||||||
|
StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
|
||||||
|
uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
|
||||||
|
#else
|
||||||
|
StartCRC ^= *(uint32 *) Data;
|
||||||
|
uint NextData = *(uint32 *) (Data+4);
|
||||||
|
#endif
|
||||||
|
StartCRC = crc_tables[7][(byte) StartCRC ] ^
|
||||||
|
crc_tables[6][(byte)(StartCRC >> 8) ] ^
|
||||||
|
crc_tables[5][(byte)(StartCRC >> 16)] ^
|
||||||
|
crc_tables[4][(byte)(StartCRC >> 24)] ^
|
||||||
|
crc_tables[3][(byte) NextData ] ^
|
||||||
|
crc_tables[2][(byte)(NextData >> 8) ] ^
|
||||||
|
crc_tables[1][(byte)(NextData >> 16)] ^
|
||||||
|
crc_tables[0][(byte)(NextData >> 24)];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;Size>0;Size--,Data++) // Process left data.
|
||||||
|
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||||
|
|
||||||
|
return StartCRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
// For RAR 1.4 archives in case somebody still has them.
|
||||||
|
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
|
||||||
|
{
|
||||||
|
byte *Data=(byte *)Addr;
|
||||||
|
for (size_t I=0;I<Size;I++)
|
||||||
|
{
|
||||||
|
StartCRC=(StartCRC+Data[I])&0xffff;
|
||||||
|
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
|
||||||
|
}
|
||||||
|
return StartCRC;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
15
deps/unrar/crc.hpp
vendored
Normal file
15
deps/unrar/crc.hpp
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _RAR_CRC_
|
||||||
|
#define _RAR_CRC_
|
||||||
|
|
||||||
|
// This function is only to intialize external CRC tables. We do not need to
|
||||||
|
// call it before calculating CRC32.
|
||||||
|
void InitCRC32(uint *CRCTab);
|
||||||
|
|
||||||
|
uint CRC32(uint StartCRC,const void *Addr,size_t Size);
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
134
deps/unrar/crypt.cpp
vendored
Normal file
134
deps/unrar/crypt.cpp
vendored
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
#include "crypt1.cpp"
|
||||||
|
#include "crypt2.cpp"
|
||||||
|
#endif
|
||||||
|
#include "crypt3.cpp"
|
||||||
|
#include "crypt5.cpp"
|
||||||
|
|
||||||
|
|
||||||
|
CryptData::CryptData()
|
||||||
|
{
|
||||||
|
Method=CRYPT_NONE;
|
||||||
|
memset(KDF3Cache,0,sizeof(KDF3Cache));
|
||||||
|
memset(KDF5Cache,0,sizeof(KDF5Cache));
|
||||||
|
KDF3CachePos=0;
|
||||||
|
KDF5CachePos=0;
|
||||||
|
memset(CRCTab,0,sizeof(CRCTab));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CryptData::~CryptData()
|
||||||
|
{
|
||||||
|
cleandata(KDF3Cache,sizeof(KDF3Cache));
|
||||||
|
cleandata(KDF5Cache,sizeof(KDF5Cache));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::DecryptBlock(byte *Buf,size_t Size)
|
||||||
|
{
|
||||||
|
switch(Method)
|
||||||
|
{
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
case CRYPT_RAR13:
|
||||||
|
Decrypt13(Buf,Size);
|
||||||
|
break;
|
||||||
|
case CRYPT_RAR15:
|
||||||
|
Crypt15(Buf,Size);
|
||||||
|
break;
|
||||||
|
case CRYPT_RAR20:
|
||||||
|
for (size_t I=0;I<Size;I+=CRYPT_BLOCK_SIZE)
|
||||||
|
DecryptBlock20(Buf+I);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case CRYPT_RAR30:
|
||||||
|
case CRYPT_RAR50:
|
||||||
|
rin.blockDecrypt(Buf,Size,Buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CryptData::SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,
|
||||||
|
SecPassword *Password,const byte *Salt,
|
||||||
|
const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck)
|
||||||
|
{
|
||||||
|
if (!Password->IsSet() || Method==CRYPT_NONE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CryptData::Method=Method;
|
||||||
|
|
||||||
|
wchar PwdW[MAXPASSWORD];
|
||||||
|
Password->Get(PwdW,ASIZE(PwdW));
|
||||||
|
char PwdA[MAXPASSWORD];
|
||||||
|
WideToChar(PwdW,PwdA,ASIZE(PwdA));
|
||||||
|
|
||||||
|
switch(Method)
|
||||||
|
{
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
case CRYPT_RAR13:
|
||||||
|
SetKey13(PwdA);
|
||||||
|
break;
|
||||||
|
case CRYPT_RAR15:
|
||||||
|
SetKey15(PwdA);
|
||||||
|
break;
|
||||||
|
case CRYPT_RAR20:
|
||||||
|
SetKey20(PwdA);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case CRYPT_RAR30:
|
||||||
|
SetKey30(Encrypt,Password,PwdW,Salt);
|
||||||
|
break;
|
||||||
|
case CRYPT_RAR50:
|
||||||
|
SetKey50(Encrypt,Password,PwdW,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cleandata(PwdA,sizeof(PwdA));
|
||||||
|
cleandata(PwdW,sizeof(PwdW));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Use the current system time to additionally randomize data.
|
||||||
|
static void TimeRandomize(byte *RndBuf,size_t BufSize)
|
||||||
|
{
|
||||||
|
static uint Count=0;
|
||||||
|
RarTime CurTime;
|
||||||
|
CurTime.SetCurrentTime();
|
||||||
|
uint64 Random=CurTime.GetWin()+clock();
|
||||||
|
for (size_t I=0;I<BufSize;I++)
|
||||||
|
{
|
||||||
|
byte RndByte = byte (Random >> ( (I & 7) * 8 ));
|
||||||
|
RndBuf[I]=byte( (RndByte ^ I) + Count++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Fill buffer with random data.
|
||||||
|
void GetRnd(byte *RndBuf,size_t BufSize)
|
||||||
|
{
|
||||||
|
bool Success=false;
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
HCRYPTPROV hProvider = 0;
|
||||||
|
if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||||
|
{
|
||||||
|
Success=CryptGenRandom(hProvider, (DWORD)BufSize, RndBuf) == TRUE;
|
||||||
|
CryptReleaseContext(hProvider, 0);
|
||||||
|
}
|
||||||
|
#elif defined(_UNIX)
|
||||||
|
FILE *rndf = fopen("/dev/urandom", "r");
|
||||||
|
if (rndf!=NULL)
|
||||||
|
{
|
||||||
|
Success=fread(RndBuf, BufSize, 1, rndf) == BufSize;
|
||||||
|
fclose(rndf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// We use this code only as the last resort if code above failed.
|
||||||
|
if (!Success)
|
||||||
|
TimeRandomize(RndBuf,BufSize);
|
||||||
|
}
|
101
deps/unrar/crypt.hpp
vendored
Normal file
101
deps/unrar/crypt.hpp
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#ifndef _RAR_CRYPT_
|
||||||
|
#define _RAR_CRYPT_
|
||||||
|
|
||||||
|
|
||||||
|
enum CRYPT_METHOD {
|
||||||
|
CRYPT_NONE,CRYPT_RAR13,CRYPT_RAR15,CRYPT_RAR20,CRYPT_RAR30,CRYPT_RAR50
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIZE_SALT50 16
|
||||||
|
#define SIZE_SALT30 8
|
||||||
|
#define SIZE_INITV 16
|
||||||
|
#define SIZE_PSWCHECK 8
|
||||||
|
#define SIZE_PSWCHECK_CSUM 4
|
||||||
|
|
||||||
|
#define CRYPT_BLOCK_SIZE 16
|
||||||
|
#define CRYPT_BLOCK_MASK (CRYPT_BLOCK_SIZE-1) // 0xf
|
||||||
|
|
||||||
|
#define CRYPT5_KDF_LG2_COUNT 15 // LOG2 of PDKDF2 iteration count.
|
||||||
|
#define CRYPT5_KDF_LG2_COUNT_MAX 24 // LOG2 of maximum accepted iteration count.
|
||||||
|
#define CRYPT_VERSION 0 // Supported encryption version.
|
||||||
|
|
||||||
|
|
||||||
|
class CryptData
|
||||||
|
{
|
||||||
|
struct KDF5CacheItem
|
||||||
|
{
|
||||||
|
SecPassword Pwd;
|
||||||
|
byte Salt[SIZE_SALT50];
|
||||||
|
byte Key[32];
|
||||||
|
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||||
|
byte PswCheckValue[SHA256_DIGEST_SIZE];
|
||||||
|
byte HashKeyValue[SHA256_DIGEST_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KDF3CacheItem
|
||||||
|
{
|
||||||
|
SecPassword Pwd;
|
||||||
|
byte Salt[SIZE_SALT30];
|
||||||
|
byte Key[16];
|
||||||
|
byte Init[16];
|
||||||
|
bool SaltPresent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetKey13(const char *Password);
|
||||||
|
void Decrypt13(byte *Data,size_t Count);
|
||||||
|
|
||||||
|
void SetKey15(const char *Password);
|
||||||
|
void Crypt15(byte *Data,size_t Count);
|
||||||
|
|
||||||
|
void SetKey20(const char *Password);
|
||||||
|
void Swap20(byte *Ch1,byte *Ch2);
|
||||||
|
void UpdKeys20(byte *Buf);
|
||||||
|
void EncryptBlock20(byte *Buf);
|
||||||
|
void DecryptBlock20(byte *Buf);
|
||||||
|
|
||||||
|
void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt);
|
||||||
|
void SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck);
|
||||||
|
|
||||||
|
KDF3CacheItem KDF3Cache[4];
|
||||||
|
uint KDF3CachePos;
|
||||||
|
|
||||||
|
KDF5CacheItem KDF5Cache[4];
|
||||||
|
uint KDF5CachePos;
|
||||||
|
|
||||||
|
CRYPT_METHOD Method;
|
||||||
|
|
||||||
|
Rijndael rin;
|
||||||
|
|
||||||
|
uint CRCTab[256]; // For RAR 1.5 and RAR 2.0 encryption.
|
||||||
|
|
||||||
|
byte SubstTable20[256];
|
||||||
|
uint Key20[4];
|
||||||
|
|
||||||
|
byte Key13[3];
|
||||||
|
ushort Key15[4];
|
||||||
|
public:
|
||||||
|
CryptData();
|
||||||
|
~CryptData();
|
||||||
|
bool SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
|
||||||
|
const byte *Salt,const byte *InitV,uint Lg2Cnt,
|
||||||
|
byte *HashKey,byte *PswCheck);
|
||||||
|
void SetAV15Encryption();
|
||||||
|
void SetCmt13Encryption();
|
||||||
|
void EncryptBlock(byte *Buf,size_t Size);
|
||||||
|
void DecryptBlock(byte *Buf,size_t Size);
|
||||||
|
static void SetSalt(byte *Salt,size_t SaltSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
void GetRnd(byte *RndBuf,size_t BufSize);
|
||||||
|
|
||||||
|
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
|
||||||
|
size_t DataLength,byte *ResDigest);
|
||||||
|
void pbkdf2(const byte *pass, size_t pass_len, const byte *salt,
|
||||||
|
size_t salt_len,byte *key, byte *Value1, byte *Value2,
|
||||||
|
uint rounds);
|
||||||
|
|
||||||
|
void ConvertHashToMAC(HashValue *Value,byte *Key);
|
||||||
|
|
||||||
|
#endif
|
79
deps/unrar/crypt1.cpp
vendored
Normal file
79
deps/unrar/crypt1.cpp
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
extern uint CRCTab[256];
|
||||||
|
|
||||||
|
void CryptData::SetKey13(const char *Password)
|
||||||
|
{
|
||||||
|
Key13[0]=Key13[1]=Key13[2]=0;
|
||||||
|
for (size_t I=0;Password[I]!=0;I++)
|
||||||
|
{
|
||||||
|
byte P=Password[I];
|
||||||
|
Key13[0]+=P;
|
||||||
|
Key13[1]^=P;
|
||||||
|
Key13[2]+=P;
|
||||||
|
Key13[2]=(byte)rotls(Key13[2],1,8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::SetKey15(const char *Password)
|
||||||
|
{
|
||||||
|
InitCRC32(CRCTab);
|
||||||
|
uint PswCRC=CRC32(0xffffffff,Password,strlen(Password));
|
||||||
|
Key15[0]=PswCRC&0xffff;
|
||||||
|
Key15[1]=(PswCRC>>16)&0xffff;
|
||||||
|
Key15[2]=Key15[3]=0;
|
||||||
|
for (size_t I=0;Password[I]!=0;I++)
|
||||||
|
{
|
||||||
|
byte P=Password[I];
|
||||||
|
Key15[2]^=P^CRCTab[P];
|
||||||
|
Key15[3]+=P+(CRCTab[P]>>16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::SetAV15Encryption()
|
||||||
|
{
|
||||||
|
InitCRC32(CRCTab);
|
||||||
|
Method=CRYPT_RAR15;
|
||||||
|
Key15[0]=0x4765;
|
||||||
|
Key15[1]=0x9021;
|
||||||
|
Key15[2]=0x7382;
|
||||||
|
Key15[3]=0x5215;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::SetCmt13Encryption()
|
||||||
|
{
|
||||||
|
Method=CRYPT_RAR13;
|
||||||
|
Key13[0]=0;
|
||||||
|
Key13[1]=7;
|
||||||
|
Key13[2]=77;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::Decrypt13(byte *Data,size_t Count)
|
||||||
|
{
|
||||||
|
while (Count--)
|
||||||
|
{
|
||||||
|
Key13[1]+=Key13[2];
|
||||||
|
Key13[0]+=Key13[1];
|
||||||
|
*Data-=Key13[0];
|
||||||
|
Data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::Crypt15(byte *Data,size_t Count)
|
||||||
|
{
|
||||||
|
while (Count--)
|
||||||
|
{
|
||||||
|
Key15[0]+=0x1234;
|
||||||
|
Key15[1]^=CRCTab[(Key15[0] & 0x1fe)>>1];
|
||||||
|
Key15[2]-=CRCTab[(Key15[0] & 0x1fe)>>1]>>16;
|
||||||
|
Key15[0]^=Key15[2];
|
||||||
|
Key15[3]=rotrs(Key15[3]&0xffff,1,16)^Key15[1];
|
||||||
|
Key15[3]=rotrs(Key15[3]&0xffff,1,16);
|
||||||
|
Key15[0]^=Key15[3];
|
||||||
|
*Data^=(byte)(Key15[0]>>8);
|
||||||
|
Data++;
|
||||||
|
}
|
||||||
|
}
|
133
deps/unrar/crypt2.cpp
vendored
Normal file
133
deps/unrar/crypt2.cpp
vendored
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#define NROUNDS 32
|
||||||
|
|
||||||
|
#define substLong(t) ( (uint)SubstTable20[(uint)t&255] | \
|
||||||
|
((uint)SubstTable20[(int)(t>> 8)&255]<< 8) | \
|
||||||
|
((uint)SubstTable20[(int)(t>>16)&255]<<16) | \
|
||||||
|
((uint)SubstTable20[(int)(t>>24)&255]<<24) )
|
||||||
|
|
||||||
|
|
||||||
|
static byte InitSubstTable20[256]={
|
||||||
|
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
|
||||||
|
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
|
||||||
|
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
|
||||||
|
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
|
||||||
|
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
|
||||||
|
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
|
||||||
|
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
|
||||||
|
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
|
||||||
|
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
|
||||||
|
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
|
||||||
|
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
|
||||||
|
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
|
||||||
|
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
|
||||||
|
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
|
||||||
|
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
|
||||||
|
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::SetKey20(const char *Password)
|
||||||
|
{
|
||||||
|
InitCRC32(CRCTab);
|
||||||
|
|
||||||
|
char Psw[MAXPASSWORD];
|
||||||
|
strncpyz(Psw,Password,ASIZE(Psw)); // We'll need to modify it below.
|
||||||
|
size_t PswLength=strlen(Psw);
|
||||||
|
|
||||||
|
Key20[0]=0xD3A3B879L;
|
||||||
|
Key20[1]=0x3F6D12F7L;
|
||||||
|
Key20[2]=0x7515A235L;
|
||||||
|
Key20[3]=0xA4E7F123L;
|
||||||
|
|
||||||
|
memcpy(SubstTable20,InitSubstTable20,sizeof(SubstTable20));
|
||||||
|
for (uint J=0;J<256;J++)
|
||||||
|
for (size_t I=0;I<PswLength;I+=2)
|
||||||
|
{
|
||||||
|
uint N1=(byte)CRCTab [ (byte(Password[I]) - J) &0xff];
|
||||||
|
uint N2=(byte)CRCTab [ (byte(Password[I+1]) + J) &0xff];
|
||||||
|
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
|
||||||
|
Swap20(&SubstTable20[N1],&SubstTable20[(N1+I+K)&0xff]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Incomplete last block of password must be zero padded.
|
||||||
|
if ((PswLength & CRYPT_BLOCK_MASK)!=0)
|
||||||
|
for (size_t I=PswLength;I<=(PswLength|CRYPT_BLOCK_MASK);I++)
|
||||||
|
Psw[I]=0;
|
||||||
|
|
||||||
|
for (size_t I=0;I<PswLength;I+=CRYPT_BLOCK_SIZE)
|
||||||
|
EncryptBlock20((byte *)Psw+I);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::EncryptBlock20(byte *Buf)
|
||||||
|
{
|
||||||
|
uint A,B,C,D,T,TA,TB;
|
||||||
|
A=RawGet4(Buf+0)^Key20[0];
|
||||||
|
B=RawGet4(Buf+4)^Key20[1];
|
||||||
|
C=RawGet4(Buf+8)^Key20[2];
|
||||||
|
D=RawGet4(Buf+12)^Key20[3];
|
||||||
|
for(int I=0;I<NROUNDS;I++)
|
||||||
|
{
|
||||||
|
T=((C+rotls(D,11,32))^Key20[I&3]);
|
||||||
|
TA=A^substLong(T);
|
||||||
|
T=((D^rotls(C,17,32))+Key20[I&3]);
|
||||||
|
TB=B^substLong(T);
|
||||||
|
A=C;
|
||||||
|
B=D;
|
||||||
|
C=TA;
|
||||||
|
D=TB;
|
||||||
|
}
|
||||||
|
RawPut4(C^Key20[0],Buf+0);
|
||||||
|
RawPut4(D^Key20[1],Buf+4);
|
||||||
|
RawPut4(A^Key20[2],Buf+8);
|
||||||
|
RawPut4(B^Key20[3],Buf+12);
|
||||||
|
UpdKeys20(Buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::DecryptBlock20(byte *Buf)
|
||||||
|
{
|
||||||
|
byte InBuf[16];
|
||||||
|
uint A,B,C,D,T,TA,TB;
|
||||||
|
A=RawGet4(Buf+0)^Key20[0];
|
||||||
|
B=RawGet4(Buf+4)^Key20[1];
|
||||||
|
C=RawGet4(Buf+8)^Key20[2];
|
||||||
|
D=RawGet4(Buf+12)^Key20[3];
|
||||||
|
memcpy(InBuf,Buf,sizeof(InBuf));
|
||||||
|
for(int I=NROUNDS-1;I>=0;I--)
|
||||||
|
{
|
||||||
|
T=((C+rotls(D,11,32))^Key20[I&3]);
|
||||||
|
TA=A^substLong(T);
|
||||||
|
T=((D^rotls(C,17,32))+Key20[I&3]);
|
||||||
|
TB=B^substLong(T);
|
||||||
|
A=C;
|
||||||
|
B=D;
|
||||||
|
C=TA;
|
||||||
|
D=TB;
|
||||||
|
}
|
||||||
|
RawPut4(C^Key20[0],Buf+0);
|
||||||
|
RawPut4(D^Key20[1],Buf+4);
|
||||||
|
RawPut4(A^Key20[2],Buf+8);
|
||||||
|
RawPut4(B^Key20[3],Buf+12);
|
||||||
|
UpdKeys20(InBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::UpdKeys20(byte *Buf)
|
||||||
|
{
|
||||||
|
for (int I=0;I<16;I+=4)
|
||||||
|
{
|
||||||
|
Key20[0]^=CRCTab[Buf[I]];
|
||||||
|
Key20[1]^=CRCTab[Buf[I+1]];
|
||||||
|
Key20[2]^=CRCTab[Buf[I+2]];
|
||||||
|
Key20[3]^=CRCTab[Buf[I+3]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::Swap20(byte *Ch1,byte *Ch2)
|
||||||
|
{
|
||||||
|
byte Ch=*Ch1;
|
||||||
|
*Ch1=*Ch2;
|
||||||
|
*Ch2=Ch;
|
||||||
|
}
|
68
deps/unrar/crypt3.cpp
vendored
Normal file
68
deps/unrar/crypt3.cpp
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt)
|
||||||
|
{
|
||||||
|
byte AESKey[16],AESInit[16];
|
||||||
|
|
||||||
|
bool Cached=false;
|
||||||
|
for (uint I=0;I<ASIZE(KDF3Cache);I++)
|
||||||
|
if (KDF3Cache[I].Pwd==*Password &&
|
||||||
|
(Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL &&
|
||||||
|
KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0))
|
||||||
|
{
|
||||||
|
memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey));
|
||||||
|
SecHideData(AESKey,sizeof(AESKey),false,false);
|
||||||
|
memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit));
|
||||||
|
Cached=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Cached)
|
||||||
|
{
|
||||||
|
byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
|
||||||
|
WideToRaw(PwdW,RawPsw,ASIZE(RawPsw));
|
||||||
|
size_t RawLength=2*wcslen(PwdW);
|
||||||
|
if (Salt!=NULL)
|
||||||
|
{
|
||||||
|
memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
|
||||||
|
RawLength+=SIZE_SALT30;
|
||||||
|
}
|
||||||
|
sha1_context c;
|
||||||
|
sha1_init(&c);
|
||||||
|
|
||||||
|
const uint HashRounds=0x40000;
|
||||||
|
for (uint I=0;I<HashRounds;I++)
|
||||||
|
{
|
||||||
|
sha1_process_rar29( &c, RawPsw, RawLength );
|
||||||
|
byte PswNum[3];
|
||||||
|
PswNum[0]=(byte)I;
|
||||||
|
PswNum[1]=(byte)(I>>8);
|
||||||
|
PswNum[2]=(byte)(I>>16);
|
||||||
|
sha1_process(&c, PswNum, 3);
|
||||||
|
if (I%(HashRounds/16)==0)
|
||||||
|
{
|
||||||
|
sha1_context tempc=c;
|
||||||
|
uint32 digest[5];
|
||||||
|
sha1_done( &tempc, digest );
|
||||||
|
AESInit[I/(HashRounds/16)]=(byte)digest[4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32 digest[5];
|
||||||
|
sha1_done( &c, digest );
|
||||||
|
for (uint I=0;I<4;I++)
|
||||||
|
for (uint J=0;J<4;J++)
|
||||||
|
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
||||||
|
|
||||||
|
KDF3Cache[KDF3CachePos].Pwd=*Password;
|
||||||
|
if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true)
|
||||||
|
memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30);
|
||||||
|
memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey));
|
||||||
|
SecHideData(KDF3Cache[KDF3CachePos].Key,sizeof(KDF3Cache[KDF3CachePos].Key),true,false);
|
||||||
|
memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit));
|
||||||
|
KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache);
|
||||||
|
|
||||||
|
cleandata(RawPsw,sizeof(RawPsw));
|
||||||
|
}
|
||||||
|
rin.Init(Encrypt, AESKey, 128, AESInit);
|
||||||
|
cleandata(AESKey,sizeof(AESKey));
|
||||||
|
cleandata(AESInit,sizeof(AESInit));
|
||||||
|
}
|
||||||
|
|
233
deps/unrar/crypt5.cpp
vendored
Normal file
233
deps/unrar/crypt5.cpp
vendored
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
|
||||||
|
size_t DataLength,byte *ResDigest,
|
||||||
|
sha256_context *ICtxOpt,bool *SetIOpt,
|
||||||
|
sha256_context *RCtxOpt,bool *SetROpt)
|
||||||
|
{
|
||||||
|
const size_t Sha256BlockSize=64; // As defined in RFC 4868.
|
||||||
|
|
||||||
|
byte KeyHash[SHA256_DIGEST_SIZE];
|
||||||
|
if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash.
|
||||||
|
{
|
||||||
|
sha256_context KCtx;
|
||||||
|
sha256_init(&KCtx);
|
||||||
|
sha256_process(&KCtx, Key, KeyLength);
|
||||||
|
sha256_done(&KCtx, KeyHash);
|
||||||
|
|
||||||
|
Key = KeyHash;
|
||||||
|
KeyLength = SHA256_DIGEST_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte KeyBuf[Sha256BlockSize]; // Store the padded key here.
|
||||||
|
sha256_context ICtx;
|
||||||
|
|
||||||
|
if (ICtxOpt!=NULL && *SetIOpt)
|
||||||
|
ICtx=*ICtxOpt; // Use already calculated first block context.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This calculation is the same for all iterations with same password.
|
||||||
|
// So for PBKDF2 we can calculate it only for first block and then reuse
|
||||||
|
// to improve performance.
|
||||||
|
|
||||||
|
for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest.
|
||||||
|
KeyBuf[I] = Key[I] ^ 0x36;
|
||||||
|
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
|
||||||
|
KeyBuf[I] = 0x36;
|
||||||
|
|
||||||
|
sha256_init(&ICtx);
|
||||||
|
sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse.
|
||||||
|
{
|
||||||
|
*ICtxOpt=ICtx;
|
||||||
|
*SetIOpt=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha256_process(&ICtx, Data, DataLength); // Hash data.
|
||||||
|
|
||||||
|
byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data.
|
||||||
|
sha256_done(&ICtx, IDig);
|
||||||
|
|
||||||
|
sha256_context RCtx;
|
||||||
|
|
||||||
|
if (RCtxOpt!=NULL && *SetROpt)
|
||||||
|
RCtx=*RCtxOpt; // Use already calculated first block context.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This calculation is the same for all iterations with same password.
|
||||||
|
// So for PBKDF2 we can calculate it only for first block and then reuse
|
||||||
|
// to improve performance.
|
||||||
|
|
||||||
|
for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding.
|
||||||
|
KeyBuf[I] = Key[I] ^ 0x5c;
|
||||||
|
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
|
||||||
|
KeyBuf[I] = 0x5c;
|
||||||
|
|
||||||
|
sha256_init(&RCtx);
|
||||||
|
sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse.
|
||||||
|
{
|
||||||
|
*RCtxOpt=RCtx;
|
||||||
|
*SetROpt=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest.
|
||||||
|
|
||||||
|
sha256_done(&RCtx, ResDigest);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PBKDF2 for 32 byte key length. We generate the key for specified number
|
||||||
|
// of iteration count also as two supplementary values (key for checksums
|
||||||
|
// and password verification) for iterations+16 and iterations+32.
|
||||||
|
void pbkdf2(const byte *Pwd, size_t PwdLength,
|
||||||
|
const byte *Salt, size_t SaltLength,
|
||||||
|
byte *Key, byte *V1, byte *V2, uint Count)
|
||||||
|
{
|
||||||
|
const size_t MaxSalt=64;
|
||||||
|
byte SaltData[MaxSalt+4];
|
||||||
|
memcpy(SaltData, Salt, Min(SaltLength,MaxSalt));
|
||||||
|
|
||||||
|
SaltData[SaltLength + 0] = 0; // Salt concatenated to 1.
|
||||||
|
SaltData[SaltLength + 1] = 0;
|
||||||
|
SaltData[SaltLength + 2] = 0;
|
||||||
|
SaltData[SaltLength + 3] = 1;
|
||||||
|
|
||||||
|
// First iteration: HMAC of password, salt and block index (1).
|
||||||
|
byte U1[SHA256_DIGEST_SIZE];
|
||||||
|
hmac_sha256(Pwd, PwdLength, SaltData, SaltLength + 4, U1, NULL, NULL, NULL, NULL);
|
||||||
|
byte Fn[SHA256_DIGEST_SIZE]; // Current function value.
|
||||||
|
memcpy(Fn, U1, sizeof(Fn)); // Function at first iteration.
|
||||||
|
|
||||||
|
uint CurCount[] = { Count-1, 16, 16 };
|
||||||
|
byte *CurValue[] = { Key , V1, V2 };
|
||||||
|
|
||||||
|
sha256_context ICtxOpt,RCtxOpt;
|
||||||
|
bool SetIOpt=false,SetROpt=false;
|
||||||
|
|
||||||
|
byte U2[SHA256_DIGEST_SIZE];
|
||||||
|
for (uint I = 0; I < 3; I++) // For output key and 2 supplementary values.
|
||||||
|
{
|
||||||
|
for (uint J = 0; J < CurCount[I]; J++)
|
||||||
|
{
|
||||||
|
// U2 = PRF (P, U1).
|
||||||
|
hmac_sha256(Pwd, PwdLength, U1, sizeof(U1), U2, &ICtxOpt, &SetIOpt, &RCtxOpt, &SetROpt);
|
||||||
|
memcpy(U1, U2, sizeof(U1));
|
||||||
|
for (uint K = 0; K < sizeof(Fn); K++) // Function ^= U.
|
||||||
|
Fn[K] ^= U1[K];
|
||||||
|
}
|
||||||
|
memcpy(CurValue[I], Fn, SHA256_DIGEST_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleandata(SaltData, sizeof(SaltData));
|
||||||
|
cleandata(Fn, sizeof(Fn));
|
||||||
|
cleandata(U1, sizeof(U1));
|
||||||
|
cleandata(U2, sizeof(U2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,
|
||||||
|
const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,
|
||||||
|
byte *PswCheck)
|
||||||
|
{
|
||||||
|
if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE];
|
||||||
|
bool Found=false;
|
||||||
|
for (uint I=0;I<ASIZE(KDF5Cache);I++)
|
||||||
|
{
|
||||||
|
KDF5CacheItem *Item=KDF5Cache+I;
|
||||||
|
if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password &&
|
||||||
|
memcmp(Item->Salt,Salt,SIZE_SALT50)==0)
|
||||||
|
{
|
||||||
|
memcpy(Key,Item->Key,sizeof(Key));
|
||||||
|
SecHideData(Key,sizeof(Key),false,false);
|
||||||
|
|
||||||
|
memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue));
|
||||||
|
memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue));
|
||||||
|
Found=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Found)
|
||||||
|
{
|
||||||
|
char PwdUtf[MAXPASSWORD*4];
|
||||||
|
WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf));
|
||||||
|
|
||||||
|
pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt));
|
||||||
|
cleandata(PwdUtf,sizeof(PwdUtf));
|
||||||
|
|
||||||
|
KDF5CacheItem *Item=KDF5Cache+(KDF5CachePos++ % ASIZE(KDF5Cache));
|
||||||
|
Item->Lg2Count=Lg2Cnt;
|
||||||
|
Item->Pwd=*Password;
|
||||||
|
memcpy(Item->Salt,Salt,SIZE_SALT50);
|
||||||
|
memcpy(Item->Key,Key,sizeof(Item->Key));
|
||||||
|
memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue));
|
||||||
|
memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue));
|
||||||
|
SecHideData(Item->Key,sizeof(Item->Key),true,false);
|
||||||
|
}
|
||||||
|
if (HashKey!=NULL)
|
||||||
|
memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE);
|
||||||
|
if (PswCheck!=NULL)
|
||||||
|
{
|
||||||
|
memset(PswCheck,0,SIZE_PSWCHECK);
|
||||||
|
for (uint I=0;I<SHA256_DIGEST_SIZE;I++)
|
||||||
|
PswCheck[I%SIZE_PSWCHECK]^=PswCheckValue[I];
|
||||||
|
cleandata(PswCheckValue,sizeof(PswCheckValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
// NULL initialization vector is possible if we only need the password
|
||||||
|
// check value for archive encryption header.
|
||||||
|
if (InitV!=NULL)
|
||||||
|
rin.Init(Encrypt, Key, 256, InitV);
|
||||||
|
|
||||||
|
cleandata(Key,sizeof(Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConvertHashToMAC(HashValue *Value,byte *Key)
|
||||||
|
{
|
||||||
|
if (Value->Type==HASH_CRC32)
|
||||||
|
{
|
||||||
|
byte RawCRC[4];
|
||||||
|
RawPut4(Value->CRC32,RawCRC);
|
||||||
|
byte Digest[SHA256_DIGEST_SIZE];
|
||||||
|
hmac_sha256(Key,SHA256_DIGEST_SIZE,RawCRC,sizeof(RawCRC),Digest,NULL,NULL,NULL,NULL);
|
||||||
|
Value->CRC32=0;
|
||||||
|
for (uint I=0;I<ASIZE(Digest);I++)
|
||||||
|
Value->CRC32^=Digest[I] << ((I & 3) * 8);
|
||||||
|
}
|
||||||
|
if (Value->Type==HASH_BLAKE2)
|
||||||
|
{
|
||||||
|
byte Digest[BLAKE2_DIGEST_SIZE];
|
||||||
|
hmac_sha256(Key,BLAKE2_DIGEST_SIZE,Value->Digest,sizeof(Value->Digest),Digest,NULL,NULL,NULL,NULL);
|
||||||
|
memcpy(Value->Digest,Digest,sizeof(Value->Digest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void TestPBKDF2();
|
||||||
|
struct TestKDF {TestKDF() {TestPBKDF2();exit(0);}} GlobalTestKDF;
|
||||||
|
|
||||||
|
void TestPBKDF2() // Test PBKDF2 HMAC-SHA256
|
||||||
|
{
|
||||||
|
byte Key[32],V1[32],V2[32];
|
||||||
|
|
||||||
|
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 1);
|
||||||
|
byte Res1[32]={0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, 0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48, 0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b };
|
||||||
|
mprintf(L"\nPBKDF2 test1: %s", memcmp(Key,Res1,32)==0 ? L"OK":L"Failed");
|
||||||
|
|
||||||
|
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 4096);
|
||||||
|
byte Res2[32]={0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, 0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11, 0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a };
|
||||||
|
mprintf(L"\nPBKDF2 test2: %s", memcmp(Key,Res2,32)==0 ? L"OK":L"Failed");
|
||||||
|
|
||||||
|
pbkdf2((byte *)"just some long string pretending to be a password", 49, (byte *)"salt, salt, salt, a lot of salt", 31, Key, V1, V2, 65536);
|
||||||
|
byte Res3[32]={0x08, 0x0f, 0xa3, 0x1d, 0x42, 0x2d, 0xb0, 0x47, 0x83, 0x9b, 0xce, 0x3a, 0x3b, 0xce, 0x49, 0x51, 0xe2, 0x62, 0xb9, 0xff, 0x76, 0x2f, 0x57, 0xe9, 0xc4, 0x71, 0x96, 0xce, 0x4b, 0x6b, 0x6e, 0xbf};
|
||||||
|
mprintf(L"\nPBKDF2 test3: %s", memcmp(Key,Res3,32)==0 ? L"OK":L"Failed");
|
||||||
|
}
|
||||||
|
#endif
|
495
deps/unrar/dll.cpp
vendored
Normal file
495
deps/unrar/dll.cpp
vendored
Normal file
@ -0,0 +1,495 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
static int RarErrorToDll(RAR_EXIT ErrCode);
|
||||||
|
|
||||||
|
struct DataSet
|
||||||
|
{
|
||||||
|
CommandData Cmd;
|
||||||
|
Archive Arc;
|
||||||
|
CmdExtract Extract;
|
||||||
|
int OpenMode;
|
||||||
|
int HeaderSize;
|
||||||
|
|
||||||
|
DataSet():Arc(&Cmd),Extract(&Cmd) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
|
||||||
|
{
|
||||||
|
RAROpenArchiveDataEx rx;
|
||||||
|
memset(&rx,0,sizeof(rx));
|
||||||
|
rx.ArcName=r->ArcName;
|
||||||
|
rx.OpenMode=r->OpenMode;
|
||||||
|
rx.CmtBuf=r->CmtBuf;
|
||||||
|
rx.CmtBufSize=r->CmtBufSize;
|
||||||
|
HANDLE hArc=RAROpenArchiveEx(&rx);
|
||||||
|
r->OpenResult=rx.OpenResult;
|
||||||
|
r->CmtSize=rx.CmtSize;
|
||||||
|
r->CmtState=rx.CmtState;
|
||||||
|
return hArc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||||
|
{
|
||||||
|
DataSet *Data=NULL;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ErrHandler.Clean();
|
||||||
|
|
||||||
|
r->OpenResult=0;
|
||||||
|
Data=new DataSet;
|
||||||
|
Data->Cmd.DllError=0;
|
||||||
|
Data->OpenMode=r->OpenMode;
|
||||||
|
Data->Cmd.FileArgs.AddString(L"*");
|
||||||
|
Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0;
|
||||||
|
|
||||||
|
char AnsiArcName[NM];
|
||||||
|
*AnsiArcName=0;
|
||||||
|
if (r->ArcName!=NULL)
|
||||||
|
{
|
||||||
|
strncpyz(AnsiArcName,r->ArcName,ASIZE(AnsiArcName));
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
if (!AreFileApisANSI())
|
||||||
|
{
|
||||||
|
OemToCharBuffA(r->ArcName,AnsiArcName,ASIZE(AnsiArcName));
|
||||||
|
AnsiArcName[ASIZE(AnsiArcName)-1]=0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar ArcName[NM];
|
||||||
|
GetWideName(AnsiArcName,r->ArcNameW,ArcName,ASIZE(ArcName));
|
||||||
|
|
||||||
|
Data->Cmd.AddArcName(ArcName);
|
||||||
|
Data->Cmd.Overwrite=OVERWRITE_ALL;
|
||||||
|
Data->Cmd.VersionControl=1;
|
||||||
|
|
||||||
|
Data->Cmd.Callback=r->Callback;
|
||||||
|
Data->Cmd.UserData=r->UserData;
|
||||||
|
|
||||||
|
// Open shared mode is added by request of dll users, who need to
|
||||||
|
// browse and unpack archives while downloading.
|
||||||
|
Data->Cmd.OpenShared = true;
|
||||||
|
if (!Data->Arc.Open(ArcName,FMF_OPENSHARED))
|
||||||
|
{
|
||||||
|
r->OpenResult=ERAR_EOPEN;
|
||||||
|
delete Data;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!Data->Arc.IsArchive(true))
|
||||||
|
{
|
||||||
|
if (Data->Cmd.DllError!=0)
|
||||||
|
r->OpenResult=Data->Cmd.DllError;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RAR_EXIT ErrCode=ErrHandler.GetErrorCode();
|
||||||
|
if (ErrCode!=RARX_SUCCESS && ErrCode!=RARX_WARNING)
|
||||||
|
r->OpenResult=RarErrorToDll(ErrCode);
|
||||||
|
else
|
||||||
|
r->OpenResult=ERAR_BAD_ARCHIVE;
|
||||||
|
}
|
||||||
|
delete Data;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
r->Flags=0;
|
||||||
|
|
||||||
|
if (Data->Arc.Volume)
|
||||||
|
r->Flags|=ROADF_VOLUME;
|
||||||
|
if (Data->Arc.MainComment)
|
||||||
|
r->Flags|=ROADF_COMMENT;
|
||||||
|
if (Data->Arc.Locked)
|
||||||
|
r->Flags|=ROADF_LOCK;
|
||||||
|
if (Data->Arc.Solid)
|
||||||
|
r->Flags|=ROADF_SOLID;
|
||||||
|
if (Data->Arc.NewNumbering)
|
||||||
|
r->Flags|=ROADF_NEWNUMBERING;
|
||||||
|
if (Data->Arc.Signed)
|
||||||
|
r->Flags|=ROADF_SIGNED;
|
||||||
|
if (Data->Arc.Protected)
|
||||||
|
r->Flags|=ROADF_RECOVERY;
|
||||||
|
if (Data->Arc.Encrypted)
|
||||||
|
r->Flags|=ROADF_ENCHEADERS;
|
||||||
|
if (Data->Arc.FirstVolume)
|
||||||
|
r->Flags|=ROADF_FIRSTVOLUME;
|
||||||
|
|
||||||
|
Array<wchar> CmtDataW;
|
||||||
|
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
|
||||||
|
{
|
||||||
|
if (r->CmtBufW!=NULL)
|
||||||
|
{
|
||||||
|
CmtDataW.Push(0);
|
||||||
|
size_t Size=wcslen(&CmtDataW[0])+1;
|
||||||
|
|
||||||
|
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||||
|
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||||
|
memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW));
|
||||||
|
r->CmtBufW[r->CmtSize-1]=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (r->CmtBuf!=NULL)
|
||||||
|
{
|
||||||
|
Array<char> CmtData(CmtDataW.Size()*4+1);
|
||||||
|
memset(&CmtData[0],0,CmtData.Size());
|
||||||
|
WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
|
||||||
|
size_t Size=strlen(&CmtData[0])+1;
|
||||||
|
|
||||||
|
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||||
|
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||||
|
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
||||||
|
r->CmtBuf[r->CmtSize-1]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
r->CmtState=r->CmtSize=0;
|
||||||
|
Data->Extract.ExtractArchiveInit(Data->Arc);
|
||||||
|
return (HANDLE)Data;
|
||||||
|
}
|
||||||
|
catch (RAR_EXIT ErrCode)
|
||||||
|
{
|
||||||
|
if (Data!=NULL && Data->Cmd.DllError!=0)
|
||||||
|
r->OpenResult=Data->Cmd.DllError;
|
||||||
|
else
|
||||||
|
r->OpenResult=RarErrorToDll(ErrCode);
|
||||||
|
if (Data != NULL)
|
||||||
|
delete Data;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&) // Catch 'new' exception.
|
||||||
|
{
|
||||||
|
r->OpenResult=ERAR_NO_MEMORY;
|
||||||
|
if (Data != NULL)
|
||||||
|
delete Data;
|
||||||
|
}
|
||||||
|
return NULL; // To make compilers happy.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PASCAL RARCloseArchive(HANDLE hArcData)
|
||||||
|
{
|
||||||
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool Success=Data==NULL ? false:Data->Arc.Close();
|
||||||
|
delete Data;
|
||||||
|
return Success ? ERAR_SUCCESS : ERAR_ECLOSE;
|
||||||
|
}
|
||||||
|
catch (RAR_EXIT ErrCode)
|
||||||
|
{
|
||||||
|
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
|
||||||
|
{
|
||||||
|
struct RARHeaderDataEx X;
|
||||||
|
memset(&X,0,sizeof(X));
|
||||||
|
|
||||||
|
int Code=RARReadHeaderEx(hArcData,&X);
|
||||||
|
|
||||||
|
strncpyz(D->ArcName,X.ArcName,ASIZE(D->ArcName));
|
||||||
|
strncpyz(D->FileName,X.FileName,ASIZE(D->FileName));
|
||||||
|
D->Flags=X.Flags;
|
||||||
|
D->PackSize=X.PackSize;
|
||||||
|
D->UnpSize=X.UnpSize;
|
||||||
|
D->HostOS=X.HostOS;
|
||||||
|
D->FileCRC=X.FileCRC;
|
||||||
|
D->FileTime=X.FileTime;
|
||||||
|
D->UnpVer=X.UnpVer;
|
||||||
|
D->Method=X.Method;
|
||||||
|
D->FileAttr=X.FileAttr;
|
||||||
|
D->CmtSize=0;
|
||||||
|
D->CmtState=0;
|
||||||
|
|
||||||
|
return Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||||
|
{
|
||||||
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(HEAD_FILE))<=0)
|
||||||
|
{
|
||||||
|
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_ENDARC &&
|
||||||
|
Data->Arc.EndArcHead.NextVolume)
|
||||||
|
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
||||||
|
{
|
||||||
|
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||||
|
return RARReadHeaderEx(hArcData,D);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERAR_EOPEN;
|
||||||
|
|
||||||
|
if (Data->Arc.BrokenHeader)
|
||||||
|
return ERAR_BAD_DATA;
|
||||||
|
|
||||||
|
// Might be necessary if RARSetPassword is still called instead of
|
||||||
|
// open callback for RAR5 archives and if password is invalid.
|
||||||
|
if (Data->Arc.FailedHeaderDecryption)
|
||||||
|
return ERAR_BAD_PASSWORD;
|
||||||
|
|
||||||
|
return ERAR_END_ARCHIVE;
|
||||||
|
}
|
||||||
|
FileHeader *hd=&Data->Arc.FileHead;
|
||||||
|
if (Data->OpenMode==RAR_OM_LIST && hd->SplitBefore)
|
||||||
|
{
|
||||||
|
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
|
||||||
|
if (Code==0)
|
||||||
|
return RARReadHeaderEx(hArcData,D);
|
||||||
|
else
|
||||||
|
return Code;
|
||||||
|
}
|
||||||
|
wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
|
||||||
|
WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName));
|
||||||
|
|
||||||
|
wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
|
||||||
|
WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName));
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
CharToOemA(D->FileName,D->FileName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
D->Flags=0;
|
||||||
|
if (hd->SplitBefore)
|
||||||
|
D->Flags|=RHDF_SPLITBEFORE;
|
||||||
|
if (hd->SplitAfter)
|
||||||
|
D->Flags|=RHDF_SPLITAFTER;
|
||||||
|
if (hd->Encrypted)
|
||||||
|
D->Flags|=RHDF_ENCRYPTED;
|
||||||
|
if (hd->Solid)
|
||||||
|
D->Flags|=RHDF_SOLID;
|
||||||
|
if (hd->Dir)
|
||||||
|
D->Flags|=RHDF_DIRECTORY;
|
||||||
|
|
||||||
|
D->PackSize=uint(hd->PackSize & 0xffffffff);
|
||||||
|
D->PackSizeHigh=uint(hd->PackSize>>32);
|
||||||
|
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
|
||||||
|
D->UnpSizeHigh=uint(hd->UnpSize>>32);
|
||||||
|
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
|
||||||
|
D->UnpVer=Data->Arc.FileHead.UnpVer;
|
||||||
|
D->FileCRC=hd->FileHash.CRC32;
|
||||||
|
D->FileTime=hd->mtime.GetDos();
|
||||||
|
|
||||||
|
uint64 MRaw=hd->mtime.GetWin();
|
||||||
|
D->MtimeLow=(uint)MRaw;
|
||||||
|
D->MtimeHigh=(uint)(MRaw>>32);
|
||||||
|
uint64 CRaw=hd->ctime.GetWin();
|
||||||
|
D->CtimeLow=(uint)CRaw;
|
||||||
|
D->CtimeHigh=(uint)(CRaw>>32);
|
||||||
|
uint64 ARaw=hd->atime.GetWin();
|
||||||
|
D->AtimeLow=(uint)ARaw;
|
||||||
|
D->AtimeHigh=(uint)(ARaw>>32);
|
||||||
|
|
||||||
|
D->Method=hd->Method+0x30;
|
||||||
|
D->FileAttr=hd->FileAttr;
|
||||||
|
D->CmtSize=0;
|
||||||
|
D->CmtState=0;
|
||||||
|
|
||||||
|
D->DictSize=uint(hd->WinSize/1024);
|
||||||
|
|
||||||
|
switch (hd->FileHash.Type)
|
||||||
|
{
|
||||||
|
case HASH_RAR14:
|
||||||
|
case HASH_CRC32:
|
||||||
|
D->HashType=RAR_HASH_CRC32;
|
||||||
|
break;
|
||||||
|
case HASH_BLAKE2:
|
||||||
|
D->HashType=RAR_HASH_BLAKE2;
|
||||||
|
memcpy(D->Hash,hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
D->HashType=RAR_HASH_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
D->RedirType=hd->RedirType;
|
||||||
|
// RedirNameSize sanity check is useful in case some developer
|
||||||
|
// did not initialize Reserved area with 0 as required in docs.
|
||||||
|
// We have taken 'Redir*' fields from Reserved area. We may remove
|
||||||
|
// this RedirNameSize check sometimes later.
|
||||||
|
if (hd->RedirType!=FSREDIR_NONE && D->RedirName!=NULL &&
|
||||||
|
D->RedirNameSize>0 && D->RedirNameSize<100000)
|
||||||
|
wcsncpyz(D->RedirName,hd->RedirName,D->RedirNameSize);
|
||||||
|
D->DirTarget=hd->DirTarget;
|
||||||
|
}
|
||||||
|
catch (RAR_EXIT ErrCode)
|
||||||
|
{
|
||||||
|
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
|
||||||
|
}
|
||||||
|
return ERAR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
|
||||||
|
{
|
||||||
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Data->Cmd.DllError=0;
|
||||||
|
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
|
||||||
|
Operation==RAR_SKIP && !Data->Arc.Solid)
|
||||||
|
{
|
||||||
|
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_FILE &&
|
||||||
|
Data->Arc.FileHead.SplitAfter)
|
||||||
|
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
||||||
|
{
|
||||||
|
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||||
|
return ERAR_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERAR_EOPEN;
|
||||||
|
Data->Arc.SeekToNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Data->Cmd.DllOpMode=Operation;
|
||||||
|
|
||||||
|
*Data->Cmd.ExtrPath=0;
|
||||||
|
*Data->Cmd.DllDestName=0;
|
||||||
|
|
||||||
|
if (DestPath!=NULL)
|
||||||
|
{
|
||||||
|
char ExtrPathA[NM];
|
||||||
|
strncpyz(ExtrPathA,DestPath,ASIZE(ExtrPathA)-2);
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// We must not apply OemToCharBuffA directly to DestPath,
|
||||||
|
// because we do not know DestPath length and OemToCharBuffA
|
||||||
|
// does not stop at 0.
|
||||||
|
OemToCharA(ExtrPathA,ExtrPathA);
|
||||||
|
#endif
|
||||||
|
CharToWide(ExtrPathA,Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
|
||||||
|
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
|
||||||
|
}
|
||||||
|
if (DestName!=NULL)
|
||||||
|
{
|
||||||
|
char DestNameA[NM];
|
||||||
|
strncpyz(DestNameA,DestName,ASIZE(DestNameA)-2);
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// We must not apply OemToCharBuffA directly to DestName,
|
||||||
|
// because we do not know DestName length and OemToCharBuffA
|
||||||
|
// does not stop at 0.
|
||||||
|
OemToCharA(DestNameA,DestNameA);
|
||||||
|
#endif
|
||||||
|
CharToWide(DestNameA,Data->Cmd.DllDestName,ASIZE(Data->Cmd.DllDestName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DestPathW!=NULL)
|
||||||
|
{
|
||||||
|
wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
|
||||||
|
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DestNameW!=NULL)
|
||||||
|
wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
|
||||||
|
|
||||||
|
wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command));
|
||||||
|
Data->Cmd.Test=Operation!=RAR_EXTRACT;
|
||||||
|
bool Repeat=false;
|
||||||
|
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
|
||||||
|
|
||||||
|
// Now we process extra file information if any.
|
||||||
|
//
|
||||||
|
// Archive can be closed if we process volumes, next volume is missing
|
||||||
|
// and current one is already removed or deleted. So we need to check
|
||||||
|
// if archive is still open to avoid calling file operations on
|
||||||
|
// the invalid file handle. Some of our file operations like Seek()
|
||||||
|
// process such invalid handle correctly, some not.
|
||||||
|
while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 &&
|
||||||
|
Data->Arc.GetHeaderType()==HEAD_SERVICE)
|
||||||
|
{
|
||||||
|
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
|
||||||
|
Data->Arc.SeekToNext();
|
||||||
|
}
|
||||||
|
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
return ERAR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
catch (RAR_EXIT ErrCode)
|
||||||
|
{
|
||||||
|
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
|
||||||
|
}
|
||||||
|
return Data->Cmd.DllError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
|
||||||
|
{
|
||||||
|
return ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
|
||||||
|
{
|
||||||
|
return ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
|
||||||
|
{
|
||||||
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
|
Data->Cmd.ChangeVolProc=ChangeVolProc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
|
||||||
|
{
|
||||||
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
|
Data->Cmd.Callback=Callback;
|
||||||
|
Data->Cmd.UserData=UserData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc)
|
||||||
|
{
|
||||||
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
|
Data->Cmd.ProcessDataProc=ProcessDataProc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
|
||||||
|
{
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
|
wchar PasswordW[MAXPASSWORD];
|
||||||
|
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
|
||||||
|
Data->Cmd.Password.Set(PasswordW);
|
||||||
|
cleandata(PasswordW,sizeof(PasswordW));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PASCAL RARGetDllVersion()
|
||||||
|
{
|
||||||
|
return RAR_DLL_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int RarErrorToDll(RAR_EXIT ErrCode)
|
||||||
|
{
|
||||||
|
switch(ErrCode)
|
||||||
|
{
|
||||||
|
case RARX_FATAL:
|
||||||
|
return ERAR_EREAD;
|
||||||
|
case RARX_CRC:
|
||||||
|
return ERAR_BAD_DATA;
|
||||||
|
case RARX_WRITE:
|
||||||
|
return ERAR_EWRITE;
|
||||||
|
case RARX_OPEN:
|
||||||
|
return ERAR_EOPEN;
|
||||||
|
case RARX_CREATE:
|
||||||
|
return ERAR_ECREATE;
|
||||||
|
case RARX_MEMORY:
|
||||||
|
return ERAR_NO_MEMORY;
|
||||||
|
case RARX_BADPWD:
|
||||||
|
return ERAR_BAD_PASSWORD;
|
||||||
|
case RARX_SUCCESS:
|
||||||
|
return ERAR_SUCCESS; // 0.
|
||||||
|
default:
|
||||||
|
return ERAR_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
13
deps/unrar/dll.def
vendored
Normal file
13
deps/unrar/dll.def
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
EXPORTS
|
||||||
|
RAROpenArchive
|
||||||
|
RAROpenArchiveEx
|
||||||
|
RARCloseArchive
|
||||||
|
RARReadHeader
|
||||||
|
RARReadHeaderEx
|
||||||
|
RARProcessFile
|
||||||
|
RARProcessFileW
|
||||||
|
RARSetCallback
|
||||||
|
RARSetChangeVolProc
|
||||||
|
RARSetProcessDataProc
|
||||||
|
RARSetPassword
|
||||||
|
RARGetDllVersion
|
189
deps/unrar/dll.hpp
vendored
Normal file
189
deps/unrar/dll.hpp
vendored
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
#ifndef _UNRAR_DLL_
|
||||||
|
#define _UNRAR_DLL_
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
#define ERAR_SUCCESS 0
|
||||||
|
#define ERAR_END_ARCHIVE 10
|
||||||
|
#define ERAR_NO_MEMORY 11
|
||||||
|
#define ERAR_BAD_DATA 12
|
||||||
|
#define ERAR_BAD_ARCHIVE 13
|
||||||
|
#define ERAR_UNKNOWN_FORMAT 14
|
||||||
|
#define ERAR_EOPEN 15
|
||||||
|
#define ERAR_ECREATE 16
|
||||||
|
#define ERAR_ECLOSE 17
|
||||||
|
#define ERAR_EREAD 18
|
||||||
|
#define ERAR_EWRITE 19
|
||||||
|
#define ERAR_SMALL_BUF 20
|
||||||
|
#define ERAR_UNKNOWN 21
|
||||||
|
#define ERAR_MISSING_PASSWORD 22
|
||||||
|
#define ERAR_EREFERENCE 23
|
||||||
|
#define ERAR_BAD_PASSWORD 24
|
||||||
|
|
||||||
|
#define RAR_OM_LIST 0
|
||||||
|
#define RAR_OM_EXTRACT 1
|
||||||
|
#define RAR_OM_LIST_INCSPLIT 2
|
||||||
|
|
||||||
|
#define RAR_SKIP 0
|
||||||
|
#define RAR_TEST 1
|
||||||
|
#define RAR_EXTRACT 2
|
||||||
|
|
||||||
|
#define RAR_VOL_ASK 0
|
||||||
|
#define RAR_VOL_NOTIFY 1
|
||||||
|
|
||||||
|
#define RAR_DLL_VERSION 8
|
||||||
|
|
||||||
|
#define RAR_HASH_NONE 0
|
||||||
|
#define RAR_HASH_CRC32 1
|
||||||
|
#define RAR_HASH_BLAKE2 2
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _UNIX
|
||||||
|
#define CALLBACK
|
||||||
|
#define PASCAL
|
||||||
|
#define LONG long
|
||||||
|
#define HANDLE void *
|
||||||
|
#define LPARAM long
|
||||||
|
#define UINT unsigned int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RHDF_SPLITBEFORE 0x01
|
||||||
|
#define RHDF_SPLITAFTER 0x02
|
||||||
|
#define RHDF_ENCRYPTED 0x04
|
||||||
|
#define RHDF_SOLID 0x10
|
||||||
|
#define RHDF_DIRECTORY 0x20
|
||||||
|
|
||||||
|
|
||||||
|
struct RARHeaderData
|
||||||
|
{
|
||||||
|
char ArcName[260];
|
||||||
|
char FileName[260];
|
||||||
|
unsigned int Flags;
|
||||||
|
unsigned int PackSize;
|
||||||
|
unsigned int UnpSize;
|
||||||
|
unsigned int HostOS;
|
||||||
|
unsigned int FileCRC;
|
||||||
|
unsigned int FileTime;
|
||||||
|
unsigned int UnpVer;
|
||||||
|
unsigned int Method;
|
||||||
|
unsigned int FileAttr;
|
||||||
|
char *CmtBuf;
|
||||||
|
unsigned int CmtBufSize;
|
||||||
|
unsigned int CmtSize;
|
||||||
|
unsigned int CmtState;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct RARHeaderDataEx
|
||||||
|
{
|
||||||
|
char ArcName[1024];
|
||||||
|
wchar_t ArcNameW[1024];
|
||||||
|
char FileName[1024];
|
||||||
|
wchar_t FileNameW[1024];
|
||||||
|
unsigned int Flags;
|
||||||
|
unsigned int PackSize;
|
||||||
|
unsigned int PackSizeHigh;
|
||||||
|
unsigned int UnpSize;
|
||||||
|
unsigned int UnpSizeHigh;
|
||||||
|
unsigned int HostOS;
|
||||||
|
unsigned int FileCRC;
|
||||||
|
unsigned int FileTime;
|
||||||
|
unsigned int UnpVer;
|
||||||
|
unsigned int Method;
|
||||||
|
unsigned int FileAttr;
|
||||||
|
char *CmtBuf;
|
||||||
|
unsigned int CmtBufSize;
|
||||||
|
unsigned int CmtSize;
|
||||||
|
unsigned int CmtState;
|
||||||
|
unsigned int DictSize;
|
||||||
|
unsigned int HashType;
|
||||||
|
char Hash[32];
|
||||||
|
unsigned int RedirType;
|
||||||
|
wchar_t *RedirName;
|
||||||
|
unsigned int RedirNameSize;
|
||||||
|
unsigned int DirTarget;
|
||||||
|
unsigned int MtimeLow;
|
||||||
|
unsigned int MtimeHigh;
|
||||||
|
unsigned int CtimeLow;
|
||||||
|
unsigned int CtimeHigh;
|
||||||
|
unsigned int AtimeLow;
|
||||||
|
unsigned int AtimeHigh;
|
||||||
|
unsigned int Reserved[988];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct RAROpenArchiveData
|
||||||
|
{
|
||||||
|
char *ArcName;
|
||||||
|
unsigned int OpenMode;
|
||||||
|
unsigned int OpenResult;
|
||||||
|
char *CmtBuf;
|
||||||
|
unsigned int CmtBufSize;
|
||||||
|
unsigned int CmtSize;
|
||||||
|
unsigned int CmtState;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
|
||||||
|
|
||||||
|
#define ROADF_VOLUME 0x0001
|
||||||
|
#define ROADF_COMMENT 0x0002
|
||||||
|
#define ROADF_LOCK 0x0004
|
||||||
|
#define ROADF_SOLID 0x0008
|
||||||
|
#define ROADF_NEWNUMBERING 0x0010
|
||||||
|
#define ROADF_SIGNED 0x0020
|
||||||
|
#define ROADF_RECOVERY 0x0040
|
||||||
|
#define ROADF_ENCHEADERS 0x0080
|
||||||
|
#define ROADF_FIRSTVOLUME 0x0100
|
||||||
|
|
||||||
|
#define ROADOF_KEEPBROKEN 0x0001
|
||||||
|
|
||||||
|
struct RAROpenArchiveDataEx
|
||||||
|
{
|
||||||
|
char *ArcName;
|
||||||
|
wchar_t *ArcNameW;
|
||||||
|
unsigned int OpenMode;
|
||||||
|
unsigned int OpenResult;
|
||||||
|
char *CmtBuf;
|
||||||
|
unsigned int CmtBufSize;
|
||||||
|
unsigned int CmtSize;
|
||||||
|
unsigned int CmtState;
|
||||||
|
unsigned int Flags;
|
||||||
|
UNRARCALLBACK Callback;
|
||||||
|
LPARAM UserData;
|
||||||
|
unsigned int OpFlags;
|
||||||
|
wchar_t *CmtBufW;
|
||||||
|
unsigned int Reserved[25];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum UNRARCALLBACK_MESSAGES {
|
||||||
|
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD,UCM_CHANGEVOLUMEW,
|
||||||
|
UCM_NEEDPASSWORDW
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
|
||||||
|
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData);
|
||||||
|
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData);
|
||||||
|
int PASCAL RARCloseArchive(HANDLE hArcData);
|
||||||
|
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
|
||||||
|
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
|
||||||
|
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
|
||||||
|
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName);
|
||||||
|
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
|
||||||
|
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
|
||||||
|
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
|
||||||
|
void PASCAL RARSetPassword(HANDLE hArcData,char *Password);
|
||||||
|
int PASCAL RARGetDllVersion();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif
|
28
deps/unrar/dll.rc
vendored
Normal file
28
deps/unrar/dll.rc
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 5, 91, 100, 3470
|
||||||
|
PRODUCTVERSION 5, 91, 100, 3470
|
||||||
|
FILEOS VOS__WINDOWS32
|
||||||
|
FILETYPE VFT_APP
|
||||||
|
{
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
{
|
||||||
|
BLOCK "040904E4"
|
||||||
|
{
|
||||||
|
VALUE "CompanyName", "Alexander Roshal\0"
|
||||||
|
VALUE "ProductName", "RAR decompression library\0"
|
||||||
|
VALUE "FileDescription", "RAR decompression library\0"
|
||||||
|
VALUE "FileVersion", "5.91.0\0"
|
||||||
|
VALUE "ProductVersion", "5.91.0\0"
|
||||||
|
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2020\0"
|
||||||
|
VALUE "OriginalFilename", "Unrar.dll\0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
{
|
||||||
|
VALUE "Translation", 0x0409, 0x04E4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
13
deps/unrar/dll_nocrypt.def
vendored
Normal file
13
deps/unrar/dll_nocrypt.def
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
EXPORTS
|
||||||
|
RAROpenArchive
|
||||||
|
RAROpenArchiveEx
|
||||||
|
RARCloseArchive
|
||||||
|
RARReadHeader
|
||||||
|
RARReadHeaderEx
|
||||||
|
RARProcessFile
|
||||||
|
RARProcessFileW
|
||||||
|
RARSetCallback
|
||||||
|
RARSetChangeVolProc
|
||||||
|
RARSetProcessDataProc
|
||||||
|
; RARSetPassword
|
||||||
|
RARGetDllVersion
|
69
deps/unrar/encname.cpp
vendored
Normal file
69
deps/unrar/encname.cpp
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
EncodeFileName::EncodeFileName()
|
||||||
|
{
|
||||||
|
Flags=0;
|
||||||
|
FlagBits=0;
|
||||||
|
FlagsPos=0;
|
||||||
|
DestSize=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void EncodeFileName::Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize,
|
||||||
|
wchar *NameW,size_t MaxDecSize)
|
||||||
|
{
|
||||||
|
size_t EncPos=0,DecPos=0;
|
||||||
|
byte HighByte=EncPos<EncSize ? EncName[EncPos++] : 0;
|
||||||
|
while (EncPos<EncSize && DecPos<MaxDecSize)
|
||||||
|
{
|
||||||
|
if (FlagBits==0)
|
||||||
|
{
|
||||||
|
if (EncPos>=EncSize)
|
||||||
|
break;
|
||||||
|
Flags=EncName[EncPos++];
|
||||||
|
FlagBits=8;
|
||||||
|
}
|
||||||
|
switch(Flags>>6)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (EncPos>=EncSize)
|
||||||
|
break;
|
||||||
|
NameW[DecPos++]=EncName[EncPos++];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (EncPos>=EncSize)
|
||||||
|
break;
|
||||||
|
NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (EncPos+1>=EncSize)
|
||||||
|
break;
|
||||||
|
NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8);
|
||||||
|
EncPos+=2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (EncPos>=EncSize)
|
||||||
|
break;
|
||||||
|
int Length=EncName[EncPos++];
|
||||||
|
if ((Length & 0x80)!=0)
|
||||||
|
{
|
||||||
|
if (EncPos>=EncSize)
|
||||||
|
break;
|
||||||
|
byte Correction=EncName[EncPos++];
|
||||||
|
for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize && DecPos<NameSize;Length--,DecPos++)
|
||||||
|
NameW[DecPos]=((Name[DecPos]+Correction)&0xff)+(HighByte<<8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (Length+=2;Length>0 && DecPos<MaxDecSize && DecPos<NameSize;Length--,DecPos++)
|
||||||
|
NameW[DecPos]=Name[DecPos];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Flags<<=2;
|
||||||
|
FlagBits-=2;
|
||||||
|
}
|
||||||
|
NameW[DecPos<MaxDecSize ? DecPos:MaxDecSize-1]=0;
|
||||||
|
}
|
20
deps/unrar/encname.hpp
vendored
Normal file
20
deps/unrar/encname.hpp
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _RAR_ENCNAME_
|
||||||
|
#define _RAR_ENCNAME_
|
||||||
|
|
||||||
|
class EncodeFileName
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void AddFlags(int Value);
|
||||||
|
|
||||||
|
byte *EncName;
|
||||||
|
byte Flags;
|
||||||
|
uint FlagBits;
|
||||||
|
size_t FlagsPos;
|
||||||
|
size_t DestSize;
|
||||||
|
public:
|
||||||
|
EncodeFileName();
|
||||||
|
size_t Encode(char *Name,wchar *NameW,byte *EncName);
|
||||||
|
void Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
409
deps/unrar/errhnd.cpp
vendored
Normal file
409
deps/unrar/errhnd.cpp
vendored
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
ErrorHandler::ErrorHandler()
|
||||||
|
{
|
||||||
|
Clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::Clean()
|
||||||
|
{
|
||||||
|
ExitCode=RARX_SUCCESS;
|
||||||
|
ErrCount=0;
|
||||||
|
EnableBreak=true;
|
||||||
|
Silent=false;
|
||||||
|
UserBreak=false;
|
||||||
|
MainExit=false;
|
||||||
|
DisableShutdown=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::MemoryError()
|
||||||
|
{
|
||||||
|
MemoryErrorMsg();
|
||||||
|
Exit(RARX_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::OpenError(const wchar *FileName)
|
||||||
|
{
|
||||||
|
#ifndef SILENT
|
||||||
|
OpenErrorMsg(FileName);
|
||||||
|
Exit(RARX_OPEN);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::CloseError(const wchar *FileName)
|
||||||
|
{
|
||||||
|
if (!UserBreak)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_FILECLOSE,FileName);
|
||||||
|
SysErrMsg();
|
||||||
|
}
|
||||||
|
// We must not call Exit and throw an exception here, because this function
|
||||||
|
// is called from File object destructor and can be invoked when stack
|
||||||
|
// unwinding while handling another exception. Throwing a new exception
|
||||||
|
// when stack unwinding is prohibited and terminates a program.
|
||||||
|
// If necessary, we can check std::uncaught_exception() before throw.
|
||||||
|
SetErrorCode(RARX_FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::ReadError(const wchar *FileName)
|
||||||
|
{
|
||||||
|
#ifndef SILENT
|
||||||
|
ReadErrorMsg(FileName);
|
||||||
|
#endif
|
||||||
|
#if !defined(SILENT) || defined(RARDLL)
|
||||||
|
Exit(RARX_FATAL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ErrorHandler::AskRepeatRead(const wchar *FileName)
|
||||||
|
{
|
||||||
|
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||||
|
if (!Silent)
|
||||||
|
{
|
||||||
|
SysErrMsg();
|
||||||
|
bool Repeat=uiAskRepeatRead(FileName);
|
||||||
|
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
|
||||||
|
DisableShutdown=true;
|
||||||
|
return Repeat;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::WriteError(const wchar *ArcName,const wchar *FileName)
|
||||||
|
{
|
||||||
|
#ifndef SILENT
|
||||||
|
WriteErrorMsg(ArcName,FileName);
|
||||||
|
#endif
|
||||||
|
#if !defined(SILENT) || defined(RARDLL)
|
||||||
|
Exit(RARX_WRITE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
void ErrorHandler::WriteErrorFAT(const wchar *FileName)
|
||||||
|
{
|
||||||
|
SysErrMsg();
|
||||||
|
uiMsg(UIERROR_NTFSREQUIRED,FileName);
|
||||||
|
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
|
||||||
|
Exit(RARX_WRITE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool ErrorHandler::AskRepeatWrite(const wchar *FileName,bool DiskFull)
|
||||||
|
{
|
||||||
|
#ifndef SILENT
|
||||||
|
if (!Silent)
|
||||||
|
{
|
||||||
|
// We do not display "repeat write" prompt in Android, so we do not
|
||||||
|
// need the matching system error message.
|
||||||
|
SysErrMsg();
|
||||||
|
bool Repeat=uiAskRepeatWrite(FileName,DiskFull);
|
||||||
|
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
|
||||||
|
DisableShutdown=true;
|
||||||
|
return Repeat;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::SeekError(const wchar *FileName)
|
||||||
|
{
|
||||||
|
if (!UserBreak)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_FILESEEK,FileName);
|
||||||
|
SysErrMsg();
|
||||||
|
}
|
||||||
|
#if !defined(SILENT) || defined(RARDLL)
|
||||||
|
Exit(RARX_FATAL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::GeneralErrMsg(const wchar *fmt,...)
|
||||||
|
{
|
||||||
|
va_list arglist;
|
||||||
|
va_start(arglist,fmt);
|
||||||
|
wchar Msg[1024];
|
||||||
|
vswprintf(Msg,ASIZE(Msg),fmt,arglist);
|
||||||
|
uiMsg(UIERROR_GENERALERRMSG,Msg);
|
||||||
|
SysErrMsg();
|
||||||
|
va_end(arglist);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::MemoryErrorMsg()
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_MEMORY);
|
||||||
|
SetErrorCode(RARX_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::OpenErrorMsg(const wchar *FileName)
|
||||||
|
{
|
||||||
|
OpenErrorMsg(NULL,FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||||
|
{
|
||||||
|
Wait(); // Keep GUI responsive if many files cannot be opened when archiving.
|
||||||
|
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
|
||||||
|
SysErrMsg();
|
||||||
|
SetErrorCode(RARX_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::CreateErrorMsg(const wchar *FileName)
|
||||||
|
{
|
||||||
|
CreateErrorMsg(NULL,FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::CreateErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_FILECREATE,ArcName,FileName);
|
||||||
|
SysErrMsg();
|
||||||
|
SetErrorCode(RARX_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::ReadErrorMsg(const wchar *FileName)
|
||||||
|
{
|
||||||
|
ReadErrorMsg(NULL,FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::ReadErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_FILEREAD,ArcName,FileName);
|
||||||
|
SysErrMsg();
|
||||||
|
SetErrorCode(RARX_FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::WriteErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_FILEWRITE,ArcName,FileName);
|
||||||
|
SysErrMsg();
|
||||||
|
SetErrorCode(RARX_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::ArcBrokenMsg(const wchar *ArcName)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_ARCBROKEN,ArcName);
|
||||||
|
SetErrorCode(RARX_CRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_CHECKSUM,ArcName,FileName);
|
||||||
|
SetErrorCode(RARX_CRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::UnknownMethodMsg(const wchar *ArcName,const wchar *FileName)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_UNKNOWNMETHOD,ArcName,FileName);
|
||||||
|
ErrHandler.SetErrorCode(RARX_FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::Exit(RAR_EXIT ExitCode)
|
||||||
|
{
|
||||||
|
uiAlarm(UIALARM_ERROR);
|
||||||
|
Throw(ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::SetErrorCode(RAR_EXIT Code)
|
||||||
|
{
|
||||||
|
switch(Code)
|
||||||
|
{
|
||||||
|
case RARX_WARNING:
|
||||||
|
case RARX_USERBREAK:
|
||||||
|
if (ExitCode==RARX_SUCCESS)
|
||||||
|
ExitCode=Code;
|
||||||
|
break;
|
||||||
|
case RARX_CRC:
|
||||||
|
if (ExitCode!=RARX_BADPWD)
|
||||||
|
ExitCode=Code;
|
||||||
|
break;
|
||||||
|
case RARX_FATAL:
|
||||||
|
if (ExitCode==RARX_SUCCESS || ExitCode==RARX_WARNING)
|
||||||
|
ExitCode=RARX_FATAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ExitCode=Code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ErrCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
BOOL __stdcall ProcessSignal(DWORD SigType)
|
||||||
|
#else
|
||||||
|
#if defined(__sun)
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
void _stdfunction ProcessSignal(int SigType)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// When a console application is run as a service, this allows the service
|
||||||
|
// to continue running after the user logs off.
|
||||||
|
if (SigType==CTRL_LOGOFF_EVENT)
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ErrHandler.UserBreak=true;
|
||||||
|
ErrHandler.SetDisableShutdown();
|
||||||
|
mprintf(St(MBreak));
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// Let the main thread to handle 'throw' and destroy file objects.
|
||||||
|
for (uint I=0;!ErrHandler.MainExit && I<50;I++)
|
||||||
|
Sleep(100);
|
||||||
|
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(RARDLL)
|
||||||
|
ExtRes.UnloadDLL();
|
||||||
|
#endif
|
||||||
|
exit(RARX_USERBREAK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _UNIX
|
||||||
|
static uint BreakCount=0;
|
||||||
|
// User continues to press Ctrl+C, exit immediately without cleanup.
|
||||||
|
if (++BreakCount>1)
|
||||||
|
exit(RARX_USERBREAK);
|
||||||
|
// Otherwise return from signal handler and let Wait() function to close
|
||||||
|
// files and quit. We cannot use the same approach as in Windows,
|
||||||
|
// because Unix signal handler can block execution of our main code.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(_MSC_VER)
|
||||||
|
// Never reached, just to avoid a compiler warning
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::SetSignalHandlers(bool Enable)
|
||||||
|
{
|
||||||
|
EnableBreak=Enable;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
SetConsoleCtrlHandler(Enable ? ProcessSignal:NULL,TRUE);
|
||||||
|
#else
|
||||||
|
signal(SIGINT,Enable ? ProcessSignal:SIG_IGN);
|
||||||
|
signal(SIGTERM,Enable ? ProcessSignal:SIG_IGN);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::Throw(RAR_EXIT Code)
|
||||||
|
{
|
||||||
|
if (Code==RARX_USERBREAK && !EnableBreak)
|
||||||
|
return;
|
||||||
|
#if !defined(SILENT)
|
||||||
|
// Do not write "aborted" when just displaying online help.
|
||||||
|
if (Code!=RARX_SUCCESS && Code!=RARX_USERERROR)
|
||||||
|
mprintf(L"\n%s\n",St(MProgAborted));
|
||||||
|
#endif
|
||||||
|
SetErrorCode(Code);
|
||||||
|
throw Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
|
||||||
|
{
|
||||||
|
#ifndef SILENT
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
int ErrType=GetLastError();
|
||||||
|
if (ErrType!=0)
|
||||||
|
return FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,ErrType,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
|
||||||
|
Msg,(DWORD)Size,NULL)!=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_UNIX) || defined(_EMX)
|
||||||
|
if (errno!=0)
|
||||||
|
{
|
||||||
|
char *err=strerror(errno);
|
||||||
|
if (err!=NULL)
|
||||||
|
{
|
||||||
|
CharToWide(err,Msg,Size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::SysErrMsg()
|
||||||
|
{
|
||||||
|
#if !defined(SFX_MODULE) && !defined(SILENT)
|
||||||
|
wchar Msg[1024];
|
||||||
|
if (!GetSysErrMsg(Msg,ASIZE(Msg)))
|
||||||
|
return;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
wchar *CurMsg=Msg;
|
||||||
|
while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines.
|
||||||
|
{
|
||||||
|
while (*CurMsg=='\r' || *CurMsg=='\n')
|
||||||
|
CurMsg++;
|
||||||
|
if (*CurMsg==0)
|
||||||
|
break;
|
||||||
|
wchar *EndMsg=wcschr(CurMsg,'\r');
|
||||||
|
if (EndMsg==NULL)
|
||||||
|
EndMsg=wcschr(CurMsg,'\n');
|
||||||
|
if (EndMsg!=NULL)
|
||||||
|
{
|
||||||
|
*EndMsg=0;
|
||||||
|
EndMsg++;
|
||||||
|
}
|
||||||
|
uiMsg(UIERROR_SYSERRMSG,CurMsg);
|
||||||
|
CurMsg=EndMsg;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_UNIX) || defined(_EMX)
|
||||||
|
uiMsg(UIERROR_SYSERRMSG,Msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ErrorHandler::GetSystemErrorCode()
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
return GetLastError();
|
||||||
|
#else
|
||||||
|
return errno;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorHandler::SetSystemErrorCode(int Code)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
SetLastError(Code);
|
||||||
|
#else
|
||||||
|
errno=Code;
|
||||||
|
#endif
|
||||||
|
}
|
72
deps/unrar/errhnd.hpp
vendored
Normal file
72
deps/unrar/errhnd.hpp
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#ifndef _RAR_ERRHANDLER_
|
||||||
|
#define _RAR_ERRHANDLER_
|
||||||
|
|
||||||
|
enum RAR_EXIT // RAR exit code.
|
||||||
|
{
|
||||||
|
RARX_SUCCESS = 0,
|
||||||
|
RARX_WARNING = 1,
|
||||||
|
RARX_FATAL = 2,
|
||||||
|
RARX_CRC = 3,
|
||||||
|
RARX_LOCK = 4,
|
||||||
|
RARX_WRITE = 5,
|
||||||
|
RARX_OPEN = 6,
|
||||||
|
RARX_USERERROR = 7,
|
||||||
|
RARX_MEMORY = 8,
|
||||||
|
RARX_CREATE = 9,
|
||||||
|
RARX_NOFILES = 10,
|
||||||
|
RARX_BADPWD = 11,
|
||||||
|
RARX_USERBREAK = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
class ErrorHandler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
RAR_EXIT ExitCode;
|
||||||
|
uint ErrCount;
|
||||||
|
bool EnableBreak;
|
||||||
|
bool Silent;
|
||||||
|
bool DisableShutdown; // Shutdown is not suitable after last error.
|
||||||
|
public:
|
||||||
|
ErrorHandler();
|
||||||
|
void Clean();
|
||||||
|
void MemoryError();
|
||||||
|
void OpenError(const wchar *FileName);
|
||||||
|
void CloseError(const wchar *FileName);
|
||||||
|
void ReadError(const wchar *FileName);
|
||||||
|
bool AskRepeatRead(const wchar *FileName);
|
||||||
|
void WriteError(const wchar *ArcName,const wchar *FileName);
|
||||||
|
void WriteErrorFAT(const wchar *FileName);
|
||||||
|
bool AskRepeatWrite(const wchar *FileName,bool DiskFull);
|
||||||
|
void SeekError(const wchar *FileName);
|
||||||
|
void GeneralErrMsg(const wchar *fmt,...);
|
||||||
|
void MemoryErrorMsg();
|
||||||
|
void OpenErrorMsg(const wchar *FileName);
|
||||||
|
void OpenErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||||
|
void CreateErrorMsg(const wchar *FileName);
|
||||||
|
void CreateErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||||
|
void ReadErrorMsg(const wchar *FileName);
|
||||||
|
void ReadErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||||
|
void WriteErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||||
|
void ArcBrokenMsg(const wchar *ArcName);
|
||||||
|
void ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName);
|
||||||
|
void UnknownMethodMsg(const wchar *ArcName,const wchar *FileName);
|
||||||
|
void Exit(RAR_EXIT ExitCode);
|
||||||
|
void SetErrorCode(RAR_EXIT Code);
|
||||||
|
RAR_EXIT GetErrorCode() {return ExitCode;}
|
||||||
|
uint GetErrorCount() {return ErrCount;}
|
||||||
|
void SetSignalHandlers(bool Enable);
|
||||||
|
void Throw(RAR_EXIT Code);
|
||||||
|
void SetSilent(bool Mode) {Silent=Mode;}
|
||||||
|
bool GetSysErrMsg(wchar *Msg,size_t Size);
|
||||||
|
void SysErrMsg();
|
||||||
|
int GetSystemErrorCode();
|
||||||
|
void SetSystemErrorCode(int Code);
|
||||||
|
void SetDisableShutdown() {DisableShutdown=true;}
|
||||||
|
bool IsShutdownEnabled() {return !DisableShutdown;}
|
||||||
|
|
||||||
|
bool UserBreak; // Ctrl+Break is pressed.
|
||||||
|
bool MainExit; // main() is completed.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
178
deps/unrar/extinfo.cpp
vendored
Normal file
178
deps/unrar/extinfo.cpp
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#include "hardlinks.cpp"
|
||||||
|
#include "win32stm.cpp"
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
#include "win32acl.cpp"
|
||||||
|
#include "win32lnk.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _UNIX
|
||||||
|
#include "uowners.cpp"
|
||||||
|
#ifdef SAVE_LINKS
|
||||||
|
#include "ulinks.cpp"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// RAR2 service header extra records.
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name)
|
||||||
|
{
|
||||||
|
if (Cmd->Test)
|
||||||
|
return;
|
||||||
|
switch(Arc.SubBlockHead.SubType)
|
||||||
|
{
|
||||||
|
#ifdef _UNIX
|
||||||
|
case UO_HEAD:
|
||||||
|
if (Cmd->ProcessOwners)
|
||||||
|
ExtractUnixOwner20(Arc,Name);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
case NTACL_HEAD:
|
||||||
|
if (Cmd->ProcessOwners)
|
||||||
|
ExtractACL20(Arc,Name);
|
||||||
|
break;
|
||||||
|
case STREAM_HEAD:
|
||||||
|
ExtractStreams20(Arc,Name);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// RAR3 and RAR5 service header extra records.
|
||||||
|
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name)
|
||||||
|
{
|
||||||
|
#ifdef _UNIX
|
||||||
|
if (!Cmd->Test && Cmd->ProcessOwners && Arc.Format==RARFMT15 &&
|
||||||
|
Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
|
||||||
|
ExtractUnixOwner30(Arc,Name);
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
if (!Cmd->Test && Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
|
||||||
|
ExtractACL(Arc,Name);
|
||||||
|
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
|
||||||
|
ExtractStreams(Arc,Name,Cmd->Test);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Extra data stored directly in file header.
|
||||||
|
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name)
|
||||||
|
{
|
||||||
|
#ifdef _UNIX
|
||||||
|
if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet)
|
||||||
|
SetUnixOwner(Arc,Name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate a number of path components except \. and \..
|
||||||
|
static int CalcAllowedDepth(const wchar *Name)
|
||||||
|
{
|
||||||
|
int AllowedDepth=0;
|
||||||
|
while (*Name!=0)
|
||||||
|
{
|
||||||
|
if (IsPathDiv(Name[0]) && Name[1]!=0 && !IsPathDiv(Name[1]))
|
||||||
|
{
|
||||||
|
bool Dot=Name[1]=='.' && (IsPathDiv(Name[2]) || Name[2]==0);
|
||||||
|
bool Dot2=Name[1]=='.' && Name[2]=='.' && (IsPathDiv(Name[3]) || Name[3]==0);
|
||||||
|
if (!Dot && !Dot2)
|
||||||
|
AllowedDepth++;
|
||||||
|
}
|
||||||
|
Name++;
|
||||||
|
}
|
||||||
|
return AllowedDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check if all existing path components are directories and not links.
|
||||||
|
static bool LinkInPath(const wchar *Name)
|
||||||
|
{
|
||||||
|
wchar Path[NM];
|
||||||
|
if (wcslen(Name)>=ASIZE(Path))
|
||||||
|
return true; // It should not be that long, skip.
|
||||||
|
wcsncpyz(Path,Name,ASIZE(Path));
|
||||||
|
for (wchar *s=Path+wcslen(Path)-1;s>Path;s--)
|
||||||
|
if (IsPathDiv(*s))
|
||||||
|
{
|
||||||
|
*s=0;
|
||||||
|
FindData FD;
|
||||||
|
if (FindFile::FastFind(Path,&FD,true) && (FD.IsLink || !FD.IsDir))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
|
||||||
|
{
|
||||||
|
// Catch root dir based /path/file paths also as stuff like \\?\.
|
||||||
|
// Do not check PrepSrcName here, it can be root based if destination path
|
||||||
|
// is a root based.
|
||||||
|
if (IsFullRootPath(SrcName) || IsFullRootPath(TargetName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Number of ".." in link target.
|
||||||
|
int UpLevels=0;
|
||||||
|
for (int Pos=0;*TargetName!=0;Pos++)
|
||||||
|
{
|
||||||
|
bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' &&
|
||||||
|
(IsPathDiv(TargetName[2]) || TargetName[2]==0) &&
|
||||||
|
(Pos==0 || IsPathDiv(*(TargetName-1)));
|
||||||
|
if (Dot2)
|
||||||
|
UpLevels++;
|
||||||
|
TargetName++;
|
||||||
|
}
|
||||||
|
// If link target includes "..", it must not have another links
|
||||||
|
// in the path, because they can bypass our safety check. For example,
|
||||||
|
// suppose we extracted "lnk1" -> "." first and "lnk1/lnk2" -> ".." next
|
||||||
|
// or "dir/lnk1" -> ".." first and "dir/lnk1/lnk2" -> ".." next.
|
||||||
|
if (UpLevels>0 && LinkInPath(PrepSrcName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We could check just prepared src name, but for extra safety
|
||||||
|
// we check both original (as from archive header) and prepared
|
||||||
|
// (after applying the destination path and -ep switches) names.
|
||||||
|
|
||||||
|
int AllowedDepth=CalcAllowedDepth(SrcName); // Original name depth.
|
||||||
|
|
||||||
|
// Remove the destination path from prepared name if any. We should not
|
||||||
|
// count the destination path depth, because the link target must point
|
||||||
|
// inside of this path, not outside of it.
|
||||||
|
size_t ExtrPathLength=wcslen(Cmd->ExtrPath);
|
||||||
|
if (ExtrPathLength>0 && wcsncmp(PrepSrcName,Cmd->ExtrPath,ExtrPathLength)==0)
|
||||||
|
{
|
||||||
|
PrepSrcName+=ExtrPathLength;
|
||||||
|
while (IsPathDiv(*PrepSrcName))
|
||||||
|
PrepSrcName++;
|
||||||
|
}
|
||||||
|
int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName);
|
||||||
|
|
||||||
|
return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName)
|
||||||
|
{
|
||||||
|
#if defined(SAVE_LINKS) && defined(_UNIX)
|
||||||
|
// For RAR 3.x archives we process links even in test mode to skip link data.
|
||||||
|
if (Arc.Format==RARFMT15)
|
||||||
|
return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName);
|
||||||
|
if (Arc.Format==RARFMT50)
|
||||||
|
return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead);
|
||||||
|
#elif defined _WIN_ALL
|
||||||
|
// RAR 5.0 archives store link information in file header, so there is
|
||||||
|
// no need to additionally test it if we do not create a file.
|
||||||
|
if (Arc.Format==RARFMT50)
|
||||||
|
return CreateReparsePoint(Cmd,LinkName,&Arc.FileHead);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
23
deps/unrar/extinfo.hpp
vendored
Normal file
23
deps/unrar/extinfo.hpp
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _RAR_EXTINFO_
|
||||||
|
#define _RAR_EXTINFO_
|
||||||
|
|
||||||
|
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName);
|
||||||
|
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName);
|
||||||
|
#ifdef _UNIX
|
||||||
|
void SetUnixOwner(Archive &Arc,const wchar *FileName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
|
||||||
|
|
||||||
|
void GetStreamNameNTFS(Archive &Arc,wchar *StreamName,size_t MaxSize);
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool SetPrivilege(LPCTSTR PrivName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name);
|
||||||
|
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name);
|
||||||
|
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
1198
deps/unrar/extract.cpp
vendored
Normal file
1198
deps/unrar/extract.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
62
deps/unrar/extract.hpp
vendored
Normal file
62
deps/unrar/extract.hpp
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef _RAR_EXTRACT_
|
||||||
|
#define _RAR_EXTRACT_
|
||||||
|
|
||||||
|
enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
|
||||||
|
|
||||||
|
class CmdExtract
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
EXTRACT_ARC_CODE ExtractArchive();
|
||||||
|
bool ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
|
||||||
|
void ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize);
|
||||||
|
#ifdef RARDLL
|
||||||
|
bool ExtrDllGetPassword();
|
||||||
|
#else
|
||||||
|
bool ExtrGetPassword(Archive &Arc,const wchar *ArcFileName);
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
|
void ConvertDosPassword(Archive &Arc,SecPassword &DestPwd);
|
||||||
|
#endif
|
||||||
|
void ExtrCreateDir(Archive &Arc,const wchar *ArcFileName);
|
||||||
|
bool ExtrCreateFile(Archive &Arc,File &CurFile);
|
||||||
|
bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName);
|
||||||
|
|
||||||
|
RarTime StartTime; // time when extraction started
|
||||||
|
|
||||||
|
CommandData *Cmd;
|
||||||
|
|
||||||
|
ComprDataIO DataIO;
|
||||||
|
Unpack *Unp;
|
||||||
|
unsigned long TotalFileCount;
|
||||||
|
|
||||||
|
unsigned long FileCount;
|
||||||
|
unsigned long MatchedArgs;
|
||||||
|
bool FirstFile;
|
||||||
|
bool AllMatchesExact;
|
||||||
|
bool ReconstructDone;
|
||||||
|
|
||||||
|
// If any non-zero solid file was successfully unpacked before current.
|
||||||
|
// If true and if current encrypted file is broken, obviously
|
||||||
|
// the password is correct and we can report broken CRC without
|
||||||
|
// any wrong password hints.
|
||||||
|
bool AnySolidDataUnpackedWell;
|
||||||
|
|
||||||
|
wchar ArcName[NM];
|
||||||
|
|
||||||
|
bool GlobalPassword;
|
||||||
|
bool PrevProcessed; // If previous file was successfully extracted or tested.
|
||||||
|
wchar DestFileName[NM];
|
||||||
|
bool PasswordCancelled;
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
|
||||||
|
bool Fat32,NotFat32;
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
CmdExtract(CommandData *Cmd);
|
||||||
|
~CmdExtract();
|
||||||
|
void DoExtract();
|
||||||
|
void ExtractArchiveInit(Archive &Arc);
|
||||||
|
bool ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat);
|
||||||
|
static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
163
deps/unrar/filcreat.cpp
vendored
Normal file
163
deps/unrar/filcreat.cpp
vendored
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
// If NewFile==NULL, we delete created file after user confirmation.
|
||||||
|
// It is useful we we need to overwrite an existing folder or file,
|
||||||
|
// but need user confirmation for that.
|
||||||
|
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||||
|
bool *UserReject,int64 FileSize,RarTime *FileTime,bool WriteOnly)
|
||||||
|
{
|
||||||
|
if (UserReject!=NULL)
|
||||||
|
*UserReject=false;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool ShortNameChanged=false;
|
||||||
|
#endif
|
||||||
|
while (FileExist(Name))
|
||||||
|
{
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
if (!ShortNameChanged)
|
||||||
|
{
|
||||||
|
// Avoid the infinite loop if UpdateExistingShortName returns
|
||||||
|
// the same name.
|
||||||
|
ShortNameChanged=true;
|
||||||
|
|
||||||
|
// Maybe our long name matches the short name of existing file.
|
||||||
|
// Let's check if we can change the short name.
|
||||||
|
if (UpdateExistingShortName(Name))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Allow short name check again. It is necessary, because rename and
|
||||||
|
// autorename below can change the name, so we need to check it again.
|
||||||
|
ShortNameChanged=false;
|
||||||
|
#endif
|
||||||
|
UIASKREP_RESULT Choice=uiAskReplaceEx(Cmd,Name,MaxNameSize,FileSize,FileTime,(NewFile==NULL ? UIASKREP_F_NORENAME:0));
|
||||||
|
|
||||||
|
if (Choice==UIASKREP_R_REPLACE)
|
||||||
|
break;
|
||||||
|
if (Choice==UIASKREP_R_SKIP)
|
||||||
|
{
|
||||||
|
if (UserReject!=NULL)
|
||||||
|
*UserReject=true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Choice==UIASKREP_R_CANCEL)
|
||||||
|
ErrHandler.Exit(RARX_USERBREAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to truncate the existing file first instead of delete,
|
||||||
|
// so we preserve existing file permissions such as NTFS permissions.
|
||||||
|
uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
|
||||||
|
if (NewFile!=NULL && NewFile->Create(Name,FileMode))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CreatePath(Name,true);
|
||||||
|
return NewFile!=NULL ? NewFile->Create(Name,FileMode):DelFile(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize)
|
||||||
|
{
|
||||||
|
wchar NewName[NM];
|
||||||
|
size_t NameLength=wcslen(Name);
|
||||||
|
wchar *Ext=GetExt(Name);
|
||||||
|
if (Ext==NULL)
|
||||||
|
Ext=Name+NameLength;
|
||||||
|
for (uint FileVer=1;;FileVer++)
|
||||||
|
{
|
||||||
|
swprintf(NewName,ASIZE(NewName),L"%.*ls(%u)%ls",uint(Ext-Name),Name,FileVer,Ext);
|
||||||
|
if (!FileExist(NewName))
|
||||||
|
{
|
||||||
|
wcsncpyz(Name,NewName,MaxNameSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (FileVer>=1000000)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
// If we find a file, which short name is equal to 'Name', we try to change
|
||||||
|
// its short name, while preserving the long name. It helps when unpacking
|
||||||
|
// an archived file, which long name is equal to short name of already
|
||||||
|
// existing file. Otherwise we would overwrite the already existing file,
|
||||||
|
// even though its long name does not match the name of unpacking file.
|
||||||
|
bool UpdateExistingShortName(const wchar *Name)
|
||||||
|
{
|
||||||
|
wchar LongPathName[NM];
|
||||||
|
DWORD Res=GetLongPathName(Name,LongPathName,ASIZE(LongPathName));
|
||||||
|
if (Res==0 || Res>=ASIZE(LongPathName))
|
||||||
|
return false;
|
||||||
|
wchar ShortPathName[NM];
|
||||||
|
Res=GetShortPathName(Name,ShortPathName,ASIZE(ShortPathName));
|
||||||
|
if (Res==0 || Res>=ASIZE(ShortPathName))
|
||||||
|
return false;
|
||||||
|
wchar *LongName=PointToName(LongPathName);
|
||||||
|
wchar *ShortName=PointToName(ShortPathName);
|
||||||
|
|
||||||
|
// We continue only if file has a short name, which does not match its
|
||||||
|
// long name, and this short name is equal to name of file which we need
|
||||||
|
// to create.
|
||||||
|
if (*ShortName==0 || wcsicomp(LongName,ShortName)==0 ||
|
||||||
|
wcsicomp(PointToName(Name),ShortName)!=0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Generate the temporary new name for existing file.
|
||||||
|
wchar NewName[NM];
|
||||||
|
*NewName=0;
|
||||||
|
for (int I=0;I<10000 && *NewName==0;I+=123)
|
||||||
|
{
|
||||||
|
// Here we copy the path part of file to create. We'll make the temporary
|
||||||
|
// file in the same folder.
|
||||||
|
wcsncpyz(NewName,Name,ASIZE(NewName));
|
||||||
|
|
||||||
|
// Here we set the random name part.
|
||||||
|
swprintf(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
|
||||||
|
|
||||||
|
// If such file is already exist, try next random name.
|
||||||
|
if (FileExist(NewName))
|
||||||
|
*NewName=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we could not generate the name not used by any other file, we return.
|
||||||
|
if (*NewName==0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// FastFind returns the name without path, but we need the fully qualified
|
||||||
|
// name for renaming, so we use the path from file to create and long name
|
||||||
|
// from existing file.
|
||||||
|
wchar FullName[NM];
|
||||||
|
wcsncpyz(FullName,Name,ASIZE(FullName));
|
||||||
|
SetName(FullName,LongName,ASIZE(FullName));
|
||||||
|
|
||||||
|
// Rename the existing file to randomly generated name. Normally it changes
|
||||||
|
// the short name too.
|
||||||
|
if (!MoveFile(FullName,NewName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Now we need to create the temporary empty file with same name as
|
||||||
|
// short name of our already existing file. We do it to occupy its previous
|
||||||
|
// short name and not allow to use it again when renaming the file back to
|
||||||
|
// its original long name.
|
||||||
|
File KeepShortFile;
|
||||||
|
bool Created=false;
|
||||||
|
if (!FileExist(Name))
|
||||||
|
Created=KeepShortFile.Create(Name,FMF_WRITE|FMF_SHAREREAD);
|
||||||
|
|
||||||
|
// Now we rename the existing file from temporary name to original long name.
|
||||||
|
// Since its previous short name is occupied by another file, it should
|
||||||
|
// get another short name.
|
||||||
|
MoveFile(NewName,FullName);
|
||||||
|
|
||||||
|
if (Created)
|
||||||
|
{
|
||||||
|
// Delete the temporary zero length file occupying the short name,
|
||||||
|
KeepShortFile.Close();
|
||||||
|
KeepShortFile.Delete();
|
||||||
|
}
|
||||||
|
// We successfully changed the short name. Maybe sometimes we'll simplify
|
||||||
|
// this function by use of SetFileShortName Windows API call.
|
||||||
|
// But SetFileShortName is not available in older Windows.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
14
deps/unrar/filcreat.hpp
vendored
Normal file
14
deps/unrar/filcreat.hpp
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _RAR_FILECREATE_
|
||||||
|
#define _RAR_FILECREATE_
|
||||||
|
|
||||||
|
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||||
|
bool *UserReject,int64 FileSize=INT64NDF,
|
||||||
|
RarTime *FileTime=NULL,bool WriteOnly=false);
|
||||||
|
|
||||||
|
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize);
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
bool UpdateExistingShortName(const wchar *Name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
745
deps/unrar/file.cpp
vendored
Normal file
745
deps/unrar/file.cpp
vendored
Normal file
@ -0,0 +1,745 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
File::File()
|
||||||
|
{
|
||||||
|
hFile=FILE_BAD_HANDLE;
|
||||||
|
*FileName=0;
|
||||||
|
NewFile=false;
|
||||||
|
LastWrite=false;
|
||||||
|
HandleType=FILE_HANDLENORMAL;
|
||||||
|
SkipClose=false;
|
||||||
|
IgnoreReadErrors=false;
|
||||||
|
ErrorType=FILE_SUCCESS;
|
||||||
|
OpenShared=false;
|
||||||
|
AllowDelete=true;
|
||||||
|
AllowExceptions=true;
|
||||||
|
PreserveAtime=false;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
NoSequentialRead=false;
|
||||||
|
CreateMode=FMF_UNDEFINED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
File::~File()
|
||||||
|
{
|
||||||
|
if (hFile!=FILE_BAD_HANDLE && !SkipClose)
|
||||||
|
if (NewFile)
|
||||||
|
Delete();
|
||||||
|
else
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::operator = (File &SrcFile)
|
||||||
|
{
|
||||||
|
hFile=SrcFile.hFile;
|
||||||
|
NewFile=SrcFile.NewFile;
|
||||||
|
LastWrite=SrcFile.LastWrite;
|
||||||
|
HandleType=SrcFile.HandleType;
|
||||||
|
wcsncpyz(FileName,SrcFile.FileName,ASIZE(FileName));
|
||||||
|
SrcFile.SkipClose=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::Open(const wchar *Name,uint Mode)
|
||||||
|
{
|
||||||
|
ErrorType=FILE_SUCCESS;
|
||||||
|
FileHandle hNewFile;
|
||||||
|
bool OpenShared=File::OpenShared || (Mode & FMF_OPENSHARED)!=0;
|
||||||
|
bool UpdateMode=(Mode & FMF_UPDATE)!=0;
|
||||||
|
bool WriteMode=(Mode & FMF_WRITE)!=0;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ;
|
||||||
|
if (UpdateMode)
|
||||||
|
Access|=GENERIC_WRITE;
|
||||||
|
uint ShareMode=(Mode & FMF_OPENEXCLUSIVE) ? 0 : FILE_SHARE_READ;
|
||||||
|
if (OpenShared)
|
||||||
|
ShareMode|=FILE_SHARE_WRITE;
|
||||||
|
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
|
||||||
|
FindData FD;
|
||||||
|
if (PreserveAtime)
|
||||||
|
Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime.
|
||||||
|
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
||||||
|
|
||||||
|
DWORD LastError;
|
||||||
|
if (hNewFile==FILE_BAD_HANDLE)
|
||||||
|
{
|
||||||
|
LastError=GetLastError();
|
||||||
|
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
{
|
||||||
|
hNewFile=CreateFile(LongName,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
||||||
|
|
||||||
|
// For archive names longer than 260 characters first CreateFile
|
||||||
|
// (without \\?\) fails and sets LastError to 3 (access denied).
|
||||||
|
// We need the correct "file not found" error code to decide
|
||||||
|
// if we create a new archive or quit with "cannot create" error.
|
||||||
|
// So we need to check the error code after \\?\ CreateFile again,
|
||||||
|
// otherwise we'll fail to create new archives with long names.
|
||||||
|
// But we cannot simply assign the new code to LastError,
|
||||||
|
// because it would break "..\arcname.rar" relative names processing.
|
||||||
|
// First CreateFile returns the correct "file not found" code for such
|
||||||
|
// names, but "\\?\" CreateFile returns ERROR_INVALID_NAME treating
|
||||||
|
// dots as a directory name. So we check only for "file not found"
|
||||||
|
// error here and for other errors use the first CreateFile result.
|
||||||
|
if (GetLastError()==ERROR_FILE_NOT_FOUND)
|
||||||
|
LastError=ERROR_FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
|
||||||
|
ErrorType=FILE_NOTFOUND;
|
||||||
|
if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE)
|
||||||
|
{
|
||||||
|
FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification.
|
||||||
|
SetFileTime(hNewFile,NULL,&ft,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
|
||||||
|
#ifdef O_BINARY
|
||||||
|
flags|=O_BINARY;
|
||||||
|
#if defined(_AIX) && defined(_LARGE_FILE_API)
|
||||||
|
flags|=O_LARGEFILE;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
// NDK r20 has O_NOATIME, but fails to create files with it in Android 7+.
|
||||||
|
#if defined(O_NOATIME)
|
||||||
|
if (PreserveAtime)
|
||||||
|
flags|=O_NOATIME;
|
||||||
|
#endif
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
|
||||||
|
int handle=open(NameA,flags);
|
||||||
|
#ifdef LOCK_EX
|
||||||
|
|
||||||
|
#ifdef _OSF_SOURCE
|
||||||
|
extern "C" int flock(int, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!OpenShared && UpdateMode && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
|
||||||
|
{
|
||||||
|
close(handle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (handle==-1)
|
||||||
|
hNewFile=FILE_BAD_HANDLE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
hNewFile=handle;
|
||||||
|
#else
|
||||||
|
hNewFile=fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (hNewFile==FILE_BAD_HANDLE && errno==ENOENT)
|
||||||
|
ErrorType=FILE_NOTFOUND;
|
||||||
|
#endif
|
||||||
|
NewFile=false;
|
||||||
|
HandleType=FILE_HANDLENORMAL;
|
||||||
|
SkipClose=false;
|
||||||
|
bool Success=hNewFile!=FILE_BAD_HANDLE;
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
hFile=hNewFile;
|
||||||
|
wcsncpyz(FileName,Name,ASIZE(FileName));
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void File::TOpen(const wchar *Name)
|
||||||
|
{
|
||||||
|
if (!WOpen(Name))
|
||||||
|
ErrHandler.Exit(RARX_OPEN);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool File::WOpen(const wchar *Name)
|
||||||
|
{
|
||||||
|
if (Open(Name))
|
||||||
|
return true;
|
||||||
|
ErrHandler.OpenErrorMsg(Name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::Create(const wchar *Name,uint Mode)
|
||||||
|
{
|
||||||
|
// OpenIndiana based NAS and CIFS shares fail to set the file time if file
|
||||||
|
// was created in read+write mode and some data was written and not flushed
|
||||||
|
// before SetFileTime call. So we should use the write only mode if we plan
|
||||||
|
// SetFileTime call and do not need to read from file.
|
||||||
|
bool WriteMode=(Mode & FMF_WRITE)!=0;
|
||||||
|
bool ShareRead=(Mode & FMF_SHAREREAD)!=0 || File::OpenShared;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
CreateMode=Mode;
|
||||||
|
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ|GENERIC_WRITE;
|
||||||
|
DWORD ShareMode=ShareRead ? FILE_SHARE_READ:0;
|
||||||
|
|
||||||
|
// Windows automatically removes dots and spaces in the end of file name,
|
||||||
|
// So we detect such names and process them with \\?\ prefix.
|
||||||
|
wchar *LastChar=PointToLastChar(Name);
|
||||||
|
bool Special=*LastChar=='.' || *LastChar==' ';
|
||||||
|
|
||||||
|
if (Special && (Mode & FMF_STANDARDNAMES)==0)
|
||||||
|
hFile=FILE_BAD_HANDLE;
|
||||||
|
else
|
||||||
|
hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
|
||||||
|
|
||||||
|
if (hFile==FILE_BAD_HANDLE)
|
||||||
|
{
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
hFile=CreateFile(LongName,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
hFile=open(NameA,(O_CREAT|O_TRUNC) | (WriteMode ? O_WRONLY : O_RDWR),0666);
|
||||||
|
#else
|
||||||
|
hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
NewFile=true;
|
||||||
|
HandleType=FILE_HANDLENORMAL;
|
||||||
|
SkipClose=false;
|
||||||
|
wcsncpyz(FileName,Name,ASIZE(FileName));
|
||||||
|
return hFile!=FILE_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void File::TCreate(const wchar *Name,uint Mode)
|
||||||
|
{
|
||||||
|
if (!WCreate(Name,Mode))
|
||||||
|
ErrHandler.Exit(RARX_FATAL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool File::WCreate(const wchar *Name,uint Mode)
|
||||||
|
{
|
||||||
|
if (Create(Name,Mode))
|
||||||
|
return true;
|
||||||
|
ErrHandler.CreateErrorMsg(Name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::Close()
|
||||||
|
{
|
||||||
|
bool Success=true;
|
||||||
|
|
||||||
|
if (hFile!=FILE_BAD_HANDLE)
|
||||||
|
{
|
||||||
|
if (!SkipClose)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// We use the standard system handle for stdout in Windows
|
||||||
|
// and it must not be closed here.
|
||||||
|
if (HandleType==FILE_HANDLENORMAL)
|
||||||
|
Success=CloseHandle(hFile)==TRUE;
|
||||||
|
#else
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
Success=close(hFile)!=-1;
|
||||||
|
#else
|
||||||
|
Success=fclose(hFile)!=EOF;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
hFile=FILE_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
HandleType=FILE_HANDLENORMAL;
|
||||||
|
if (!Success && AllowExceptions)
|
||||||
|
ErrHandler.CloseError(FileName);
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::Delete()
|
||||||
|
{
|
||||||
|
if (HandleType!=FILE_HANDLENORMAL)
|
||||||
|
return false;
|
||||||
|
if (hFile!=FILE_BAD_HANDLE)
|
||||||
|
Close();
|
||||||
|
if (!AllowDelete)
|
||||||
|
return false;
|
||||||
|
return DelFile(FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::Rename(const wchar *NewName)
|
||||||
|
{
|
||||||
|
// No need to rename if names are already same.
|
||||||
|
bool Success=wcscmp(FileName,NewName)==0;
|
||||||
|
|
||||||
|
if (!Success)
|
||||||
|
Success=RenameFile(FileName,NewName);
|
||||||
|
|
||||||
|
if (Success)
|
||||||
|
wcsncpyz(FileName,NewName,ASIZE(FileName));
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::Write(const void *Data,size_t Size)
|
||||||
|
{
|
||||||
|
if (Size==0)
|
||||||
|
return true;
|
||||||
|
if (HandleType==FILE_HANDLESTD)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
hFile=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
#else
|
||||||
|
// Cannot use the standard stdout here, because it already has wide orientation.
|
||||||
|
if (hFile==FILE_BAD_HANDLE)
|
||||||
|
{
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
hFile=dup(STDOUT_FILENO); // Open new stdout stream.
|
||||||
|
#else
|
||||||
|
hFile=fdopen(dup(STDOUT_FILENO),"w"); // Open new stdout stream.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
bool Success;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
Success=false;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
DWORD Written=0;
|
||||||
|
if (HandleType!=FILE_HANDLENORMAL)
|
||||||
|
{
|
||||||
|
// writing to stdout can fail in old Windows if data block is too large
|
||||||
|
const size_t MaxSize=0x4000;
|
||||||
|
for (size_t I=0;I<Size;I+=MaxSize)
|
||||||
|
{
|
||||||
|
Success=WriteFile(hFile,(byte *)Data+I,(DWORD)Min(Size-I,MaxSize),&Written,NULL)==TRUE;
|
||||||
|
if (!Success)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Success=WriteFile(hFile,Data,(DWORD)Size,&Written,NULL)==TRUE;
|
||||||
|
#else
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
ssize_t Written=write(hFile,Data,Size);
|
||||||
|
Success=Written==Size;
|
||||||
|
#else
|
||||||
|
int Written=fwrite(Data,1,Size,hFile);
|
||||||
|
Success=Written==Size && !ferror(hFile);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
|
||||||
|
{
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(RARDLL)
|
||||||
|
int ErrCode=GetLastError();
|
||||||
|
int64 FilePos=Tell();
|
||||||
|
uint64 FreeSize=GetFreeDisk(FileName);
|
||||||
|
SetLastError(ErrCode);
|
||||||
|
if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
|
||||||
|
ErrHandler.WriteErrorFAT(FileName);
|
||||||
|
#endif
|
||||||
|
if (ErrHandler.AskRepeatWrite(FileName,false))
|
||||||
|
{
|
||||||
|
#if !defined(_WIN_ALL) && !defined(FILE_USE_OPEN)
|
||||||
|
clearerr(hFile);
|
||||||
|
#endif
|
||||||
|
if (Written<Size && Written>0)
|
||||||
|
Seek(Tell()-Written,SEEK_SET);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ErrHandler.WriteError(NULL,FileName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LastWrite=true;
|
||||||
|
return Success; // It can return false only if AllowExceptions is disabled.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int File::Read(void *Data,size_t Size)
|
||||||
|
{
|
||||||
|
int64 FilePos=0; // Initialized only to suppress some compilers warning.
|
||||||
|
|
||||||
|
if (IgnoreReadErrors)
|
||||||
|
FilePos=Tell();
|
||||||
|
int ReadSize;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ReadSize=DirectRead(Data,Size);
|
||||||
|
if (ReadSize==-1)
|
||||||
|
{
|
||||||
|
ErrorType=FILE_READERROR;
|
||||||
|
if (AllowExceptions)
|
||||||
|
if (IgnoreReadErrors)
|
||||||
|
{
|
||||||
|
ReadSize=0;
|
||||||
|
for (size_t I=0;I<Size;I+=512)
|
||||||
|
{
|
||||||
|
Seek(FilePos+I,SEEK_SET);
|
||||||
|
size_t SizeToRead=Min(Size-I,512);
|
||||||
|
int ReadCode=DirectRead(Data,SizeToRead);
|
||||||
|
ReadSize+=(ReadCode==-1) ? 512:ReadCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName))
|
||||||
|
continue;
|
||||||
|
ErrHandler.ReadError(FileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ReadSize; // It can return -1 only if AllowExceptions is disabled.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns -1 in case of error.
|
||||||
|
int File::DirectRead(void *Data,size_t Size)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
const size_t MaxDeviceRead=20000;
|
||||||
|
const size_t MaxLockedRead=32768;
|
||||||
|
#endif
|
||||||
|
if (HandleType==FILE_HANDLESTD)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// if (Size>MaxDeviceRead)
|
||||||
|
// Size=MaxDeviceRead;
|
||||||
|
hFile=GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
#else
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
hFile=STDIN_FILENO;
|
||||||
|
#else
|
||||||
|
hFile=stdin;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// For pipes like 'type file.txt | rar -si arcname' ReadFile may return
|
||||||
|
// data in small ~4KB blocks. It may slightly reduce the compression ratio.
|
||||||
|
DWORD Read;
|
||||||
|
if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
|
||||||
|
{
|
||||||
|
if (IsDevice() && Size>MaxDeviceRead)
|
||||||
|
return DirectRead(Data,MaxDeviceRead);
|
||||||
|
if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// We had a bug report about failure to archive 1C database lock file
|
||||||
|
// 1Cv8tmp.1CL, which is a zero length file with a region above 200 KB
|
||||||
|
// permanently locked. If our first read request uses too large buffer
|
||||||
|
// and if we are in -dh mode, so we were able to open the file,
|
||||||
|
// we'll fail with "Read error". So now we use try a smaller buffer size
|
||||||
|
// in case of lock error.
|
||||||
|
if (HandleType==FILE_HANDLENORMAL && Size>MaxLockedRead &&
|
||||||
|
GetLastError()==ERROR_LOCK_VIOLATION)
|
||||||
|
return DirectRead(Data,MaxLockedRead);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return Read;
|
||||||
|
#else
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
ssize_t ReadSize=read(hFile,Data,Size);
|
||||||
|
if (ReadSize==-1)
|
||||||
|
return -1;
|
||||||
|
return (int)ReadSize;
|
||||||
|
#else
|
||||||
|
if (LastWrite)
|
||||||
|
{
|
||||||
|
fflush(hFile);
|
||||||
|
LastWrite=false;
|
||||||
|
}
|
||||||
|
clearerr(hFile);
|
||||||
|
size_t ReadSize=fread(Data,1,Size,hFile);
|
||||||
|
if (ferror(hFile))
|
||||||
|
return -1;
|
||||||
|
return (int)ReadSize;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::Seek(int64 Offset,int Method)
|
||||||
|
{
|
||||||
|
if (!RawSeek(Offset,Method) && AllowExceptions)
|
||||||
|
ErrHandler.SeekError(FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::RawSeek(int64 Offset,int Method)
|
||||||
|
{
|
||||||
|
if (hFile==FILE_BAD_HANDLE)
|
||||||
|
return true;
|
||||||
|
if (Offset<0 && Method!=SEEK_SET)
|
||||||
|
{
|
||||||
|
Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
|
||||||
|
Method=SEEK_SET;
|
||||||
|
}
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
LONG HighDist=(LONG)(Offset>>32);
|
||||||
|
if (SetFilePointer(hFile,(LONG)Offset,&HighDist,Method)==0xffffffff &&
|
||||||
|
GetLastError()!=NO_ERROR)
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
LastWrite=false;
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
if (lseek(hFile,(off_t)Offset,Method)==-1)
|
||||||
|
return false;
|
||||||
|
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
|
||||||
|
if (fseeko(hFile,Offset,Method)!=0)
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (fseek(hFile,(long)Offset,Method)!=0)
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64 File::Tell()
|
||||||
|
{
|
||||||
|
if (hFile==FILE_BAD_HANDLE)
|
||||||
|
if (AllowExceptions)
|
||||||
|
ErrHandler.SeekError(FileName);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
LONG HighDist=0;
|
||||||
|
uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
|
||||||
|
if (LowDist==0xffffffff && GetLastError()!=NO_ERROR)
|
||||||
|
if (AllowExceptions)
|
||||||
|
ErrHandler.SeekError(FileName);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
return INT32TO64(HighDist,LowDist);
|
||||||
|
#else
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
return lseek(hFile,0,SEEK_CUR);
|
||||||
|
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
|
||||||
|
return ftello(hFile);
|
||||||
|
#else
|
||||||
|
return ftell(hFile);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::Prealloc(int64 Size)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
if (RawSeek(Size,SEEK_SET))
|
||||||
|
{
|
||||||
|
Truncate();
|
||||||
|
Seek(0,SEEK_SET);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_UNIX) && defined(USE_FALLOCATE)
|
||||||
|
// fallocate is rather new call. Only latest kernels support it.
|
||||||
|
// So we are not using it by default yet.
|
||||||
|
int fd = GetFD();
|
||||||
|
if (fd >= 0)
|
||||||
|
fallocate(fd, 0, 0, Size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
byte File::GetByte()
|
||||||
|
{
|
||||||
|
byte Byte=0;
|
||||||
|
Read(&Byte,1);
|
||||||
|
return Byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::PutByte(byte Byte)
|
||||||
|
{
|
||||||
|
Write(&Byte,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::Truncate()
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
return SetEndOfFile(hFile)==TRUE;
|
||||||
|
#else
|
||||||
|
return ftruncate(GetFD(),(off_t)Tell())==0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::Flush()
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
FlushFileBuffers(hFile);
|
||||||
|
#else
|
||||||
|
#ifndef FILE_USE_OPEN
|
||||||
|
fflush(hFile);
|
||||||
|
#endif
|
||||||
|
fsync(GetFD());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// Workaround for OpenIndiana NAS time bug. If we cannot create a file
|
||||||
|
// in write only mode, we need to flush the write buffer before calling
|
||||||
|
// SetFileTime or file time will not be changed.
|
||||||
|
if (CreateMode!=FMF_UNDEFINED && (CreateMode & FMF_WRITE)==0)
|
||||||
|
FlushFileBuffers(hFile);
|
||||||
|
|
||||||
|
bool sm=ftm!=NULL && ftm->IsSet();
|
||||||
|
bool sc=ftc!=NULL && ftc->IsSet();
|
||||||
|
bool sa=fta!=NULL && fta->IsSet();
|
||||||
|
FILETIME fm,fc,fa;
|
||||||
|
if (sm)
|
||||||
|
ftm->GetWinFT(&fm);
|
||||||
|
if (sc)
|
||||||
|
ftc->GetWinFT(&fc);
|
||||||
|
if (sa)
|
||||||
|
fta->GetWinFT(&fa);
|
||||||
|
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::SetCloseFileTime(RarTime *ftm,RarTime *fta)
|
||||||
|
{
|
||||||
|
// Android APP_PLATFORM := android-14 does not support futimens and futimes.
|
||||||
|
// Newer platforms support futimens, but fail on Android 4.2.
|
||||||
|
// We have to use utime for Android.
|
||||||
|
// Also we noticed futimens fail to set timestamps on NTFS partition
|
||||||
|
// mounted to virtual Linux x86 machine, but utimensat worked correctly.
|
||||||
|
// So we set timestamps for already closed files in Unix.
|
||||||
|
#ifdef _UNIX
|
||||||
|
SetCloseFileTimeByName(FileName,ftm,fta);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta)
|
||||||
|
{
|
||||||
|
#ifdef _UNIX
|
||||||
|
bool setm=ftm!=NULL && ftm->IsSet();
|
||||||
|
bool seta=fta!=NULL && fta->IsSet();
|
||||||
|
if (setm || seta)
|
||||||
|
{
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
|
||||||
|
#ifdef UNIX_TIME_NS
|
||||||
|
timespec times[2];
|
||||||
|
times[0].tv_sec=seta ? fta->GetUnix() : 0;
|
||||||
|
times[0].tv_nsec=seta ? long(fta->GetUnixNS()%1000000000) : UTIME_NOW;
|
||||||
|
times[1].tv_sec=setm ? ftm->GetUnix() : 0;
|
||||||
|
times[1].tv_nsec=setm ? long(ftm->GetUnixNS()%1000000000) : UTIME_NOW;
|
||||||
|
utimensat(AT_FDCWD,NameA,times,0);
|
||||||
|
#else
|
||||||
|
utimbuf ut;
|
||||||
|
if (setm)
|
||||||
|
ut.modtime=ftm->GetUnix();
|
||||||
|
else
|
||||||
|
ut.modtime=fta->GetUnix(); // Need to set something, cannot left it 0.
|
||||||
|
if (seta)
|
||||||
|
ut.actime=fta->GetUnix();
|
||||||
|
else
|
||||||
|
ut.actime=ut.modtime; // Need to set something, cannot left it 0.
|
||||||
|
utime(NameA,&ut);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void File::GetOpenFileTime(RarTime *ft)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
FILETIME FileTime;
|
||||||
|
GetFileTime(hFile,NULL,NULL,&FileTime);
|
||||||
|
ft->SetWinFT(&FileTime);
|
||||||
|
#endif
|
||||||
|
#if defined(_UNIX) || defined(_EMX)
|
||||||
|
struct stat st;
|
||||||
|
fstat(GetFD(),&st);
|
||||||
|
ft->SetUnix(st.st_mtime);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64 File::FileLength()
|
||||||
|
{
|
||||||
|
int64 SavePos=Tell();
|
||||||
|
Seek(0,SEEK_END);
|
||||||
|
int64 Length=Tell();
|
||||||
|
Seek(SavePos,SEEK_SET);
|
||||||
|
return Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool File::IsDevice()
|
||||||
|
{
|
||||||
|
if (hFile==FILE_BAD_HANDLE)
|
||||||
|
return false;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
uint Type=GetFileType(hFile);
|
||||||
|
return Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE;
|
||||||
|
#else
|
||||||
|
return isatty(GetFD());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
int64 File::Copy(File &Dest,int64 Length)
|
||||||
|
{
|
||||||
|
Array<byte> Buffer(File::CopyBufferSize());
|
||||||
|
int64 CopySize=0;
|
||||||
|
bool CopyAll=(Length==INT64NDF);
|
||||||
|
|
||||||
|
while (CopyAll || Length>0)
|
||||||
|
{
|
||||||
|
Wait();
|
||||||
|
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
|
||||||
|
byte *Buf=&Buffer[0];
|
||||||
|
int ReadSize=Read(Buf,SizeToRead);
|
||||||
|
if (ReadSize==0)
|
||||||
|
break;
|
||||||
|
size_t WriteSize=ReadSize;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// For FAT32 USB flash drives in Windows if first write is 4 KB or more,
|
||||||
|
// write caching is disabled and "write through" is enabled, resulting
|
||||||
|
// in bad performance, especially for many small files. It happens when
|
||||||
|
// we create SFX archive on USB drive, because SFX module is written first.
|
||||||
|
// So we split the first write to small 1 KB followed by rest of data.
|
||||||
|
if (CopySize==0 && WriteSize>=4096)
|
||||||
|
{
|
||||||
|
const size_t FirstWrite=1024;
|
||||||
|
Dest.Write(Buf,FirstWrite);
|
||||||
|
Buf+=FirstWrite;
|
||||||
|
WriteSize-=FirstWrite;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Dest.Write(Buf,WriteSize);
|
||||||
|
CopySize+=ReadSize;
|
||||||
|
if (!CopyAll)
|
||||||
|
Length-=ReadSize;
|
||||||
|
}
|
||||||
|
return CopySize;
|
||||||
|
}
|
||||||
|
#endif
|
142
deps/unrar/file.hpp
vendored
Normal file
142
deps/unrar/file.hpp
vendored
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#ifndef _RAR_FILE_
|
||||||
|
#define _RAR_FILE_
|
||||||
|
|
||||||
|
#define FILE_USE_OPEN
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
typedef HANDLE FileHandle;
|
||||||
|
#define FILE_BAD_HANDLE INVALID_HANDLE_VALUE
|
||||||
|
#elif defined(FILE_USE_OPEN)
|
||||||
|
typedef off_t FileHandle;
|
||||||
|
#define FILE_BAD_HANDLE -1
|
||||||
|
#else
|
||||||
|
typedef FILE* FileHandle;
|
||||||
|
#define FILE_BAD_HANDLE NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class RAROptions;
|
||||||
|
|
||||||
|
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD};
|
||||||
|
|
||||||
|
enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR};
|
||||||
|
|
||||||
|
enum FILE_MODE_FLAGS {
|
||||||
|
// Request read only access to file. Default for Open.
|
||||||
|
FMF_READ=0,
|
||||||
|
|
||||||
|
// Request both read and write access to file. Default for Create.
|
||||||
|
FMF_UPDATE=1,
|
||||||
|
|
||||||
|
// Request write only access to file.
|
||||||
|
FMF_WRITE=2,
|
||||||
|
|
||||||
|
// Open files which are already opened for write by other programs.
|
||||||
|
FMF_OPENSHARED=4,
|
||||||
|
|
||||||
|
// Open files only if no other program is opened it even in shared mode.
|
||||||
|
FMF_OPENEXCLUSIVE=8,
|
||||||
|
|
||||||
|
// Provide read access to created file for other programs.
|
||||||
|
FMF_SHAREREAD=16,
|
||||||
|
|
||||||
|
// Use standard NTFS names without trailing dots and spaces.
|
||||||
|
FMF_STANDARDNAMES=32,
|
||||||
|
|
||||||
|
// Mode flags are not defined yet.
|
||||||
|
FMF_UNDEFINED=256
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class File
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
FileHandle hFile;
|
||||||
|
bool LastWrite;
|
||||||
|
FILE_HANDLETYPE HandleType;
|
||||||
|
bool SkipClose;
|
||||||
|
bool IgnoreReadErrors;
|
||||||
|
bool NewFile;
|
||||||
|
bool AllowDelete;
|
||||||
|
bool AllowExceptions;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool NoSequentialRead;
|
||||||
|
uint CreateMode;
|
||||||
|
#endif
|
||||||
|
bool PreserveAtime;
|
||||||
|
protected:
|
||||||
|
bool OpenShared; // Set by 'Archive' class.
|
||||||
|
public:
|
||||||
|
wchar FileName[NM];
|
||||||
|
|
||||||
|
FILE_ERRORTYPE ErrorType;
|
||||||
|
public:
|
||||||
|
File();
|
||||||
|
virtual ~File();
|
||||||
|
void operator = (File &SrcFile);
|
||||||
|
|
||||||
|
// Several functions below are 'virtual', because they are redefined
|
||||||
|
// by Archive for QOpen and by MultiFile for split files in WinRAR.
|
||||||
|
virtual bool Open(const wchar *Name,uint Mode=FMF_READ);
|
||||||
|
void TOpen(const wchar *Name);
|
||||||
|
bool WOpen(const wchar *Name);
|
||||||
|
bool Create(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||||
|
void TCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||||
|
bool WCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||||
|
virtual bool Close(); // 'virtual' for MultiFile class.
|
||||||
|
bool Delete();
|
||||||
|
bool Rename(const wchar *NewName);
|
||||||
|
bool Write(const void *Data,size_t Size);
|
||||||
|
virtual int Read(void *Data,size_t Size);
|
||||||
|
int DirectRead(void *Data,size_t Size);
|
||||||
|
virtual void Seek(int64 Offset,int Method);
|
||||||
|
bool RawSeek(int64 Offset,int Method);
|
||||||
|
virtual int64 Tell();
|
||||||
|
void Prealloc(int64 Size);
|
||||||
|
byte GetByte();
|
||||||
|
void PutByte(byte Byte);
|
||||||
|
bool Truncate();
|
||||||
|
void Flush();
|
||||||
|
void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
|
||||||
|
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
|
||||||
|
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
|
||||||
|
void GetOpenFileTime(RarTime *ft);
|
||||||
|
virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class.
|
||||||
|
int64 FileLength();
|
||||||
|
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
|
||||||
|
FILE_HANDLETYPE GetHandleType() {return HandleType;}
|
||||||
|
bool IsDevice();
|
||||||
|
static bool RemoveCreated();
|
||||||
|
FileHandle GetHandle() {return hFile;}
|
||||||
|
void SetHandle(FileHandle Handle) {Close();hFile=Handle;}
|
||||||
|
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;}
|
||||||
|
int64 Copy(File &Dest,int64 Length=INT64NDF);
|
||||||
|
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
|
||||||
|
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
void RemoveSequentialFlag() {NoSequentialRead=true;}
|
||||||
|
#endif
|
||||||
|
void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
|
||||||
|
#ifdef _UNIX
|
||||||
|
int GetFD()
|
||||||
|
{
|
||||||
|
#ifdef FILE_USE_OPEN
|
||||||
|
return hFile;
|
||||||
|
#else
|
||||||
|
return fileno(hFile);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
static size_t CopyBufferSize()
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// USB flash performance is poor with 64 KB buffer, 256+ KB resolved it.
|
||||||
|
// For copying from HDD to same HDD the best performance was with 256 KB
|
||||||
|
// buffer in XP and with 1 MB buffer in Win10.
|
||||||
|
return WinNT()==WNT_WXP ? 0x40000:0x100000;
|
||||||
|
#else
|
||||||
|
return 0x100000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
512
deps/unrar/filefn.cpp
vendored
Normal file
512
deps/unrar/filefn.cpp
vendored
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// Windows automatically removes dots and spaces in the end of directory
|
||||||
|
// name. So we detect such names and process them with \\?\ prefix.
|
||||||
|
wchar *LastChar=PointToLastChar(Name);
|
||||||
|
bool Special=*LastChar=='.' || *LastChar==' ';
|
||||||
|
BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL);
|
||||||
|
if (RetCode==0 && !FileExist(Name))
|
||||||
|
{
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
RetCode=CreateDirectory(LongName,NULL);
|
||||||
|
}
|
||||||
|
if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
|
||||||
|
{
|
||||||
|
if (SetAttr)
|
||||||
|
SetFileAttr(Name,Attr);
|
||||||
|
return MKDIR_SUCCESS;
|
||||||
|
}
|
||||||
|
int ErrCode=GetLastError();
|
||||||
|
if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
|
||||||
|
return MKDIR_BADPATH;
|
||||||
|
return MKDIR_ERROR;
|
||||||
|
#elif defined(_UNIX)
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
mode_t uattr=SetAttr ? (mode_t)Attr:0777;
|
||||||
|
int ErrCode=mkdir(NameA,uattr);
|
||||||
|
if (ErrCode==-1)
|
||||||
|
return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR;
|
||||||
|
return MKDIR_SUCCESS;
|
||||||
|
#else
|
||||||
|
return MKDIR_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CreatePath(const wchar *Path,bool SkipLastName)
|
||||||
|
{
|
||||||
|
if (Path==NULL || *Path==0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) || defined(_EMX)
|
||||||
|
uint DirAttr=0;
|
||||||
|
#else
|
||||||
|
uint DirAttr=0777;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Success=true;
|
||||||
|
|
||||||
|
for (const wchar *s=Path;*s!=0;s++)
|
||||||
|
{
|
||||||
|
wchar DirName[NM];
|
||||||
|
if (s-Path>=ASIZE(DirName))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Process all kinds of path separators, so user can enter Unix style
|
||||||
|
// path in Windows or Windows in Unix. s>Path check avoids attempting
|
||||||
|
// creating an empty directory for paths starting from path separator.
|
||||||
|
if (IsPathDiv(*s) && s>Path)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// We must not attempt to create "D:" directory, because first
|
||||||
|
// CreateDirectory will fail, so we'll use \\?\D:, which forces Wine
|
||||||
|
// to create "D:" directory.
|
||||||
|
if (s==Path+2 && Path[1]==':')
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
wcsncpy(DirName,Path,s-Path);
|
||||||
|
DirName[s-Path]=0;
|
||||||
|
|
||||||
|
Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS;
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
mprintf(St(MCreatDir),DirName);
|
||||||
|
mprintf(L" %s",St(MOk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
|
||||||
|
Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||||
|
{
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
bool sm=ftm!=NULL && ftm->IsSet();
|
||||||
|
bool sc=ftc!=NULL && ftc->IsSet();
|
||||||
|
bool sa=fta!=NULL && fta->IsSet();
|
||||||
|
|
||||||
|
uint DirAttr=GetFileAttr(Name);
|
||||||
|
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FILE_ATTRIBUTE_READONLY)!=0);
|
||||||
|
if (ResetAttr)
|
||||||
|
SetFileAttr(Name,0);
|
||||||
|
|
||||||
|
HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
|
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
|
||||||
|
if (hFile==INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
hFile=CreateFile(LongName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
|
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hFile==INVALID_HANDLE_VALUE)
|
||||||
|
return;
|
||||||
|
FILETIME fm,fc,fa;
|
||||||
|
if (sm)
|
||||||
|
ftm->GetWinFT(&fm);
|
||||||
|
if (sc)
|
||||||
|
ftc->GetWinFT(&fc);
|
||||||
|
if (sa)
|
||||||
|
fta->GetWinFT(&fa);
|
||||||
|
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
if (ResetAttr)
|
||||||
|
SetFileAttr(Name,DirAttr);
|
||||||
|
#endif
|
||||||
|
#if defined(_UNIX) || defined(_EMX)
|
||||||
|
File::SetCloseFileTimeByName(Name,ftm,fta);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsRemovable(const wchar *Name)
|
||||||
|
{
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
wchar Root[NM];
|
||||||
|
GetPathRoot(Name,Root,ASIZE(Root));
|
||||||
|
int Type=GetDriveType(*Root!=0 ? Root:NULL);
|
||||||
|
return Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
int64 GetFreeDisk(const wchar *Name)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
wchar Root[NM];
|
||||||
|
GetFilePath(Name,Root,ASIZE(Root));
|
||||||
|
|
||||||
|
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
|
||||||
|
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
|
||||||
|
if (GetDiskFreeSpaceEx(*Root!=0 ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
|
||||||
|
uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
|
||||||
|
return INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart);
|
||||||
|
return 0;
|
||||||
|
#elif defined(_UNIX)
|
||||||
|
wchar Root[NM];
|
||||||
|
GetFilePath(Name,Root,ASIZE(Root));
|
||||||
|
char RootA[NM];
|
||||||
|
WideToChar(Root,RootA,ASIZE(RootA));
|
||||||
|
struct statvfs sfs;
|
||||||
|
if (statvfs(*RootA!=0 ? RootA:".",&sfs)!=0)
|
||||||
|
return 0;
|
||||||
|
int64 FreeSize=sfs.f_bsize;
|
||||||
|
FreeSize=FreeSize*sfs.f_bavail;
|
||||||
|
return FreeSize;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
|
||||||
|
// Return 'true' for FAT and FAT32, so we can adjust the maximum supported
|
||||||
|
// file size to 4 GB for these file systems.
|
||||||
|
bool IsFAT(const wchar *Name)
|
||||||
|
{
|
||||||
|
wchar Root[NM];
|
||||||
|
GetPathRoot(Name,Root,ASIZE(Root));
|
||||||
|
wchar FileSystem[MAX_PATH+1];
|
||||||
|
if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem)))
|
||||||
|
return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool FileExist(const wchar *Name)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
return GetFileAttr(Name)!=0xffffffff;
|
||||||
|
#elif defined(ENABLE_ACCESS)
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
return access(NameA,0)==0;
|
||||||
|
#else
|
||||||
|
FindData FD;
|
||||||
|
return FindFile::FastFind(Name,&FD);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WildFileExist(const wchar *Name)
|
||||||
|
{
|
||||||
|
if (IsWildcard(Name))
|
||||||
|
{
|
||||||
|
FindFile Find;
|
||||||
|
Find.SetMask(Name);
|
||||||
|
FindData fd;
|
||||||
|
return Find.Next(&fd);
|
||||||
|
}
|
||||||
|
return FileExist(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsDir(uint Attr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
return Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_DIRECTORY)!=0;
|
||||||
|
#endif
|
||||||
|
#if defined(_UNIX)
|
||||||
|
return (Attr & 0xF000)==0x4000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsUnreadable(uint Attr)
|
||||||
|
{
|
||||||
|
#if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
|
||||||
|
return S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsLink(uint Attr)
|
||||||
|
{
|
||||||
|
#ifdef _UNIX
|
||||||
|
return (Attr & 0xF000)==0xA000;
|
||||||
|
#elif defined(_WIN_ALL)
|
||||||
|
return (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool IsDeleteAllowed(uint FileAttr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
return (FileAttr & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN))==0;
|
||||||
|
#else
|
||||||
|
return (FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrepareToDelete(const wchar *Name)
|
||||||
|
{
|
||||||
|
#if defined(_WIN_ALL) || defined(_EMX)
|
||||||
|
SetFileAttr(Name,0);
|
||||||
|
#endif
|
||||||
|
#ifdef _UNIX
|
||||||
|
if (Name!=NULL)
|
||||||
|
{
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
chmod(NameA,S_IRUSR|S_IWUSR|S_IXUSR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint GetFileAttr(const wchar *Name)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
DWORD Attr=GetFileAttributes(Name);
|
||||||
|
if (Attr==0xffffffff)
|
||||||
|
{
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
Attr=GetFileAttributes(LongName);
|
||||||
|
}
|
||||||
|
return Attr;
|
||||||
|
#else
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
struct stat st;
|
||||||
|
if (stat(NameA,&st)!=0)
|
||||||
|
return 0;
|
||||||
|
return st.st_mode;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SetFileAttr(const wchar *Name,uint Attr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool Success=SetFileAttributes(Name,Attr)!=0;
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
Success=SetFileAttributes(LongName,Attr)!=0;
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
#elif defined(_UNIX)
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
return chmod(NameA,(mode_t)Attr)==0;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||||
|
{
|
||||||
|
size_t Length=wcslen(Name);
|
||||||
|
|
||||||
|
RarTime CurTime;
|
||||||
|
CurTime.SetCurrentTime();
|
||||||
|
|
||||||
|
// We cannot use CurTime.GetWin() as is, because its lowest bits can
|
||||||
|
// have low informational value, like being a zero or few fixed numbers.
|
||||||
|
uint Random=(uint)(CurTime.GetWin()/100000);
|
||||||
|
|
||||||
|
// Using PID we guarantee that different RAR copies use different temp names
|
||||||
|
// even if started in exactly the same time.
|
||||||
|
uint PID=0;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
PID=(uint)GetCurrentProcessId();
|
||||||
|
#elif defined(_UNIX)
|
||||||
|
PID=(uint)getpid();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (uint Attempt=0;;Attempt++)
|
||||||
|
{
|
||||||
|
uint Ext=Random%50000+Attempt;
|
||||||
|
wchar RndText[50];
|
||||||
|
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
|
||||||
|
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
|
||||||
|
return NULL;
|
||||||
|
wcsncpyz(Name+Length,RndText,MaxSize-Length);
|
||||||
|
if (!FileExist(Name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
|
||||||
|
{
|
||||||
|
int64 SavePos=SrcFile->Tell();
|
||||||
|
#ifndef SILENT
|
||||||
|
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWPERCENT))!=0)
|
||||||
|
uiMsg(UIEVENT_FILESUMSTART);
|
||||||
|
|
||||||
|
if ((Flags & CALCFSUM_CURPOS)==0)
|
||||||
|
SrcFile->Seek(0,SEEK_SET);
|
||||||
|
|
||||||
|
const size_t BufSize=0x100000;
|
||||||
|
Array<byte> Data(BufSize);
|
||||||
|
|
||||||
|
|
||||||
|
DataHash HashCRC,HashBlake2;
|
||||||
|
HashCRC.Init(HASH_CRC32,Threads);
|
||||||
|
HashBlake2.Init(HASH_BLAKE2,Threads);
|
||||||
|
|
||||||
|
int64 BlockCount=0;
|
||||||
|
int64 TotalRead=0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
size_t SizeToRead;
|
||||||
|
if (Size==INT64NDF) // If we process the entire file.
|
||||||
|
SizeToRead=BufSize; // Then always attempt to read the entire buffer.
|
||||||
|
else
|
||||||
|
SizeToRead=(size_t)Min((int64)BufSize,Size);
|
||||||
|
int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
|
||||||
|
if (ReadSize==0)
|
||||||
|
break;
|
||||||
|
TotalRead+=ReadSize;
|
||||||
|
|
||||||
|
if ((++BlockCount & 0xf)==0)
|
||||||
|
{
|
||||||
|
#ifndef SILENT
|
||||||
|
if ((Flags & CALCFSUM_SHOWPROGRESS)!=0)
|
||||||
|
uiExtractProgress(TotalRead,FileLength,TotalRead,FileLength);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||||
|
uiMsg(UIEVENT_FILESUMPROGRESS,ToPercent(TotalRead,FileLength));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CRC32!=NULL)
|
||||||
|
HashCRC.Update(&Data[0],ReadSize);
|
||||||
|
if (Blake2!=NULL)
|
||||||
|
HashBlake2.Update(&Data[0],ReadSize);
|
||||||
|
|
||||||
|
if (Size!=INT64NDF)
|
||||||
|
Size-=ReadSize;
|
||||||
|
}
|
||||||
|
SrcFile->Seek(SavePos,SEEK_SET);
|
||||||
|
|
||||||
|
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||||
|
uiMsg(UIEVENT_FILESUMEND);
|
||||||
|
|
||||||
|
if (CRC32!=NULL)
|
||||||
|
*CRC32=HashCRC.GetCRC32();
|
||||||
|
if (Blake2!=NULL)
|
||||||
|
{
|
||||||
|
HashValue Result;
|
||||||
|
HashBlake2.Result(&Result);
|
||||||
|
memcpy(Blake2,Result.Digest,sizeof(Result.Digest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool RenameFile(const wchar *SrcName,const wchar *DestName)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool Success=MoveFile(SrcName,DestName)!=0;
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
wchar LongName1[NM],LongName2[NM];
|
||||||
|
if (GetWinLongPath(SrcName,LongName1,ASIZE(LongName1)) &&
|
||||||
|
GetWinLongPath(DestName,LongName2,ASIZE(LongName2)))
|
||||||
|
Success=MoveFile(LongName1,LongName2)!=0;
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
#else
|
||||||
|
char SrcNameA[NM],DestNameA[NM];
|
||||||
|
WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA));
|
||||||
|
WideToChar(DestName,DestNameA,ASIZE(DestNameA));
|
||||||
|
bool Success=rename(SrcNameA,DestNameA)==0;
|
||||||
|
return Success;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DelFile(const wchar *Name)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool Success=DeleteFile(Name)!=0;
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
Success=DeleteFile(LongName)!=0;
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
#else
|
||||||
|
char NameA[NM];
|
||||||
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
bool Success=remove(NameA)==0;
|
||||||
|
return Success;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
|
bool SetFileCompression(const wchar *Name,bool State)
|
||||||
|
{
|
||||||
|
HANDLE hFile=CreateFile(Name,FILE_READ_DATA|FILE_WRITE_DATA,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||||
|
if (hFile==INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
wchar LongName[NM];
|
||||||
|
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||||
|
hFile=CreateFile(LongName,FILE_READ_DATA|FILE_WRITE_DATA,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||||
|
}
|
||||||
|
if (hFile==INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
|
||||||
|
DWORD Result;
|
||||||
|
int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
|
||||||
|
sizeof(NewState),NULL,0,&Result,NULL);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return RetCode!=0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
50
deps/unrar/filefn.hpp
vendored
Normal file
50
deps/unrar/filefn.hpp
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef _RAR_FILEFN_
|
||||||
|
#define _RAR_FILEFN_
|
||||||
|
|
||||||
|
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
|
||||||
|
|
||||||
|
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr);
|
||||||
|
bool CreatePath(const wchar *Path,bool SkipLastName);
|
||||||
|
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
|
||||||
|
bool IsRemovable(const wchar *Name);
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
int64 GetFreeDisk(const wchar *Name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
|
||||||
|
bool IsFAT(const wchar *Root);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool FileExist(const wchar *Name);
|
||||||
|
bool WildFileExist(const wchar *Name);
|
||||||
|
bool IsDir(uint Attr);
|
||||||
|
bool IsUnreadable(uint Attr);
|
||||||
|
bool IsLink(uint Attr);
|
||||||
|
void SetSFXMode(const wchar *FileName);
|
||||||
|
void EraseDiskContents(const wchar *FileName);
|
||||||
|
bool IsDeleteAllowed(uint FileAttr);
|
||||||
|
void PrepareToDelete(const wchar *Name);
|
||||||
|
uint GetFileAttr(const wchar *Name);
|
||||||
|
bool SetFileAttr(const wchar *Name,uint Attr);
|
||||||
|
#if 0
|
||||||
|
wchar* MkTemp(wchar *Name,size_t MaxSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum CALCFSUM_FLAGS {CALCFSUM_SHOWTEXT=1,CALCFSUM_SHOWPERCENT=2,CALCFSUM_SHOWPROGRESS=4,CALCFSUM_CURPOS=8};
|
||||||
|
|
||||||
|
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size=INT64NDF,uint Flags=0);
|
||||||
|
|
||||||
|
bool RenameFile(const wchar *SrcName,const wchar *DestName);
|
||||||
|
bool DelFile(const wchar *Name);
|
||||||
|
bool DelDir(const wchar *Name);
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
|
bool SetFileCompression(const wchar *Name,bool State);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
166
deps/unrar/filestr.cpp
vendored
Normal file
166
deps/unrar/filestr.cpp
vendored
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
bool ReadTextFile(
|
||||||
|
const wchar *Name,
|
||||||
|
StringList *List,
|
||||||
|
bool Config,
|
||||||
|
bool AbortOnError,
|
||||||
|
RAR_CHARSET SrcCharset,
|
||||||
|
bool Unquote,
|
||||||
|
bool SkipComments,
|
||||||
|
bool ExpandEnvStr)
|
||||||
|
{
|
||||||
|
wchar FileName[NM];
|
||||||
|
*FileName=0;
|
||||||
|
|
||||||
|
if (Name!=NULL)
|
||||||
|
if (Config)
|
||||||
|
GetConfigName(Name,FileName,ASIZE(FileName),true,false);
|
||||||
|
else
|
||||||
|
wcsncpyz(FileName,Name,ASIZE(FileName));
|
||||||
|
|
||||||
|
File SrcFile;
|
||||||
|
if (*FileName!=0)
|
||||||
|
{
|
||||||
|
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName):SrcFile.Open(FileName,0);
|
||||||
|
|
||||||
|
if (!OpenCode)
|
||||||
|
{
|
||||||
|
if (AbortOnError)
|
||||||
|
ErrHandler.Exit(RARX_OPEN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||||
|
|
||||||
|
uint DataSize=0,ReadSize;
|
||||||
|
const int ReadBlock=4096;
|
||||||
|
|
||||||
|
Array<byte> Data(ReadBlock);
|
||||||
|
while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0)
|
||||||
|
{
|
||||||
|
DataSize+=ReadSize;
|
||||||
|
Data.Add(ReadSize); // Always have ReadBlock available for next data.
|
||||||
|
}
|
||||||
|
// Set to really read size, so we can zero terminate it correctly.
|
||||||
|
Data.Alloc(DataSize);
|
||||||
|
|
||||||
|
int LittleEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0;
|
||||||
|
int BigEndian=DataSize>=2 && Data[0]==254 && Data[1]==255 ? 1:0;
|
||||||
|
bool Utf8=DataSize>=3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf;
|
||||||
|
|
||||||
|
if (SrcCharset==RCH_DEFAULT)
|
||||||
|
SrcCharset=DetectTextEncoding(&Data[0],DataSize);
|
||||||
|
|
||||||
|
Array<wchar> DataW;
|
||||||
|
|
||||||
|
if (SrcCharset==RCH_DEFAULT || SrcCharset==RCH_OEM || SrcCharset==RCH_ANSI)
|
||||||
|
{
|
||||||
|
Data.Push(0); // Zero terminate.
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
if (SrcCharset==RCH_OEM)
|
||||||
|
OemToCharA((char *)&Data[0],(char *)&Data[0]);
|
||||||
|
#endif
|
||||||
|
DataW.Alloc(Data.Size());
|
||||||
|
CharToWide((char *)&Data[0],&DataW[0],DataW.Size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SrcCharset==RCH_UNICODE)
|
||||||
|
{
|
||||||
|
size_t Start=2; // Skip byte order mark.
|
||||||
|
if (!LittleEndian && !BigEndian) // No byte order mask.
|
||||||
|
{
|
||||||
|
Start=0;
|
||||||
|
LittleEndian=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataW.Alloc(Data.Size()/2+1);
|
||||||
|
size_t End=Data.Size() & ~1; // We need even bytes number for UTF-16.
|
||||||
|
for (size_t I=Start;I<End;I+=2)
|
||||||
|
DataW[(I-Start)/2]=Data[I+BigEndian]+Data[I+LittleEndian]*256;
|
||||||
|
DataW[(End-Start)/2]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SrcCharset==RCH_UTF8)
|
||||||
|
{
|
||||||
|
Data.Push(0); // Zero terminate data.
|
||||||
|
DataW.Alloc(Data.Size());
|
||||||
|
UtfToWide((const char *)(Data+(Utf8 ? 3:0)),&DataW[0],DataW.Size());
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar *CurStr=&DataW[0];
|
||||||
|
|
||||||
|
while (*CurStr!=0)
|
||||||
|
{
|
||||||
|
wchar *NextStr=CurStr,*CmtPtr=NULL;
|
||||||
|
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
|
||||||
|
{
|
||||||
|
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
|
||||||
|
{
|
||||||
|
*NextStr=0;
|
||||||
|
CmtPtr=NextStr;
|
||||||
|
}
|
||||||
|
NextStr++;
|
||||||
|
}
|
||||||
|
bool Done=*NextStr==0;
|
||||||
|
|
||||||
|
*NextStr=0;
|
||||||
|
for (wchar *SpacePtr=(CmtPtr!=NULL ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
|
||||||
|
{
|
||||||
|
if (*SpacePtr!=' ' && *SpacePtr!='\t')
|
||||||
|
break;
|
||||||
|
*SpacePtr=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Unquote && *CurStr=='\"')
|
||||||
|
{
|
||||||
|
size_t Length=wcslen(CurStr);
|
||||||
|
if (CurStr[Length-1]=='\"')
|
||||||
|
{
|
||||||
|
CurStr[Length-1]=0;
|
||||||
|
CurStr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Expanded=false;
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
if (ExpandEnvStr && *CurStr=='%') // Expand environment variables in Windows.
|
||||||
|
{
|
||||||
|
wchar ExpName[NM];
|
||||||
|
*ExpName=0;
|
||||||
|
DWORD Result=ExpandEnvironmentStrings(CurStr,ExpName,ASIZE(ExpName));
|
||||||
|
Expanded=Result!=0 && Result<ASIZE(ExpName);
|
||||||
|
if (Expanded && *ExpName!=0)
|
||||||
|
List->AddString(ExpName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!Expanded && *CurStr!=0)
|
||||||
|
List->AddString(CurStr);
|
||||||
|
|
||||||
|
if (Done)
|
||||||
|
break;
|
||||||
|
CurStr=NextStr+1;
|
||||||
|
while (*CurStr=='\r' || *CurStr=='\n')
|
||||||
|
CurStr++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RAR_CHARSET DetectTextEncoding(const byte *Data,size_t DataSize)
|
||||||
|
{
|
||||||
|
if (DataSize>3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf &&
|
||||||
|
IsTextUtf8(Data+3,DataSize-3))
|
||||||
|
return RCH_UTF8;
|
||||||
|
|
||||||
|
bool LittleEndian=DataSize>2 && Data[0]==255 && Data[1]==254;
|
||||||
|
bool BigEndian=DataSize>2 && Data[0]==254 && Data[1]==255;
|
||||||
|
|
||||||
|
if (LittleEndian || BigEndian)
|
||||||
|
for (size_t I=LittleEndian ? 3 : 2;I<DataSize;I+=2)
|
||||||
|
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
|
||||||
|
return RCH_UNICODE; // High byte in UTF-16 char is found.
|
||||||
|
|
||||||
|
return RCH_DEFAULT;
|
||||||
|
}
|
17
deps/unrar/filestr.hpp
vendored
Normal file
17
deps/unrar/filestr.hpp
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _RAR_FILESTR_
|
||||||
|
#define _RAR_FILESTR_
|
||||||
|
|
||||||
|
bool ReadTextFile(
|
||||||
|
const wchar *Name,
|
||||||
|
StringList *List,
|
||||||
|
bool Config,
|
||||||
|
bool AbortOnError=false,
|
||||||
|
RAR_CHARSET SrcCharset=RCH_DEFAULT,
|
||||||
|
bool Unquote=false,
|
||||||
|
bool SkipComments=false,
|
||||||
|
bool ExpandEnvStr=false
|
||||||
|
);
|
||||||
|
|
||||||
|
RAR_CHARSET DetectTextEncoding(const byte *Data,size_t DataSize);
|
||||||
|
|
||||||
|
#endif
|
218
deps/unrar/find.cpp
vendored
Normal file
218
deps/unrar/find.cpp
vendored
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
FindFile::FindFile()
|
||||||
|
{
|
||||||
|
*FindMask=0;
|
||||||
|
FirstCall=true;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
hFind=INVALID_HANDLE_VALUE;
|
||||||
|
#else
|
||||||
|
dirp=NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FindFile::~FindFile()
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
if (hFind!=INVALID_HANDLE_VALUE)
|
||||||
|
FindClose(hFind);
|
||||||
|
#else
|
||||||
|
if (dirp!=NULL)
|
||||||
|
closedir(dirp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FindFile::SetMask(const wchar *Mask)
|
||||||
|
{
|
||||||
|
wcsncpyz(FindMask,Mask,ASIZE(FindMask));
|
||||||
|
FirstCall=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FindFile::Next(FindData *fd,bool GetSymLink)
|
||||||
|
{
|
||||||
|
fd->Error=false;
|
||||||
|
if (*FindMask==0)
|
||||||
|
return false;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
if (FirstCall)
|
||||||
|
{
|
||||||
|
if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (FirstCall)
|
||||||
|
{
|
||||||
|
wchar DirName[NM];
|
||||||
|
wcsncpyz(DirName,FindMask,ASIZE(DirName));
|
||||||
|
RemoveNameFromPath(DirName);
|
||||||
|
if (*DirName==0)
|
||||||
|
wcsncpyz(DirName,L".",ASIZE(DirName));
|
||||||
|
char DirNameA[NM];
|
||||||
|
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
|
||||||
|
if ((dirp=opendir(DirNameA))==NULL)
|
||||||
|
{
|
||||||
|
fd->Error=(errno!=ENOENT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
wchar Name[NM];
|
||||||
|
struct dirent *ent=readdir(dirp);
|
||||||
|
if (ent==NULL)
|
||||||
|
return false;
|
||||||
|
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
|
||||||
|
continue;
|
||||||
|
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
|
||||||
|
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
|
||||||
|
|
||||||
|
if (CmpName(FindMask,Name,MATCH_NAMES))
|
||||||
|
{
|
||||||
|
wchar FullName[NM];
|
||||||
|
wcsncpyz(FullName,FindMask,ASIZE(FullName));
|
||||||
|
*PointToName(FullName)=0;
|
||||||
|
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
wcsncatz(FullName,Name,ASIZE(FullName));
|
||||||
|
if (!FastFind(FullName,fd,GetSymLink))
|
||||||
|
{
|
||||||
|
ErrHandler.OpenErrorMsg(FullName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wcsncpyz(fd->Name,FullName,ASIZE(fd->Name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fd->Flags=0;
|
||||||
|
fd->IsDir=IsDir(fd->FileAttr);
|
||||||
|
fd->IsLink=IsLink(fd->FileAttr);
|
||||||
|
|
||||||
|
FirstCall=false;
|
||||||
|
wchar *NameOnly=PointToName(fd->Name);
|
||||||
|
if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
|
||||||
|
return Next(fd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
|
||||||
|
{
|
||||||
|
fd->Error=false;
|
||||||
|
#ifndef _UNIX
|
||||||
|
if (IsWildcard(FindMask))
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd);
|
||||||
|
if (hFind==INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
FindClose(hFind);
|
||||||
|
#else
|
||||||
|
char FindMaskA[NM];
|
||||||
|
WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA));
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (GetSymLink)
|
||||||
|
{
|
||||||
|
#ifdef SAVE_LINKS
|
||||||
|
if (lstat(FindMaskA,&st)!=0)
|
||||||
|
#else
|
||||||
|
if (stat(FindMaskA,&st)!=0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
fd->Error=(errno!=ENOENT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (stat(FindMaskA,&st)!=0)
|
||||||
|
{
|
||||||
|
fd->Error=(errno!=ENOENT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fd->FileAttr=st.st_mode;
|
||||||
|
fd->Size=st.st_size;
|
||||||
|
|
||||||
|
#ifdef UNIX_TIME_NS
|
||||||
|
fd->mtime.SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec);
|
||||||
|
fd->atime.SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec);
|
||||||
|
fd->ctime.SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec);
|
||||||
|
#else
|
||||||
|
fd->mtime.SetUnix(st.st_mtime);
|
||||||
|
fd->atime.SetUnix(st.st_atime);
|
||||||
|
fd->ctime.SetUnix(st.st_ctime);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name));
|
||||||
|
#endif
|
||||||
|
fd->Flags=0;
|
||||||
|
fd->IsDir=IsDir(fd->FileAttr);
|
||||||
|
fd->IsLink=IsLink(fd->FileAttr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATA FindData;
|
||||||
|
if (hFind==INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
hFind=FindFirstFile(Mask,&FindData);
|
||||||
|
if (hFind==INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
wchar LongMask[NM];
|
||||||
|
if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask)))
|
||||||
|
hFind=FindFirstFile(LongMask,&FindData);
|
||||||
|
}
|
||||||
|
if (hFind==INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
int SysErr=GetLastError();
|
||||||
|
// We must not issue an error for "file not found" and "path not found",
|
||||||
|
// because it is normal to not find anything for wildcard mask when
|
||||||
|
// archiving. Also searching for non-existent file is normal in some
|
||||||
|
// other modules, like WinRAR scanning for winrar_theme_description.txt
|
||||||
|
// to check if any themes are available.
|
||||||
|
fd->Error=SysErr!=ERROR_FILE_NOT_FOUND &&
|
||||||
|
SysErr!=ERROR_PATH_NOT_FOUND &&
|
||||||
|
SysErr!=ERROR_NO_MORE_FILES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!FindNextFile(hFind,&FindData))
|
||||||
|
{
|
||||||
|
hFind=INVALID_HANDLE_VALUE;
|
||||||
|
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hFind!=INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
wcsncpyz(fd->Name,Mask,ASIZE(fd->Name));
|
||||||
|
SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name));
|
||||||
|
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
|
||||||
|
fd->FileAttr=FindData.dwFileAttributes;
|
||||||
|
fd->ftCreationTime=FindData.ftCreationTime;
|
||||||
|
fd->ftLastAccessTime=FindData.ftLastAccessTime;
|
||||||
|
fd->ftLastWriteTime=FindData.ftLastWriteTime;
|
||||||
|
fd->mtime.SetWinFT(&FindData.ftLastWriteTime);
|
||||||
|
fd->ctime.SetWinFT(&FindData.ftCreationTime);
|
||||||
|
fd->atime.SetWinFT(&FindData.ftLastAccessTime);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
fd->Flags=0;
|
||||||
|
return hFind;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
49
deps/unrar/find.hpp
vendored
Normal file
49
deps/unrar/find.hpp
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef _RAR_FINDDATA_
|
||||||
|
#define _RAR_FINDDATA_
|
||||||
|
|
||||||
|
enum FINDDATA_FLAGS {
|
||||||
|
FDDF_SECONDDIR=1 // Second encounter of same directory in SCAN_GETDIRSTWICE ScanTree mode.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FindData
|
||||||
|
{
|
||||||
|
wchar Name[NM];
|
||||||
|
uint64 Size;
|
||||||
|
uint FileAttr;
|
||||||
|
bool IsDir;
|
||||||
|
bool IsLink;
|
||||||
|
RarTime mtime;
|
||||||
|
RarTime ctime;
|
||||||
|
RarTime atime;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
FILETIME ftCreationTime;
|
||||||
|
FILETIME ftLastAccessTime;
|
||||||
|
FILETIME ftLastWriteTime;
|
||||||
|
#endif
|
||||||
|
uint Flags;
|
||||||
|
bool Error;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FindFile
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
static HANDLE Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wchar FindMask[NM];
|
||||||
|
bool FirstCall;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
HANDLE hFind;
|
||||||
|
#else
|
||||||
|
DIR *dirp;
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
FindFile();
|
||||||
|
~FindFile();
|
||||||
|
void SetMask(const wchar *Mask);
|
||||||
|
bool Next(FindData *fd,bool GetSymLink=false);
|
||||||
|
static bool FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink=false);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
52
deps/unrar/getbits.cpp
vendored
Normal file
52
deps/unrar/getbits.cpp
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
BitInput::BitInput(bool AllocBuffer)
|
||||||
|
{
|
||||||
|
ExternalBuffer=false;
|
||||||
|
if (AllocBuffer)
|
||||||
|
{
|
||||||
|
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
|
||||||
|
// So let's allocate 3 additional bytes for situation, when we need to
|
||||||
|
// read only 1 byte from the last position of buffer and avoid a crash
|
||||||
|
// from access to next 3 bytes, which contents we do not need.
|
||||||
|
size_t BufSize=MAX_SIZE+3;
|
||||||
|
InBuf=new byte[BufSize];
|
||||||
|
|
||||||
|
// Ensure that we get predictable results when accessing bytes in area
|
||||||
|
// not filled with read data.
|
||||||
|
memset(InBuf,0,BufSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
InBuf=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BitInput::~BitInput()
|
||||||
|
{
|
||||||
|
if (!ExternalBuffer)
|
||||||
|
delete[] InBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitInput::faddbits(uint Bits)
|
||||||
|
{
|
||||||
|
// Function wrapped version of inline addbits to save code size.
|
||||||
|
addbits(Bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint BitInput::fgetbits()
|
||||||
|
{
|
||||||
|
// Function wrapped version of inline getbits to save code size.
|
||||||
|
return getbits();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitInput::SetExternalBuffer(byte *Buf)
|
||||||
|
{
|
||||||
|
if (InBuf!=NULL && !ExternalBuffer)
|
||||||
|
delete[] InBuf;
|
||||||
|
InBuf=Buf;
|
||||||
|
ExternalBuffer=true;
|
||||||
|
}
|
||||||
|
|
68
deps/unrar/getbits.hpp
vendored
Normal file
68
deps/unrar/getbits.hpp
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#ifndef _RAR_GETBITS_
|
||||||
|
#define _RAR_GETBITS_
|
||||||
|
|
||||||
|
class BitInput
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer.
|
||||||
|
|
||||||
|
int InAddr; // Curent byte position in the buffer.
|
||||||
|
int InBit; // Current bit position in the current byte.
|
||||||
|
|
||||||
|
bool ExternalBuffer;
|
||||||
|
public:
|
||||||
|
BitInput(bool AllocBuffer);
|
||||||
|
~BitInput();
|
||||||
|
|
||||||
|
byte *InBuf; // Dynamically allocated input buffer.
|
||||||
|
|
||||||
|
void InitBitInput()
|
||||||
|
{
|
||||||
|
InAddr=InBit=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move forward by 'Bits' bits.
|
||||||
|
void addbits(uint Bits)
|
||||||
|
{
|
||||||
|
Bits+=InBit;
|
||||||
|
InAddr+=Bits>>3;
|
||||||
|
InBit=Bits&7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return 16 bits from current position in the buffer.
|
||||||
|
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||||
|
uint getbits()
|
||||||
|
{
|
||||||
|
uint BitField=(uint)InBuf[InAddr] << 16;
|
||||||
|
BitField|=(uint)InBuf[InAddr+1] << 8;
|
||||||
|
BitField|=(uint)InBuf[InAddr+2];
|
||||||
|
BitField >>= (8-InBit);
|
||||||
|
return BitField & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return 32 bits from current position in the buffer.
|
||||||
|
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||||
|
uint getbits32()
|
||||||
|
{
|
||||||
|
uint BitField=(uint)InBuf[InAddr] << 24;
|
||||||
|
BitField|=(uint)InBuf[InAddr+1] << 16;
|
||||||
|
BitField|=(uint)InBuf[InAddr+2] << 8;
|
||||||
|
BitField|=(uint)InBuf[InAddr+3];
|
||||||
|
BitField <<= InBit;
|
||||||
|
BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
|
||||||
|
return BitField & 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void faddbits(uint Bits);
|
||||||
|
uint fgetbits();
|
||||||
|
|
||||||
|
// Check if buffer has enough space for IncPtr bytes. Returns 'true'
|
||||||
|
// if buffer will be overflown.
|
||||||
|
bool Overflow(uint IncPtr)
|
||||||
|
{
|
||||||
|
return InAddr+IncPtr>=MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetExternalBuffer(byte *Buf);
|
||||||
|
};
|
||||||
|
#endif
|
7
deps/unrar/global.cpp
vendored
Normal file
7
deps/unrar/global.cpp
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#define INCLUDEGLOBAL
|
||||||
|
|
||||||
|
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
||||||
|
#pragma hdrstop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "rar.hpp"
|
14
deps/unrar/global.hpp
vendored
Normal file
14
deps/unrar/global.hpp
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _RAR_GLOBAL_
|
||||||
|
#define _RAR_GLOBAL_
|
||||||
|
|
||||||
|
#ifdef INCLUDEGLOBAL
|
||||||
|
#define EXTVAR
|
||||||
|
#else
|
||||||
|
#define EXTVAR extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTVAR ErrorHandler ErrHandler;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
39
deps/unrar/hardlinks.cpp
vendored
Normal file
39
deps/unrar/hardlinks.cpp
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
|
||||||
|
{
|
||||||
|
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
|
||||||
|
|
||||||
|
if (!FileExist(NameExisting))
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||||
|
uiMsg(UIERROR_NOLINKTARGET);
|
||||||
|
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CreatePath(NameNew,true);
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool Success=CreateHardLink(NameNew,NameExisting,NULL)!=0;
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||||
|
ErrHandler.SysErrMsg();
|
||||||
|
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
#elif defined(_UNIX)
|
||||||
|
char NameExistingA[NM],NameNewA[NM];
|
||||||
|
WideToChar(NameExisting,NameExistingA,ASIZE(NameExistingA));
|
||||||
|
WideToChar(NameNew,NameNewA,ASIZE(NameNewA));
|
||||||
|
bool Success=link(NameExistingA,NameNewA)==0;
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||||
|
ErrHandler.SysErrMsg();
|
||||||
|
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
135
deps/unrar/hash.cpp
vendored
Normal file
135
deps/unrar/hash.cpp
vendored
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
void HashValue::Init(HASH_TYPE Type)
|
||||||
|
{
|
||||||
|
HashValue::Type=Type;
|
||||||
|
|
||||||
|
// Zero length data CRC32 is 0. It is important to set it when creating
|
||||||
|
// headers with no following data like directories or symlinks.
|
||||||
|
if (Type==HASH_RAR14 || Type==HASH_CRC32)
|
||||||
|
CRC32=0;
|
||||||
|
if (Type==HASH_BLAKE2)
|
||||||
|
{
|
||||||
|
// dd0e891776933f43c7d032b08a917e25741f8aa9a12c12e1cac8801500f2ca4f
|
||||||
|
// is BLAKE2sp hash of empty data. We init the structure to this value,
|
||||||
|
// so if we create a file or service header with no following data like
|
||||||
|
// "file copy" or "symlink", we set the checksum to proper value avoiding
|
||||||
|
// additional header type or size checks when extracting.
|
||||||
|
static byte EmptyHash[32]={
|
||||||
|
0xdd, 0x0e, 0x89, 0x17, 0x76, 0x93, 0x3f, 0x43,
|
||||||
|
0xc7, 0xd0, 0x32, 0xb0, 0x8a, 0x91, 0x7e, 0x25,
|
||||||
|
0x74, 0x1f, 0x8a, 0xa9, 0xa1, 0x2c, 0x12, 0xe1,
|
||||||
|
0xca, 0xc8, 0x80, 0x15, 0x00, 0xf2, 0xca, 0x4f
|
||||||
|
};
|
||||||
|
memcpy(Digest,EmptyHash,sizeof(Digest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool HashValue::operator == (const HashValue &cmp)
|
||||||
|
{
|
||||||
|
if (Type==HASH_NONE || cmp.Type==HASH_NONE)
|
||||||
|
return true;
|
||||||
|
if (Type==HASH_RAR14 && cmp.Type==HASH_RAR14 ||
|
||||||
|
Type==HASH_CRC32 && cmp.Type==HASH_CRC32)
|
||||||
|
return CRC32==cmp.CRC32;
|
||||||
|
if (Type==HASH_BLAKE2 && cmp.Type==HASH_BLAKE2)
|
||||||
|
return memcmp(Digest,cmp.Digest,sizeof(Digest))==0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataHash::DataHash()
|
||||||
|
{
|
||||||
|
blake2ctx=NULL;
|
||||||
|
HashType=HASH_NONE;
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
ThPool=NULL;
|
||||||
|
MaxThreads=0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataHash::~DataHash()
|
||||||
|
{
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
delete ThPool;
|
||||||
|
#endif
|
||||||
|
cleandata(&CurCRC32, sizeof(CurCRC32));
|
||||||
|
if (blake2ctx!=NULL)
|
||||||
|
{
|
||||||
|
cleandata(blake2ctx, sizeof(blake2sp_state));
|
||||||
|
delete blake2ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DataHash::Init(HASH_TYPE Type,uint MaxThreads)
|
||||||
|
{
|
||||||
|
if (blake2ctx==NULL)
|
||||||
|
blake2ctx=new blake2sp_state;
|
||||||
|
HashType=Type;
|
||||||
|
if (Type==HASH_RAR14)
|
||||||
|
CurCRC32=0;
|
||||||
|
if (Type==HASH_CRC32)
|
||||||
|
CurCRC32=0xffffffff; // Initial CRC32 value.
|
||||||
|
if (Type==HASH_BLAKE2)
|
||||||
|
blake2sp_init(blake2ctx);
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DataHash::Update(const void *Data,size_t DataSize)
|
||||||
|
{
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
if (HashType==HASH_RAR14)
|
||||||
|
CurCRC32=Checksum14((ushort)CurCRC32,Data,DataSize);
|
||||||
|
#endif
|
||||||
|
if (HashType==HASH_CRC32)
|
||||||
|
CurCRC32=CRC32(CurCRC32,Data,DataSize);
|
||||||
|
|
||||||
|
if (HashType==HASH_BLAKE2)
|
||||||
|
{
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
if (MaxThreads>1 && ThPool==NULL)
|
||||||
|
ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER);
|
||||||
|
blake2ctx->ThPool=ThPool;
|
||||||
|
blake2ctx->MaxThreads=MaxThreads;
|
||||||
|
#endif
|
||||||
|
blake2sp_update( blake2ctx, (byte *)Data, DataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DataHash::Result(HashValue *Result)
|
||||||
|
{
|
||||||
|
Result->Type=HashType;
|
||||||
|
if (HashType==HASH_RAR14)
|
||||||
|
Result->CRC32=CurCRC32;
|
||||||
|
if (HashType==HASH_CRC32)
|
||||||
|
Result->CRC32=CurCRC32^0xffffffff;
|
||||||
|
if (HashType==HASH_BLAKE2)
|
||||||
|
{
|
||||||
|
// Preserve the original context, so we can continue hashing if necessary.
|
||||||
|
blake2sp_state res=*blake2ctx;
|
||||||
|
blake2sp_final(&res,Result->Digest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint DataHash::GetCRC32()
|
||||||
|
{
|
||||||
|
return HashType==HASH_CRC32 ? CurCRC32^0xffffffff : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DataHash::Cmp(HashValue *CmpValue,byte *Key)
|
||||||
|
{
|
||||||
|
HashValue Final;
|
||||||
|
Result(&Final);
|
||||||
|
if (Key!=NULL)
|
||||||
|
ConvertHashToMAC(&Final,Key);
|
||||||
|
return Final==*CmpValue;
|
||||||
|
}
|
52
deps/unrar/hash.hpp
vendored
Normal file
52
deps/unrar/hash.hpp
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef _RAR_DATAHASH_
|
||||||
|
#define _RAR_DATAHASH_
|
||||||
|
|
||||||
|
enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
|
||||||
|
|
||||||
|
struct HashValue
|
||||||
|
{
|
||||||
|
void Init(HASH_TYPE Type);
|
||||||
|
bool operator == (const HashValue &cmp);
|
||||||
|
bool operator != (const HashValue &cmp) {return !(*this==cmp);}
|
||||||
|
|
||||||
|
HASH_TYPE Type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint CRC32;
|
||||||
|
byte Digest[SHA256_DIGEST_SIZE];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
class ThreadPool;
|
||||||
|
class DataHash;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
class DataHash
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
HASH_TYPE HashType;
|
||||||
|
uint CurCRC32;
|
||||||
|
blake2sp_state *blake2ctx;
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
ThreadPool *ThPool;
|
||||||
|
|
||||||
|
uint MaxThreads;
|
||||||
|
// Upper limit for maximum threads to prevent wasting threads in pool.
|
||||||
|
static const uint MaxHashThreads=8;
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
DataHash();
|
||||||
|
~DataHash();
|
||||||
|
void Init(HASH_TYPE Type,uint MaxThreads);
|
||||||
|
void Update(const void *Data,size_t DataSize);
|
||||||
|
void Result(HashValue *Result);
|
||||||
|
uint GetCRC32();
|
||||||
|
bool Cmp(HashValue *CmpValue,byte *Key);
|
||||||
|
HASH_TYPE Type() {return HashType;}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
61
deps/unrar/headers.cpp
vendored
Normal file
61
deps/unrar/headers.cpp
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
void FileHeader::Reset(size_t SubDataSize)
|
||||||
|
{
|
||||||
|
SubData.Alloc(SubDataSize);
|
||||||
|
BaseBlock::Reset();
|
||||||
|
FileHash.Init(HASH_NONE);
|
||||||
|
mtime.Reset();
|
||||||
|
atime.Reset();
|
||||||
|
ctime.Reset();
|
||||||
|
SplitBefore=false;
|
||||||
|
SplitAfter=false;
|
||||||
|
|
||||||
|
UnknownUnpSize=0;
|
||||||
|
|
||||||
|
SubFlags=0; // Important for RAR 3.0 subhead.
|
||||||
|
|
||||||
|
CryptMethod=CRYPT_NONE;
|
||||||
|
Encrypted=false;
|
||||||
|
SaltSet=false;
|
||||||
|
UsePswCheck=false;
|
||||||
|
UseHashKey=false;
|
||||||
|
Lg2Count=0;
|
||||||
|
|
||||||
|
Solid=false;
|
||||||
|
Dir=false;
|
||||||
|
WinSize=0;
|
||||||
|
Inherited=false;
|
||||||
|
SubBlock=false;
|
||||||
|
CommentInHeader=false;
|
||||||
|
Version=false;
|
||||||
|
LargeFile=false;
|
||||||
|
|
||||||
|
RedirType=FSREDIR_NONE;
|
||||||
|
DirTarget=false;
|
||||||
|
UnixOwnerSet=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FileHeader& FileHeader::operator = (FileHeader &hd)
|
||||||
|
{
|
||||||
|
SubData.Reset();
|
||||||
|
memcpy(this,&hd,sizeof(*this));
|
||||||
|
SubData.CleanData();
|
||||||
|
SubData=hd.SubData;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainHeader::Reset()
|
||||||
|
{
|
||||||
|
HighPosAV=0;
|
||||||
|
PosAV=0;
|
||||||
|
CommentInHeader=false;
|
||||||
|
PackComment=false;
|
||||||
|
Locator=false;
|
||||||
|
QOpenOffset=0;
|
||||||
|
QOpenMaxSize=0;
|
||||||
|
RROffset=0;
|
||||||
|
RRMaxSize=0;
|
||||||
|
}
|
354
deps/unrar/headers.hpp
vendored
Normal file
354
deps/unrar/headers.hpp
vendored
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
#ifndef _RAR_HEADERS_
|
||||||
|
#define _RAR_HEADERS_
|
||||||
|
|
||||||
|
#define SIZEOF_MARKHEAD3 7 // Size of RAR 4.x archive mark header.
|
||||||
|
#define SIZEOF_MAINHEAD14 7 // Size of RAR 1.4 main archive header.
|
||||||
|
#define SIZEOF_MAINHEAD3 13 // Size of RAR 4.x main archive header.
|
||||||
|
#define SIZEOF_FILEHEAD14 21 // Size of RAR 1.4 file header.
|
||||||
|
#define SIZEOF_FILEHEAD3 32 // Size of RAR 3.0 file header.
|
||||||
|
#define SIZEOF_SHORTBLOCKHEAD 7
|
||||||
|
#define SIZEOF_LONGBLOCKHEAD 11
|
||||||
|
#define SIZEOF_SUBBLOCKHEAD 14
|
||||||
|
#define SIZEOF_COMMHEAD 13
|
||||||
|
#define SIZEOF_PROTECTHEAD 26
|
||||||
|
#define SIZEOF_UOHEAD 18
|
||||||
|
#define SIZEOF_STREAMHEAD 26
|
||||||
|
|
||||||
|
#define VER_PACK 29U
|
||||||
|
#define VER_PACK5 50U // It is stored as 0, but we subtract 50 when saving an archive.
|
||||||
|
#define VER_UNPACK 29U
|
||||||
|
#define VER_UNPACK5 50U // It is stored as 0, but we add 50 when reading an archive.
|
||||||
|
#define VER_UNKNOWN 9999U // Just some large value.
|
||||||
|
|
||||||
|
#define MHD_VOLUME 0x0001U
|
||||||
|
|
||||||
|
// Old style main archive comment embed into main archive header. Must not
|
||||||
|
// be used in new archives anymore.
|
||||||
|
#define MHD_COMMENT 0x0002U
|
||||||
|
|
||||||
|
#define MHD_LOCK 0x0004U
|
||||||
|
#define MHD_SOLID 0x0008U
|
||||||
|
#define MHD_PACK_COMMENT 0x0010U
|
||||||
|
#define MHD_NEWNUMBERING 0x0010U
|
||||||
|
#define MHD_AV 0x0020U
|
||||||
|
#define MHD_PROTECT 0x0040U
|
||||||
|
#define MHD_PASSWORD 0x0080U
|
||||||
|
#define MHD_FIRSTVOLUME 0x0100U
|
||||||
|
|
||||||
|
#define LHD_SPLIT_BEFORE 0x0001U
|
||||||
|
#define LHD_SPLIT_AFTER 0x0002U
|
||||||
|
#define LHD_PASSWORD 0x0004U
|
||||||
|
|
||||||
|
// Old style file comment embed into file header. Must not be used
|
||||||
|
// in new archives anymore.
|
||||||
|
#define LHD_COMMENT 0x0008U
|
||||||
|
|
||||||
|
// For non-file subheaders it denotes 'subblock having a parent file' flag.
|
||||||
|
#define LHD_SOLID 0x0010U
|
||||||
|
|
||||||
|
|
||||||
|
#define LHD_WINDOWMASK 0x00e0U
|
||||||
|
#define LHD_WINDOW64 0x0000U
|
||||||
|
#define LHD_WINDOW128 0x0020U
|
||||||
|
#define LHD_WINDOW256 0x0040U
|
||||||
|
#define LHD_WINDOW512 0x0060U
|
||||||
|
#define LHD_WINDOW1024 0x0080U
|
||||||
|
#define LHD_WINDOW2048 0x00a0U
|
||||||
|
#define LHD_WINDOW4096 0x00c0U
|
||||||
|
#define LHD_DIRECTORY 0x00e0U
|
||||||
|
|
||||||
|
#define LHD_LARGE 0x0100U
|
||||||
|
#define LHD_UNICODE 0x0200U
|
||||||
|
#define LHD_SALT 0x0400U
|
||||||
|
#define LHD_VERSION 0x0800U
|
||||||
|
#define LHD_EXTTIME 0x1000U
|
||||||
|
|
||||||
|
#define SKIP_IF_UNKNOWN 0x4000U
|
||||||
|
#define LONG_BLOCK 0x8000U
|
||||||
|
|
||||||
|
#define EARC_NEXT_VOLUME 0x0001U // Not last volume.
|
||||||
|
#define EARC_DATACRC 0x0002U // Store CRC32 of RAR archive (now is used only in volumes).
|
||||||
|
#define EARC_REVSPACE 0x0004U // Reserve space for end of REV file 7 byte record.
|
||||||
|
#define EARC_VOLNUMBER 0x0008U // Store a number of current volume.
|
||||||
|
|
||||||
|
enum HEADER_TYPE {
|
||||||
|
// RAR 5.0 header types.
|
||||||
|
HEAD_MARK=0x00, HEAD_MAIN=0x01, HEAD_FILE=0x02, HEAD_SERVICE=0x03,
|
||||||
|
HEAD_CRYPT=0x04, HEAD_ENDARC=0x05, HEAD_UNKNOWN=0xff,
|
||||||
|
|
||||||
|
// RAR 1.5 - 4.x header types.
|
||||||
|
HEAD3_MARK=0x72,HEAD3_MAIN=0x73,HEAD3_FILE=0x74,HEAD3_CMT=0x75,
|
||||||
|
HEAD3_AV=0x76,HEAD3_OLDSERVICE=0x77,HEAD3_PROTECT=0x78,HEAD3_SIGN=0x79,
|
||||||
|
HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// RAR 2.9 and earlier.
|
||||||
|
enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
|
||||||
|
NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
|
||||||
|
|
||||||
|
|
||||||
|
// Internal implementation, depends on archive format version.
|
||||||
|
enum HOST_SYSTEM {
|
||||||
|
// RAR 5.0 host OS
|
||||||
|
HOST5_WINDOWS=0,HOST5_UNIX=1,
|
||||||
|
|
||||||
|
// RAR 3.0 host OS.
|
||||||
|
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
|
||||||
|
HOST_BEOS=5,HOST_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unified archive format independent implementation.
|
||||||
|
enum HOST_SYSTEM_TYPE {
|
||||||
|
HSYS_WINDOWS, HSYS_UNIX, HSYS_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// We also use these values in extra field, so do not modify them.
|
||||||
|
enum FILE_SYSTEM_REDIRECT {
|
||||||
|
FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
|
||||||
|
FSREDIR_HARDLINK, FSREDIR_FILECOPY
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define SUBHEAD_TYPE_CMT L"CMT"
|
||||||
|
#define SUBHEAD_TYPE_QOPEN L"QO"
|
||||||
|
#define SUBHEAD_TYPE_ACL L"ACL"
|
||||||
|
#define SUBHEAD_TYPE_STREAM L"STM"
|
||||||
|
#define SUBHEAD_TYPE_UOWNER L"UOW"
|
||||||
|
#define SUBHEAD_TYPE_AV L"AV"
|
||||||
|
#define SUBHEAD_TYPE_RR L"RR"
|
||||||
|
#define SUBHEAD_TYPE_OS2EA L"EA2"
|
||||||
|
|
||||||
|
/* new file inherits a subblock when updating a host file */
|
||||||
|
#define SUBHEAD_FLAGS_INHERITED 0x80000000
|
||||||
|
|
||||||
|
#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
struct MarkHeader
|
||||||
|
{
|
||||||
|
byte Mark[8];
|
||||||
|
|
||||||
|
// Following fields are virtual and not present in real blocks.
|
||||||
|
uint HeadSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct BaseBlock
|
||||||
|
{
|
||||||
|
uint HeadCRC; // 'ushort' for RAR 1.5.
|
||||||
|
HEADER_TYPE HeaderType; // 1 byte for RAR 1.5.
|
||||||
|
uint Flags; // 'ushort' for RAR 1.5.
|
||||||
|
uint HeadSize; // 'ushort' for RAR 1.5, up to 2 MB for RAR 5.0.
|
||||||
|
|
||||||
|
bool SkipIfUnknown;
|
||||||
|
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
SkipIfUnknown=false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct BlockHeader:BaseBlock
|
||||||
|
{
|
||||||
|
uint DataSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct MainHeader:BaseBlock
|
||||||
|
{
|
||||||
|
ushort HighPosAV;
|
||||||
|
uint PosAV;
|
||||||
|
bool CommentInHeader;
|
||||||
|
bool PackComment; // For RAR 1.4 archive format only.
|
||||||
|
bool Locator;
|
||||||
|
uint64 QOpenOffset; // Offset of quick list record.
|
||||||
|
uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
|
||||||
|
uint64 RROffset; // Offset of recovery record.
|
||||||
|
uint64 RRMaxSize; // Maximum size of RR offset in locator extra field.
|
||||||
|
void Reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct FileHeader:BlockHeader
|
||||||
|
{
|
||||||
|
byte HostOS;
|
||||||
|
uint UnpVer; // It is 1 byte in RAR29 and bit field in RAR5.
|
||||||
|
byte Method;
|
||||||
|
union {
|
||||||
|
uint FileAttr;
|
||||||
|
uint SubFlags;
|
||||||
|
};
|
||||||
|
wchar FileName[NM];
|
||||||
|
|
||||||
|
Array<byte> SubData;
|
||||||
|
|
||||||
|
RarTime mtime;
|
||||||
|
RarTime ctime;
|
||||||
|
RarTime atime;
|
||||||
|
|
||||||
|
int64 PackSize;
|
||||||
|
int64 UnpSize;
|
||||||
|
int64 MaxSize; // Reserve packed and unpacked size bytes for vint of this size.
|
||||||
|
|
||||||
|
HashValue FileHash;
|
||||||
|
|
||||||
|
uint FileFlags;
|
||||||
|
|
||||||
|
bool SplitBefore;
|
||||||
|
bool SplitAfter;
|
||||||
|
|
||||||
|
bool UnknownUnpSize;
|
||||||
|
|
||||||
|
bool Encrypted;
|
||||||
|
CRYPT_METHOD CryptMethod;
|
||||||
|
bool SaltSet;
|
||||||
|
byte Salt[SIZE_SALT50];
|
||||||
|
byte InitV[SIZE_INITV];
|
||||||
|
bool UsePswCheck;
|
||||||
|
byte PswCheck[SIZE_PSWCHECK];
|
||||||
|
|
||||||
|
// Use HMAC calculated from HashKey and checksum instead of plain checksum.
|
||||||
|
bool UseHashKey;
|
||||||
|
|
||||||
|
// Key to convert checksum to HMAC. Derived from password with PBKDF2
|
||||||
|
// using additional iterations.
|
||||||
|
byte HashKey[SHA256_DIGEST_SIZE];
|
||||||
|
|
||||||
|
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||||
|
|
||||||
|
bool Solid;
|
||||||
|
bool Dir;
|
||||||
|
bool CommentInHeader; // RAR 2.0 file comment.
|
||||||
|
bool Version; // name.ext;ver file name containing the version number.
|
||||||
|
size_t WinSize;
|
||||||
|
bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only).
|
||||||
|
|
||||||
|
// 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0.
|
||||||
|
bool LargeFile;
|
||||||
|
|
||||||
|
// 'true' for HEAD_SERVICE block, which is a child of preceding file block.
|
||||||
|
// RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
|
||||||
|
bool SubBlock;
|
||||||
|
|
||||||
|
HOST_SYSTEM_TYPE HSType;
|
||||||
|
|
||||||
|
FILE_SYSTEM_REDIRECT RedirType;
|
||||||
|
wchar RedirName[NM];
|
||||||
|
bool DirTarget;
|
||||||
|
|
||||||
|
bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric;
|
||||||
|
char UnixOwnerName[256],UnixGroupName[256];
|
||||||
|
#ifdef _UNIX
|
||||||
|
uid_t UnixOwnerID;
|
||||||
|
gid_t UnixGroupID;
|
||||||
|
#else // Need these Unix fields in Windows too for 'list' command.
|
||||||
|
uint UnixOwnerID;
|
||||||
|
uint UnixGroupID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Reset(size_t SubDataSize=0);
|
||||||
|
|
||||||
|
bool CmpName(const wchar *Name)
|
||||||
|
{
|
||||||
|
return(wcscmp(FileName,Name)==0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileHeader& operator = (FileHeader &hd);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct EndArcHeader:BaseBlock
|
||||||
|
{
|
||||||
|
// Optional CRC32 of entire archive up to start of EndArcHeader block.
|
||||||
|
// Present in RAR 4.x archives if EARC_DATACRC flag is set.
|
||||||
|
uint ArcDataCRC;
|
||||||
|
|
||||||
|
uint VolNumber; // Optional number of current volume.
|
||||||
|
|
||||||
|
// 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
|
||||||
|
|
||||||
|
bool NextVolume; // Not last volume.
|
||||||
|
bool DataCRC;
|
||||||
|
bool RevSpace;
|
||||||
|
bool StoreVolNumber;
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
BaseBlock::Reset();
|
||||||
|
NextVolume=false;
|
||||||
|
DataCRC=false;
|
||||||
|
RevSpace=false;
|
||||||
|
StoreVolNumber=false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CryptHeader:BaseBlock
|
||||||
|
{
|
||||||
|
bool UsePswCheck;
|
||||||
|
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||||
|
byte Salt[SIZE_SALT50];
|
||||||
|
byte PswCheck[SIZE_PSWCHECK];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// SubBlockHeader and its successors were used in RAR 2.x format.
|
||||||
|
// RAR 4.x uses FileHeader with HEAD_SERVICE HeaderType for subblocks.
|
||||||
|
struct SubBlockHeader:BlockHeader
|
||||||
|
{
|
||||||
|
ushort SubType;
|
||||||
|
byte Level;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CommentHeader:BaseBlock
|
||||||
|
{
|
||||||
|
ushort UnpSize;
|
||||||
|
byte UnpVer;
|
||||||
|
byte Method;
|
||||||
|
ushort CommCRC;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ProtectHeader:BlockHeader
|
||||||
|
{
|
||||||
|
byte Version;
|
||||||
|
ushort RecSectors;
|
||||||
|
uint TotalBlocks;
|
||||||
|
byte Mark[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct UnixOwnersHeader:SubBlockHeader
|
||||||
|
{
|
||||||
|
ushort OwnerNameSize;
|
||||||
|
ushort GroupNameSize;
|
||||||
|
/* dummy */
|
||||||
|
char OwnerName[256];
|
||||||
|
char GroupName[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct EAHeader:SubBlockHeader
|
||||||
|
{
|
||||||
|
uint UnpSize;
|
||||||
|
byte UnpVer;
|
||||||
|
byte Method;
|
||||||
|
uint EACRC;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct StreamHeader:SubBlockHeader
|
||||||
|
{
|
||||||
|
uint UnpSize;
|
||||||
|
byte UnpVer;
|
||||||
|
byte Method;
|
||||||
|
uint StreamCRC;
|
||||||
|
ushort StreamNameSize;
|
||||||
|
char StreamName[260];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
100
deps/unrar/headers5.hpp
vendored
Normal file
100
deps/unrar/headers5.hpp
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef _RAR_HEADERS5_
|
||||||
|
#define _RAR_HEADERS5_
|
||||||
|
|
||||||
|
#define SIZEOF_MARKHEAD5 8 // RAR 5.0 signature length.
|
||||||
|
#define SIZEOF_SHORTBLOCKHEAD5 7 // Smallest RAR 5.0 block size.
|
||||||
|
|
||||||
|
// RAR 5.0 block flags common for all blocks.
|
||||||
|
|
||||||
|
// Additional extra area is present in the end of block header.
|
||||||
|
#define HFL_EXTRA 0x0001
|
||||||
|
// Additional data area is present in the end of block header.
|
||||||
|
#define HFL_DATA 0x0002
|
||||||
|
// Unknown blocks with this flag must be skipped when updating an archive.
|
||||||
|
#define HFL_SKIPIFUNKNOWN 0x0004
|
||||||
|
// Data area of this block is continuing from previous volume.
|
||||||
|
#define HFL_SPLITBEFORE 0x0008
|
||||||
|
// Data area of this block is continuing in next volume.
|
||||||
|
#define HFL_SPLITAFTER 0x0010
|
||||||
|
// Block depends on preceding file block.
|
||||||
|
#define HFL_CHILD 0x0020
|
||||||
|
// Preserve a child block if host is modified.
|
||||||
|
#define HFL_INHERITED 0x0040
|
||||||
|
|
||||||
|
// RAR 5.0 main archive header specific flags.
|
||||||
|
#define MHFL_VOLUME 0x0001 // Volume.
|
||||||
|
#define MHFL_VOLNUMBER 0x0002 // Volume number field is present. True for all volumes except first.
|
||||||
|
#define MHFL_SOLID 0x0004 // Solid archive.
|
||||||
|
#define MHFL_PROTECT 0x0008 // Recovery record is present.
|
||||||
|
#define MHFL_LOCK 0x0010 // Locked archive.
|
||||||
|
|
||||||
|
// RAR 5.0 file header specific flags.
|
||||||
|
#define FHFL_DIRECTORY 0x0001 // Directory.
|
||||||
|
#define FHFL_UTIME 0x0002 // Time field in Unix format is present.
|
||||||
|
#define FHFL_CRC32 0x0004 // CRC32 field is present.
|
||||||
|
#define FHFL_UNPUNKNOWN 0x0008 // Unknown unpacked size.
|
||||||
|
|
||||||
|
// RAR 5.0 end of archive header specific flags.
|
||||||
|
#define EHFL_NEXTVOLUME 0x0001 // Not last volume.
|
||||||
|
|
||||||
|
// RAR 5.0 archive encryption header specific flags.
|
||||||
|
#define CHFL_CRYPT_PSWCHECK 0x0001 // Password check data is present.
|
||||||
|
|
||||||
|
|
||||||
|
// RAR 5.0 file compression flags.
|
||||||
|
#define FCI_ALGO_BIT0 0x0001 // Version of compression algorithm.
|
||||||
|
#define FCI_ALGO_BIT1 0x0002 // 0 .. 63.
|
||||||
|
#define FCI_ALGO_BIT2 0x0004
|
||||||
|
#define FCI_ALGO_BIT3 0x0008
|
||||||
|
#define FCI_ALGO_BIT4 0x0010
|
||||||
|
#define FCI_ALGO_BIT5 0x0020
|
||||||
|
#define FCI_SOLID 0x0040 // Solid flag.
|
||||||
|
#define FCI_METHOD_BIT0 0x0080 // Compression method.
|
||||||
|
#define FCI_METHOD_BIT1 0x0100 // 0 .. 5 (6 and 7 are not used).
|
||||||
|
#define FCI_METHOD_BIT2 0x0200
|
||||||
|
#define FCI_DICT_BIT0 0x0400 // Dictionary size.
|
||||||
|
#define FCI_DICT_BIT1 0x0800 // 128 KB .. 4 GB.
|
||||||
|
#define FCI_DICT_BIT2 0x1000
|
||||||
|
#define FCI_DICT_BIT3 0x2000
|
||||||
|
|
||||||
|
// Main header extra field values.
|
||||||
|
#define MHEXTRA_LOCATOR 0x01 // Position of quick list and other blocks.
|
||||||
|
|
||||||
|
// Flags for MHEXTRA_LOCATOR.
|
||||||
|
#define MHEXTRA_LOCATOR_QLIST 0x01 // Quick open offset is present.
|
||||||
|
#define MHEXTRA_LOCATOR_RR 0x02 // Recovery record offset is present.
|
||||||
|
|
||||||
|
// File and service header extra field values.
|
||||||
|
#define FHEXTRA_CRYPT 0x01 // Encryption parameters.
|
||||||
|
#define FHEXTRA_HASH 0x02 // File hash.
|
||||||
|
#define FHEXTRA_HTIME 0x03 // High precision file time.
|
||||||
|
#define FHEXTRA_VERSION 0x04 // File version information.
|
||||||
|
#define FHEXTRA_REDIR 0x05 // File system redirection (links, etc.).
|
||||||
|
#define FHEXTRA_UOWNER 0x06 // Unix owner and group information.
|
||||||
|
#define FHEXTRA_SUBDATA 0x07 // Service header subdata array.
|
||||||
|
|
||||||
|
|
||||||
|
// Hash type values for FHEXTRA_HASH.
|
||||||
|
#define FHEXTRA_HASH_BLAKE2 0x00
|
||||||
|
|
||||||
|
// Flags for FHEXTRA_HTIME.
|
||||||
|
#define FHEXTRA_HTIME_UNIXTIME 0x01 // Use Unix time_t format.
|
||||||
|
#define FHEXTRA_HTIME_MTIME 0x02 // mtime is present.
|
||||||
|
#define FHEXTRA_HTIME_CTIME 0x04 // ctime is present.
|
||||||
|
#define FHEXTRA_HTIME_ATIME 0x08 // atime is present.
|
||||||
|
#define FHEXTRA_HTIME_UNIX_NS 0x10 // Unix format with nanosecond precision.
|
||||||
|
|
||||||
|
// Flags for FHEXTRA_CRYPT.
|
||||||
|
#define FHEXTRA_CRYPT_PSWCHECK 0x01 // Store password check data.
|
||||||
|
#define FHEXTRA_CRYPT_HASHMAC 0x02 // Use MAC for unpacked data checksums.
|
||||||
|
|
||||||
|
// Flags for FHEXTRA_REDIR.
|
||||||
|
#define FHEXTRA_REDIR_DIR 0x01 // Link target is directory.
|
||||||
|
|
||||||
|
// Flags for FHEXTRA_UOWNER.
|
||||||
|
#define FHEXTRA_UOWNER_UNAME 0x01 // User name string is present.
|
||||||
|
#define FHEXTRA_UOWNER_GNAME 0x02 // Group name string is present.
|
||||||
|
#define FHEXTRA_UOWNER_NUMUID 0x04 // Numeric user ID is present.
|
||||||
|
#define FHEXTRA_UOWNER_NUMGID 0x08 // Numeric group ID is present.
|
||||||
|
|
||||||
|
#endif
|
24
deps/unrar/isnt.cpp
vendored
Normal file
24
deps/unrar/isnt.cpp
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
DWORD WinNT()
|
||||||
|
{
|
||||||
|
static int dwPlatformId=-1;
|
||||||
|
static DWORD dwMajorVersion,dwMinorVersion;
|
||||||
|
if (dwPlatformId==-1)
|
||||||
|
{
|
||||||
|
OSVERSIONINFO WinVer;
|
||||||
|
WinVer.dwOSVersionInfoSize=sizeof(WinVer);
|
||||||
|
GetVersionEx(&WinVer);
|
||||||
|
dwPlatformId=WinVer.dwPlatformId;
|
||||||
|
dwMajorVersion=WinVer.dwMajorVersion;
|
||||||
|
dwMinorVersion=WinVer.dwMinorVersion;
|
||||||
|
}
|
||||||
|
DWORD Result=0;
|
||||||
|
if (dwPlatformId==VER_PLATFORM_WIN32_NT)
|
||||||
|
Result=dwMajorVersion*0x100+dwMinorVersion;
|
||||||
|
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
#endif
|
13
deps/unrar/isnt.hpp
vendored
Normal file
13
deps/unrar/isnt.hpp
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _RAR_ISNT_
|
||||||
|
#define _RAR_ISNT_
|
||||||
|
|
||||||
|
enum WINNT_VERSION {
|
||||||
|
WNT_NONE=0,WNT_NT351=0x0333,WNT_NT4=0x0400,WNT_W2000=0x0500,
|
||||||
|
WNT_WXP=0x0501,WNT_W2003=0x0502,WNT_VISTA=0x0600,WNT_W7=0x0601,
|
||||||
|
WNT_W8=0x0602,WNT_W81=0x0603,WNT_W10=0x0a00
|
||||||
|
};
|
||||||
|
|
||||||
|
DWORD WinNT();
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
42
deps/unrar/license.txt
vendored
Normal file
42
deps/unrar/license.txt
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
****** ***** ****** UnRAR - free utility for RAR archives
|
||||||
|
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
****** ******* ****** License for use and distribution of
|
||||||
|
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
** ** ** ** ** ** FREE portable version
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The source code of UnRAR utility is freeware. This means:
|
||||||
|
|
||||||
|
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||||
|
owned by the author - Alexander Roshal.
|
||||||
|
|
||||||
|
2. UnRAR source code may be used in any software to handle
|
||||||
|
RAR archives without limitations free of charge, but cannot be
|
||||||
|
used to develop RAR (WinRAR) compatible archiver and to
|
||||||
|
re-create RAR compression algorithm, which is proprietary.
|
||||||
|
Distribution of modified UnRAR source code in separate form
|
||||||
|
or as a part of other software is permitted, provided that
|
||||||
|
full text of this paragraph, starting from "UnRAR source code"
|
||||||
|
words, is included in license, or in documentation if license
|
||||||
|
is not available, and in source code comments of resulting package.
|
||||||
|
|
||||||
|
3. The UnRAR utility may be freely distributed. It is allowed
|
||||||
|
to distribute UnRAR inside of other software packages.
|
||||||
|
|
||||||
|
4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||||
|
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
||||||
|
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
||||||
|
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
||||||
|
OR MISUSING THIS SOFTWARE.
|
||||||
|
|
||||||
|
5. Installing and using the UnRAR utility signifies acceptance of
|
||||||
|
these terms and conditions of the license.
|
||||||
|
|
||||||
|
6. If you don't agree with terms of the license you must remove
|
||||||
|
UnRAR files from your storage devices and cease to use the
|
||||||
|
utility.
|
||||||
|
|
||||||
|
Thank you for your interest in RAR and UnRAR.
|
||||||
|
|
||||||
|
|
||||||
|
Alexander L. Roshal
|
474
deps/unrar/list.cpp
vendored
Normal file
474
deps/unrar/list.cpp
vendored
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
static void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare);
|
||||||
|
static void ListSymLink(Archive &Arc);
|
||||||
|
static void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize);
|
||||||
|
static void ListOldSubHeader(Archive &Arc);
|
||||||
|
static void ListNewSubHeader(CommandData *Cmd,Archive &Arc);
|
||||||
|
|
||||||
|
void ListArchive(CommandData *Cmd)
|
||||||
|
{
|
||||||
|
int64 SumPackSize=0,SumUnpSize=0;
|
||||||
|
uint ArcCount=0,SumFileCount=0;
|
||||||
|
bool Technical=(Cmd->Command[1]=='T');
|
||||||
|
bool ShowService=Technical && Cmd->Command[2]=='A';
|
||||||
|
bool Bare=(Cmd->Command[1]=='B');
|
||||||
|
bool Verbose=(Cmd->Command[0]=='V');
|
||||||
|
|
||||||
|
wchar ArcName[NM];
|
||||||
|
while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
|
||||||
|
{
|
||||||
|
if (Cmd->ManualPassword)
|
||||||
|
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
||||||
|
|
||||||
|
Archive Arc(Cmd);
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
Arc.RemoveSequentialFlag();
|
||||||
|
#endif
|
||||||
|
if (!Arc.WOpen(ArcName))
|
||||||
|
continue;
|
||||||
|
bool FileMatched=true;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int64 TotalPackSize=0,TotalUnpSize=0;
|
||||||
|
uint FileCount=0;
|
||||||
|
if (Arc.IsArchive(true))
|
||||||
|
{
|
||||||
|
bool TitleShown=false;
|
||||||
|
if (!Bare)
|
||||||
|
{
|
||||||
|
Arc.ViewComment();
|
||||||
|
mprintf(L"\n%s: %s",St(MListArchive),Arc.FileName);
|
||||||
|
mprintf(L"\n%s: ",St(MListDetails));
|
||||||
|
uint SetCount=0;
|
||||||
|
const wchar *Fmt=Arc.Format==RARFMT14 ? L"RAR 1.4":(Arc.Format==RARFMT15 ? L"RAR 4":L"RAR 5");
|
||||||
|
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", Fmt);
|
||||||
|
if (Arc.Solid)
|
||||||
|
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSolid));
|
||||||
|
if (Arc.SFXSize>0)
|
||||||
|
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSFX));
|
||||||
|
if (Arc.Volume)
|
||||||
|
if (Arc.Format==RARFMT50)
|
||||||
|
{
|
||||||
|
// RAR 5.0 archives store the volume number in main header,
|
||||||
|
// so it is already available now.
|
||||||
|
if (SetCount++ > 0)
|
||||||
|
mprintf(L", ");
|
||||||
|
mprintf(St(MVolumeNumber),Arc.VolNumber+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListVolume));
|
||||||
|
if (Arc.Protected)
|
||||||
|
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListRR));
|
||||||
|
if (Arc.Locked)
|
||||||
|
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListLock));
|
||||||
|
if (Arc.Encrypted)
|
||||||
|
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListEncHead));
|
||||||
|
mprintf(L"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar VolNumText[50];
|
||||||
|
*VolNumText=0;
|
||||||
|
while(Arc.ReadHeader()>0)
|
||||||
|
{
|
||||||
|
Wait(); // Allow quit listing with Ctrl+C.
|
||||||
|
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||||
|
if (HeaderType==HEAD_ENDARC)
|
||||||
|
{
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
// Only RAR 1.5 archives store the volume number in end record.
|
||||||
|
if (Arc.EndArcHead.StoreVolNumber && Arc.Format==RARFMT15)
|
||||||
|
swprintf(VolNumText,ASIZE(VolNumText),L"%.10ls %u",St(MListVolume),Arc.VolNumber+1);
|
||||||
|
#endif
|
||||||
|
if (Technical && ShowService)
|
||||||
|
{
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListService),L"EOF");
|
||||||
|
if (*VolNumText!=0)
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListFlags),VolNumText);
|
||||||
|
mprintf(L"\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch(HeaderType)
|
||||||
|
{
|
||||||
|
case HEAD_FILE:
|
||||||
|
FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0;
|
||||||
|
if (FileMatched)
|
||||||
|
{
|
||||||
|
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
|
||||||
|
if (!Arc.FileHead.SplitBefore)
|
||||||
|
{
|
||||||
|
TotalUnpSize+=Arc.FileHead.UnpSize;
|
||||||
|
FileCount++;
|
||||||
|
}
|
||||||
|
TotalPackSize+=Arc.FileHead.PackSize;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HEAD_SERVICE:
|
||||||
|
if (FileMatched && !Bare)
|
||||||
|
{
|
||||||
|
if (Technical && ShowService)
|
||||||
|
ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Arc.SeekToNext();
|
||||||
|
}
|
||||||
|
if (!Bare && !Technical)
|
||||||
|
if (TitleShown)
|
||||||
|
{
|
||||||
|
wchar UnpSizeText[20];
|
||||||
|
itoa(TotalUnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||||
|
|
||||||
|
wchar PackSizeText[20];
|
||||||
|
itoa(TotalPackSize,PackSizeText,ASIZE(PackSizeText));
|
||||||
|
|
||||||
|
if (Verbose)
|
||||||
|
{
|
||||||
|
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
|
||||||
|
mprintf(L"\n%21ls %9ls %3d%% %-27ls %u",UnpSizeText,
|
||||||
|
PackSizeText,ToPercentUnlim(TotalPackSize,TotalUnpSize),
|
||||||
|
VolNumText,FileCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mprintf(L"\n----------- --------- ---------- ----- ----");
|
||||||
|
mprintf(L"\n%21ls %-16ls %u",UnpSizeText,VolNumText,FileCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
SumFileCount+=FileCount;
|
||||||
|
SumUnpSize+=TotalUnpSize;
|
||||||
|
SumPackSize+=TotalPackSize;
|
||||||
|
mprintf(L"\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mprintf(St(MListNoFiles));
|
||||||
|
|
||||||
|
ArcCount++;
|
||||||
|
|
||||||
|
#ifndef NOVOLUME
|
||||||
|
if (Cmd->VolSize!=0 && (Arc.FileHead.SplitAfter ||
|
||||||
|
Arc.GetHeaderType()==HEAD_ENDARC && Arc.EndArcHead.NextVolume) &&
|
||||||
|
MergeArchive(Arc,NULL,false,Cmd->Command[0]))
|
||||||
|
Arc.Seek(0,SEEK_SET);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Cmd->ArcNames.ItemsCount()<2 && !Bare)
|
||||||
|
mprintf(St(MNotRAR),Arc.FileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean user entered password. Not really required, just for extra safety.
|
||||||
|
if (Cmd->ManualPassword)
|
||||||
|
Cmd->Password.Clean();
|
||||||
|
|
||||||
|
if (ArcCount>1 && !Bare && !Technical)
|
||||||
|
{
|
||||||
|
wchar UnpSizeText[20],PackSizeText[20];
|
||||||
|
itoa(SumUnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||||
|
itoa(SumPackSize,PackSizeText,ASIZE(PackSizeText));
|
||||||
|
|
||||||
|
if (Verbose)
|
||||||
|
mprintf(L"%21ls %9ls %3d%% %28ls %u",UnpSizeText,PackSizeText,
|
||||||
|
ToPercentUnlim(SumPackSize,SumUnpSize),L"",SumFileCount);
|
||||||
|
else
|
||||||
|
mprintf(L"%21ls %18s %lu",UnpSizeText,L"",SumFileCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum LISTCOL_TYPE {
|
||||||
|
LCOL_NAME,LCOL_ATTR,LCOL_SIZE,LCOL_PACKED,LCOL_RATIO,LCOL_CSUM,LCOL_ENCR
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare)
|
||||||
|
{
|
||||||
|
wchar *Name=hd.FileName;
|
||||||
|
RARFORMAT Format=Arc.Format;
|
||||||
|
|
||||||
|
if (Bare)
|
||||||
|
{
|
||||||
|
mprintf(L"%s\n",Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TitleShown && !Technical)
|
||||||
|
{
|
||||||
|
if (Verbose)
|
||||||
|
{
|
||||||
|
mprintf(L"\n%ls",St(MListTitleV));
|
||||||
|
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mprintf(L"\n%ls",St(MListTitleL));
|
||||||
|
mprintf(L"\n----------- --------- ---------- ----- ----");
|
||||||
|
}
|
||||||
|
TitleShown=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar UnpSizeText[30],PackSizeText[30];
|
||||||
|
if (hd.UnpSize==INT64NDF)
|
||||||
|
wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText));
|
||||||
|
else
|
||||||
|
itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||||
|
itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));
|
||||||
|
|
||||||
|
wchar AttrStr[30];
|
||||||
|
if (hd.HeaderType==HEAD_SERVICE)
|
||||||
|
swprintf(AttrStr,ASIZE(AttrStr),L"%cB",hd.Inherited ? 'I' : '.');
|
||||||
|
else
|
||||||
|
ListFileAttr(hd.FileAttr,hd.HSType,AttrStr,ASIZE(AttrStr));
|
||||||
|
|
||||||
|
wchar RatioStr[10];
|
||||||
|
|
||||||
|
if (hd.SplitBefore && hd.SplitAfter)
|
||||||
|
wcsncpyz(RatioStr,L"<->",ASIZE(RatioStr));
|
||||||
|
else
|
||||||
|
if (hd.SplitBefore)
|
||||||
|
wcsncpyz(RatioStr,L"<--",ASIZE(RatioStr));
|
||||||
|
else
|
||||||
|
if (hd.SplitAfter)
|
||||||
|
wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr));
|
||||||
|
else
|
||||||
|
swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));
|
||||||
|
|
||||||
|
wchar DateStr[50];
|
||||||
|
hd.mtime.GetText(DateStr,ASIZE(DateStr),Technical);
|
||||||
|
|
||||||
|
if (Technical)
|
||||||
|
{
|
||||||
|
mprintf(L"\n%12s: %s",St(MListName),Name);
|
||||||
|
|
||||||
|
bool FileBlock=hd.HeaderType==HEAD_FILE;
|
||||||
|
|
||||||
|
if (!FileBlock && Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
|
||||||
|
{
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListType),St(MListStream));
|
||||||
|
wchar StreamName[NM];
|
||||||
|
GetStreamNameNTFS(Arc,StreamName,ASIZE(StreamName));
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListTarget),StreamName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const wchar *Type=St(FileBlock ? (hd.Dir ? MListDir:MListFile):MListService);
|
||||||
|
|
||||||
|
if (hd.RedirType!=FSREDIR_NONE)
|
||||||
|
switch(hd.RedirType)
|
||||||
|
{
|
||||||
|
case FSREDIR_UNIXSYMLINK:
|
||||||
|
Type=St(MListUSymlink); break;
|
||||||
|
case FSREDIR_WINSYMLINK:
|
||||||
|
Type=St(MListWSymlink); break;
|
||||||
|
case FSREDIR_JUNCTION:
|
||||||
|
Type=St(MListJunction); break;
|
||||||
|
case FSREDIR_HARDLINK:
|
||||||
|
Type=St(MListHardlink); break;
|
||||||
|
case FSREDIR_FILECOPY:
|
||||||
|
Type=St(MListCopy); break;
|
||||||
|
}
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListType),Type);
|
||||||
|
if (hd.RedirType!=FSREDIR_NONE)
|
||||||
|
if (Format==RARFMT15)
|
||||||
|
{
|
||||||
|
char LinkTargetA[NM];
|
||||||
|
if (Arc.FileHead.Encrypted)
|
||||||
|
{
|
||||||
|
// Link data are encrypted. We would need to ask for password
|
||||||
|
// and initialize decryption routine to display the link target.
|
||||||
|
strncpyz(LinkTargetA,"*<-?->",ASIZE(LinkTargetA));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int DataSize=(int)Min(hd.PackSize,ASIZE(LinkTargetA)-1);
|
||||||
|
Arc.Read(LinkTargetA,DataSize);
|
||||||
|
LinkTargetA[DataSize > 0 ? DataSize : 0] = 0;
|
||||||
|
}
|
||||||
|
wchar LinkTarget[NM];
|
||||||
|
CharToWide(LinkTargetA,LinkTarget,ASIZE(LinkTarget));
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListTarget),LinkTarget);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListTarget),hd.RedirName);
|
||||||
|
}
|
||||||
|
if (!hd.Dir)
|
||||||
|
{
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListSize),UnpSizeText);
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListPacked),PackSizeText);
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListRatio),RatioStr);
|
||||||
|
}
|
||||||
|
if (hd.mtime.IsSet())
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListMtime),DateStr);
|
||||||
|
if (hd.ctime.IsSet())
|
||||||
|
{
|
||||||
|
hd.ctime.GetText(DateStr,ASIZE(DateStr),true);
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListCtime),DateStr);
|
||||||
|
}
|
||||||
|
if (hd.atime.IsSet())
|
||||||
|
{
|
||||||
|
hd.atime.GetText(DateStr,ASIZE(DateStr),true);
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListAtime),DateStr);
|
||||||
|
}
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListAttr),AttrStr);
|
||||||
|
if (hd.FileHash.Type==HASH_CRC32)
|
||||||
|
mprintf(L"\n%12ls: %8.8X",
|
||||||
|
hd.UseHashKey ? L"CRC32 MAC":hd.SplitAfter ? L"Pack-CRC32":L"CRC32",
|
||||||
|
hd.FileHash.CRC32);
|
||||||
|
if (hd.FileHash.Type==HASH_BLAKE2)
|
||||||
|
{
|
||||||
|
wchar BlakeStr[BLAKE2_DIGEST_SIZE*2+1];
|
||||||
|
BinToHex(hd.FileHash.Digest,BLAKE2_DIGEST_SIZE,NULL,BlakeStr,ASIZE(BlakeStr));
|
||||||
|
mprintf(L"\n%12ls: %ls",
|
||||||
|
hd.UseHashKey ? L"BLAKE2 MAC":hd.SplitAfter ? L"Pack-BLAKE2":L"BLAKE2",
|
||||||
|
BlakeStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar *HostOS=L"";
|
||||||
|
if (Format==RARFMT50 && hd.HSType!=HSYS_UNKNOWN)
|
||||||
|
HostOS=hd.HSType==HSYS_WINDOWS ? L"Windows":L"Unix";
|
||||||
|
if (Format==RARFMT15)
|
||||||
|
{
|
||||||
|
static const wchar *RarOS[]={
|
||||||
|
L"DOS",L"OS/2",L"Windows",L"Unix",L"Mac OS",L"BeOS",L"WinCE",L"",L"",L""
|
||||||
|
};
|
||||||
|
if (hd.HostOS<ASIZE(RarOS))
|
||||||
|
HostOS=RarOS[hd.HostOS];
|
||||||
|
}
|
||||||
|
if (*HostOS!=0)
|
||||||
|
mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS);
|
||||||
|
|
||||||
|
mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo),
|
||||||
|
Format==RARFMT15 ? L"1.5":L"5.0",
|
||||||
|
hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method,
|
||||||
|
hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400,
|
||||||
|
hd.WinSize>=0x100000 ? L"M":L"K");
|
||||||
|
|
||||||
|
if (hd.Solid || hd.Encrypted)
|
||||||
|
{
|
||||||
|
mprintf(L"\n%12ls: ",St(MListFlags));
|
||||||
|
if (hd.Solid)
|
||||||
|
mprintf(L"%ls ",St(MListSolid));
|
||||||
|
if (hd.Encrypted)
|
||||||
|
mprintf(L"%ls ",St(MListEnc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hd.Version)
|
||||||
|
{
|
||||||
|
uint Version=ParseVersionFileName(Name,false);
|
||||||
|
if (Version!=0)
|
||||||
|
mprintf(L"\n%12ls: %u",St(MListFileVer),Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hd.UnixOwnerSet)
|
||||||
|
{
|
||||||
|
mprintf(L"\n%12ls: ",L"Unix owner");
|
||||||
|
if (*hd.UnixOwnerName!=0)
|
||||||
|
mprintf(L"%ls:",GetWide(hd.UnixOwnerName));
|
||||||
|
if (*hd.UnixGroupName!=0)
|
||||||
|
mprintf(L"%ls",GetWide(hd.UnixGroupName));
|
||||||
|
if ((*hd.UnixOwnerName!=0 || *hd.UnixGroupName!=0) && (hd.UnixOwnerNumeric || hd.UnixGroupNumeric))
|
||||||
|
mprintf(L" ");
|
||||||
|
if (hd.UnixOwnerNumeric)
|
||||||
|
mprintf(L"#%d:",hd.UnixOwnerID);
|
||||||
|
if (hd.UnixGroupNumeric)
|
||||||
|
mprintf(L"#%d:",hd.UnixGroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
mprintf(L"\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mprintf(L"\n%c%10ls %9ls ",hd.Encrypted ? '*' : ' ',AttrStr,UnpSizeText);
|
||||||
|
|
||||||
|
if (Verbose)
|
||||||
|
mprintf(L"%9ls %4ls ",PackSizeText,RatioStr);
|
||||||
|
|
||||||
|
mprintf(L" %ls ",DateStr);
|
||||||
|
|
||||||
|
if (Verbose)
|
||||||
|
{
|
||||||
|
if (hd.FileHash.Type==HASH_CRC32)
|
||||||
|
mprintf(L"%8.8X ",hd.FileHash.CRC32);
|
||||||
|
else
|
||||||
|
if (hd.FileHash.Type==HASH_BLAKE2)
|
||||||
|
{
|
||||||
|
byte *S=hd.FileHash.Digest;
|
||||||
|
mprintf(L"%02x%02x..%02x ",S[0],S[1],S[31]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mprintf(L"???????? ");
|
||||||
|
}
|
||||||
|
mprintf(L"%ls",Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void ListSymLink(Archive &Arc)
|
||||||
|
{
|
||||||
|
if (Arc.FileHead.HSType==HSYS_UNIX && (Arc.FileHead.FileAttr & 0xF000)==0xA000)
|
||||||
|
if (Arc.FileHead.Encrypted)
|
||||||
|
{
|
||||||
|
// Link data are encrypted. We would need to ask for password
|
||||||
|
// and initialize decryption routine to display the link target.
|
||||||
|
mprintf(L"\n%22ls %ls",L"-->",L"*<-?->");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char FileName[NM];
|
||||||
|
uint DataSize=(uint)Min(Arc.FileHead.PackSize,sizeof(FileName)-1);
|
||||||
|
Arc.Read(FileName,DataSize);
|
||||||
|
FileName[DataSize]=0;
|
||||||
|
mprintf(L"\n%22ls %ls",L"-->",GetWide(FileName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize)
|
||||||
|
{
|
||||||
|
switch(HostType)
|
||||||
|
{
|
||||||
|
case HSYS_WINDOWS:
|
||||||
|
swprintf(AttrStr,AttrSize,L"%c%c%c%c%c%c%c",
|
||||||
|
(A & 0x2000)!=0 ? 'I' : '.', // Not content indexed.
|
||||||
|
(A & 0x0800)!=0 ? 'C' : '.', // Compressed.
|
||||||
|
(A & 0x0020)!=0 ? 'A' : '.', // Archive.
|
||||||
|
(A & 0x0010)!=0 ? 'D' : '.', // Directory.
|
||||||
|
(A & 0x0004)!=0 ? 'S' : '.', // System.
|
||||||
|
(A & 0x0002)!=0 ? 'H' : '.', // Hidden.
|
||||||
|
(A & 0x0001)!=0 ? 'R' : '.'); // Read-only.
|
||||||
|
break;
|
||||||
|
case HSYS_UNIX:
|
||||||
|
switch (A & 0xF000)
|
||||||
|
{
|
||||||
|
case 0x4000:
|
||||||
|
AttrStr[0]='d';
|
||||||
|
break;
|
||||||
|
case 0xA000:
|
||||||
|
AttrStr[0]='l';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
AttrStr[0]='-';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
swprintf(AttrStr+1,AttrSize-1,L"%c%c%c%c%c%c%c%c%c",
|
||||||
|
(A & 0x0100) ? 'r' : '-',
|
||||||
|
(A & 0x0080) ? 'w' : '-',
|
||||||
|
(A & 0x0040) ? ((A & 0x0800)!=0 ? 's':'x'):((A & 0x0800)!=0 ? 'S':'-'),
|
||||||
|
(A & 0x0020) ? 'r' : '-',
|
||||||
|
(A & 0x0010) ? 'w' : '-',
|
||||||
|
(A & 0x0008) ? ((A & 0x0400)!=0 ? 's':'x'):((A & 0x0400)!=0 ? 'S':'-'),
|
||||||
|
(A & 0x0004) ? 'r' : '-',
|
||||||
|
(A & 0x0002) ? 'w' : '-',
|
||||||
|
(A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-');
|
||||||
|
break;
|
||||||
|
case HSYS_UNKNOWN:
|
||||||
|
wcsncpyz(AttrStr,L"?",AttrSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
6
deps/unrar/list.hpp
vendored
Normal file
6
deps/unrar/list.hpp
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _RAR_LIST_
|
||||||
|
#define _RAR_LIST_
|
||||||
|
|
||||||
|
void ListArchive(CommandData *Cmd);
|
||||||
|
|
||||||
|
#endif
|
382
deps/unrar/loclang.hpp
vendored
Normal file
382
deps/unrar/loclang.hpp
vendored
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
#define MYesNo L"_Yes_No"
|
||||||
|
#define MYesNoAll L"_Yes_No_All"
|
||||||
|
#define MYesNoAllQ L"_Yes_No_All_nEver_Quit"
|
||||||
|
#define MYesNoAllRenQ L"_Yes_No_All_nEver_Rename_Quit"
|
||||||
|
#define MContinueQuit L"_Continue_Quit"
|
||||||
|
#define MRetryAbort L"_Retry_Abort"
|
||||||
|
#define MCopyright L"\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d"
|
||||||
|
#define MRegTo L"\nRegistered to %s\n"
|
||||||
|
#define MShare L"\nTrial version Type 'rar -?' for help\n"
|
||||||
|
#define MRegKeyWarning L"\nAvailable license key is valid only for %s\n"
|
||||||
|
#define MUCopyright L"\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
|
||||||
|
#define MBeta L"beta"
|
||||||
|
#define Mx86 L"x86"
|
||||||
|
#define Mx64 L"x64"
|
||||||
|
#define MMonthJan L"Jan"
|
||||||
|
#define MMonthFeb L"Feb"
|
||||||
|
#define MMonthMar L"Mar"
|
||||||
|
#define MMonthApr L"Apr"
|
||||||
|
#define MMonthMay L"May"
|
||||||
|
#define MMonthJun L"Jun"
|
||||||
|
#define MMonthJul L"Jul"
|
||||||
|
#define MMonthAug L"Aug"
|
||||||
|
#define MMonthSep L"Sep"
|
||||||
|
#define MMonthOct L"Oct"
|
||||||
|
#define MMonthNov L"Nov"
|
||||||
|
#define MMonthDec L"Dec"
|
||||||
|
#define MRARTitle1 L"\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||||
|
#define MUNRARTitle1 L"\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||||
|
#define MRARTitle2 L"\n <@listfiles...> <path_to_extract\\>"
|
||||||
|
#define MCHelpCmd L"\n\n<Commands>"
|
||||||
|
#define MCHelpCmdA L"\n a Add files to archive"
|
||||||
|
#define MCHelpCmdC L"\n c Add archive comment"
|
||||||
|
#define MCHelpCmdCH L"\n ch Change archive parameters"
|
||||||
|
#define MCHelpCmdCW L"\n cw Write archive comment to file"
|
||||||
|
#define MCHelpCmdD L"\n d Delete files from archive"
|
||||||
|
#define MCHelpCmdE L"\n e Extract files without archived paths"
|
||||||
|
#define MCHelpCmdF L"\n f Freshen files in archive"
|
||||||
|
#define MCHelpCmdI L"\n i[par]=<str> Find string in archives"
|
||||||
|
#define MCHelpCmdK L"\n k Lock archive"
|
||||||
|
#define MCHelpCmdL L"\n l[t[a],b] List archive contents [technical[all], bare]"
|
||||||
|
#define MCHelpCmdM L"\n m[f] Move to archive [files only]"
|
||||||
|
#define MCHelpCmdP L"\n p Print file to stdout"
|
||||||
|
#define MCHelpCmdR L"\n r Repair archive"
|
||||||
|
#define MCHelpCmdRC L"\n rc Reconstruct missing volumes"
|
||||||
|
#define MCHelpCmdRN L"\n rn Rename archived files"
|
||||||
|
#define MCHelpCmdRR L"\n rr[N] Add data recovery record"
|
||||||
|
#define MCHelpCmdRV L"\n rv[N] Create recovery volumes"
|
||||||
|
#define MCHelpCmdS L"\n s[name|-] Convert archive to or from SFX"
|
||||||
|
#define MCHelpCmdT L"\n t Test archive files"
|
||||||
|
#define MCHelpCmdU L"\n u Update files in archive"
|
||||||
|
#define MCHelpCmdV L"\n v[t[a],b] Verbosely list archive contents [technical[all],bare]"
|
||||||
|
#define MCHelpCmdX L"\n x Extract files with full path"
|
||||||
|
#define MCHelpSw L"\n\n<Switches>"
|
||||||
|
#define MCHelpSwm L"\n - Stop switches scanning"
|
||||||
|
#define MCHelpSwAT L"\n @[+] Disable [enable] file lists"
|
||||||
|
#define MCHelpSwAC L"\n ac Clear Archive attribute after compression or extraction"
|
||||||
|
#define MCHelpSwAD L"\n ad Append archive name to destination path"
|
||||||
|
#define MCHelpSwAG L"\n ag[format] Generate archive name using the current date"
|
||||||
|
#define MCHelpSwAI L"\n ai Ignore file attributes"
|
||||||
|
#define MCHelpSwAO L"\n ao Add files with Archive attribute set"
|
||||||
|
#define MCHelpSwAP L"\n ap<path> Set path inside archive"
|
||||||
|
#define MCHelpSwAS L"\n as Synchronize archive contents"
|
||||||
|
#define MCHelpSwCm L"\n c- Disable comments show"
|
||||||
|
#define MCHelpSwCFGm L"\n cfg- Disable read configuration"
|
||||||
|
#define MCHelpSwCL L"\n cl Convert names to lower case"
|
||||||
|
#define MCHelpSwCU L"\n cu Convert names to upper case"
|
||||||
|
#define MCHelpSwDF L"\n df Delete files after archiving"
|
||||||
|
#define MCHelpSwDH L"\n dh Open shared files"
|
||||||
|
#define MCHelpSwDR L"\n dr Delete files to Recycle Bin"
|
||||||
|
#define MCHelpSwDS L"\n ds Disable name sort for solid archive"
|
||||||
|
#define MCHelpSwDW L"\n dw Wipe files after archiving"
|
||||||
|
#define MCHelpSwEa L"\n e[+]<attr> Set file exclude and include attributes"
|
||||||
|
#define MCHelpSwED L"\n ed Do not add empty directories"
|
||||||
|
#define MCHelpSwEN L"\n en Do not put 'end of archive' block"
|
||||||
|
#define MCHelpSwEP L"\n ep Exclude paths from names"
|
||||||
|
#define MCHelpSwEP1 L"\n ep1 Exclude base directory from names"
|
||||||
|
#define MCHelpSwEP2 L"\n ep2 Expand paths to full"
|
||||||
|
#define MCHelpSwEP3 L"\n ep3 Expand paths to full including the drive letter"
|
||||||
|
#define MCHelpSwF L"\n f Freshen files"
|
||||||
|
#define MCHelpSwHP L"\n hp[password] Encrypt both file data and headers"
|
||||||
|
#define MCHelpSwHT L"\n ht[b|c] Select hash type [BLAKE2,CRC32] for file checksum"
|
||||||
|
#define MCHelpSwIDP L"\n id[c,d,p,q] Disable messages"
|
||||||
|
#define MCHelpSwIEML L"\n ieml[addr] Send archive by email"
|
||||||
|
#define MCHelpSwIERR L"\n ierr Send all messages to stderr"
|
||||||
|
#define MCHelpSwILOG L"\n ilog[name] Log errors to file"
|
||||||
|
#define MCHelpSwINUL L"\n inul Disable all messages"
|
||||||
|
#define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation"
|
||||||
|
#define MCHelpSwISND L"\n isnd[-] Control notification sounds"
|
||||||
|
#define MCHelpSwIVER L"\n iver Display the version number"
|
||||||
|
#define MCHelpSwK L"\n k Lock archive"
|
||||||
|
#define MCHelpSwKB L"\n kb Keep broken extracted files"
|
||||||
|
#define MCHelpSwLog L"\n log[f][=name] Write names to log file"
|
||||||
|
#define MCHelpSwMn L"\n m<0..5> Set compression level (0-store...3-default...5-maximal)"
|
||||||
|
#define MCHelpSwMA L"\n ma[4|5] Specify a version of archiving format"
|
||||||
|
#define MCHelpSwMC L"\n mc<par> Set advanced compression parameters"
|
||||||
|
#define MCHelpSwMD L"\n md<n>[k,m,g] Dictionary size in KB, MB or GB"
|
||||||
|
#define MCHelpSwMS L"\n ms[ext;ext] Specify file types to store"
|
||||||
|
#define MCHelpSwMT L"\n mt<threads> Set the number of threads"
|
||||||
|
#define MCHelpSwN L"\n n<file> Additionally filter included files"
|
||||||
|
#define MCHelpSwNa L"\n n@ Read additional filter masks from stdin"
|
||||||
|
#define MCHelpSwNal L"\n n@<list> Read additional filter masks from list file"
|
||||||
|
#define MCHelpSwO L"\n o[+|-] Set the overwrite mode"
|
||||||
|
#define MCHelpSwOC L"\n oc Set NTFS Compressed attribute"
|
||||||
|
#define MCHelpSwOH L"\n oh Save hard links as the link instead of the file"
|
||||||
|
#define MCHelpSwOI L"\n oi[0-4][:min] Save identical files as references"
|
||||||
|
#define MCHelpSwOL L"\n ol[a] Process symbolic links as the link [absolute paths]"
|
||||||
|
#define MCHelpSwONI L"\n oni Allow potentially incompatible names"
|
||||||
|
#define MCHelpSwOR L"\n or Rename files automatically"
|
||||||
|
#define MCHelpSwOS L"\n os Save NTFS streams"
|
||||||
|
#define MCHelpSwOW L"\n ow Save or restore file owner and group"
|
||||||
|
#define MCHelpSwP L"\n p[password] Set password"
|
||||||
|
#define MCHelpSwPm L"\n p- Do not query password"
|
||||||
|
#define MCHelpSwQO L"\n qo[-|+] Add quick open information [none|force]"
|
||||||
|
#define MCHelpSwR L"\n r Recurse subdirectories"
|
||||||
|
#define MCHelpSwRm L"\n r- Disable recursion"
|
||||||
|
#define MCHelpSwR0 L"\n r0 Recurse subdirectories for wildcard names only"
|
||||||
|
#define MCHelpSwRI L"\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms"
|
||||||
|
#define MCHelpSwRR L"\n rr[N] Add data recovery record"
|
||||||
|
#define MCHelpSwRV L"\n rv[N] Create recovery volumes"
|
||||||
|
#define MCHelpSwS L"\n s[<N>,v[-],e] Create solid archive"
|
||||||
|
#define MCHelpSwSm L"\n s- Disable solid archiving"
|
||||||
|
#define MCHelpSwSC L"\n sc<chr>[obj] Specify the character set"
|
||||||
|
#define MCHelpSwSFX L"\n sfx[name] Create SFX archive"
|
||||||
|
#define MCHelpSwSI L"\n si[name] Read data from standard input (stdin)"
|
||||||
|
#define MCHelpSwSL L"\n sl<size> Process files with size less than specified"
|
||||||
|
#define MCHelpSwSM L"\n sm<size> Process files with size more than specified"
|
||||||
|
#define MCHelpSwT L"\n t Test files after archiving"
|
||||||
|
#define MCHelpSwTK L"\n tk Keep original archive time"
|
||||||
|
#define MCHelpSwTL L"\n tl Set archive time to latest file"
|
||||||
|
#define MCHelpSwTN L"\n tn[mcao]<t> Process files newer than <t> time"
|
||||||
|
#define MCHelpSwTO L"\n to[mcao]<t> Process files older than <t> time"
|
||||||
|
#define MCHelpSwTA L"\n ta[mcao]<d> Process files modified after <d> YYYYMMDDHHMMSS date"
|
||||||
|
#define MCHelpSwTB L"\n tb[mcao]<d> Process files modified before <d> YYYYMMDDHHMMSS date"
|
||||||
|
#define MCHelpSwTS L"\n ts[m,c,a,p] Save or restore time (modification, creation, access, preserve)"
|
||||||
|
#define MCHelpSwU L"\n u Update files"
|
||||||
|
#define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes"
|
||||||
|
#define MCHelpSwVUnr L"\n v List all volumes"
|
||||||
|
#define MCHelpSwVn L"\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]"
|
||||||
|
#define MCHelpSwVD L"\n vd Erase disk contents before creating volume"
|
||||||
|
#define MCHelpSwVER L"\n ver[n] File version control"
|
||||||
|
#define MCHelpSwVN L"\n vn Use the old style volume naming scheme"
|
||||||
|
#define MCHelpSwVP L"\n vp Pause before each volume"
|
||||||
|
#define MCHelpSwW L"\n w<path> Assign work directory"
|
||||||
|
#define MCHelpSwX L"\n x<file> Exclude specified file"
|
||||||
|
#define MCHelpSwXa L"\n x@ Read file names to exclude from stdin"
|
||||||
|
#define MCHelpSwXal L"\n x@<list> Exclude files listed in specified list file"
|
||||||
|
#define MCHelpSwY L"\n y Assume Yes on all queries"
|
||||||
|
#define MCHelpSwZ L"\n z[file] Read archive comment from file"
|
||||||
|
#define MBadArc L"\nERROR: Bad archive %s\n"
|
||||||
|
#define MAskPsw L"Enter password (will not be echoed)"
|
||||||
|
#define MAskPswFor L"\nEnter password (will not be echoed) for %s: "
|
||||||
|
#define MReAskPsw L"\nReenter password: "
|
||||||
|
#define MNotMatchPsw L"\nERROR: Passwords do not match\n"
|
||||||
|
#define MErrWrite L"Write error in the file %s"
|
||||||
|
#define MErrRead L"Read error in the file %s"
|
||||||
|
#define MErrSeek L"Seek error in the file %s"
|
||||||
|
#define MErrFClose L"Cannot close the file %s"
|
||||||
|
#define MErrOutMem L"Not enough memory"
|
||||||
|
#define MErrBrokenArc L"Corrupt archive - use 'Repair' command"
|
||||||
|
#define MProgAborted L"Program aborted"
|
||||||
|
#define MErrRename L"\nCannot rename %s to %s"
|
||||||
|
#define MAbsNextVol L"\nCannot find volume %s"
|
||||||
|
#define MBreak L"\nUser break\n"
|
||||||
|
#define MAskCreatVol L"\nCreate next volume ?"
|
||||||
|
#define MAskNextDisk L"\nDisk full. Insert next"
|
||||||
|
#define MCreatVol L"\n\nCreating %sarchive %s\n"
|
||||||
|
#define MAskNextVol L"\nInsert disk with %s"
|
||||||
|
#define MTestVol L"\n\nTesting archive %s\n"
|
||||||
|
#define MExtrVol L"\n\nExtracting from %s\n"
|
||||||
|
#define MConverting L"\nConverting %s"
|
||||||
|
#define MCvtToSFX L"\nConvert archives to SFX"
|
||||||
|
#define MCvtFromSFX L"\nRemoving SFX module"
|
||||||
|
#define MNotSFX L"\n%s is not SFX archive"
|
||||||
|
#define MNotRAR L"\n%s is not RAR archive"
|
||||||
|
#define MNotFirstVol L"\n%s is not the first volume"
|
||||||
|
#define MCvtOldFormat L"\n%s - cannot convert to SFX archive with old format"
|
||||||
|
#define MCannotCreate L"\nCannot create %s"
|
||||||
|
#define MCannotOpen L"\nCannot open %s"
|
||||||
|
#define MUnknownMeth L"\nUnknown method in %s"
|
||||||
|
#define MNewRarFormat L"\nUnsupported archive format. Please update RAR to a newer version."
|
||||||
|
#define MOk L" OK"
|
||||||
|
#define MDone L"\nDone"
|
||||||
|
#define MLockingArc L"\nLocking archive"
|
||||||
|
#define MNotMdfOld L"\n\nERROR: Cannot modify old format archive"
|
||||||
|
#define MNotMdfLock L"\n\nERROR: Locked archive"
|
||||||
|
#define MNotMdfVol L"\n\nERROR: Cannot modify volume"
|
||||||
|
#define MPackAskReg L"\nEvaluation copy. Please register.\n"
|
||||||
|
#define MCreateArchive L"\nCreating %sarchive %s\n"
|
||||||
|
#define MUpdateArchive L"\nUpdating %sarchive %s\n"
|
||||||
|
#define MAddSolid L"solid "
|
||||||
|
#define MAddFile L"\nAdding %-58s "
|
||||||
|
#define MUpdFile L"\nUpdating %-58s "
|
||||||
|
#define MAddPoints L"\n... %-58s "
|
||||||
|
#define MMoveDelFiles L"\n\nDeleting files %s..."
|
||||||
|
#define MMoveDelDirs L"and directories"
|
||||||
|
#define MMoveDelFile L"\nDeleting %-30s"
|
||||||
|
#define MMoveDeleted L" deleted"
|
||||||
|
#define MMoveNotDeleted L" NOT DELETED"
|
||||||
|
#define MClearAttrib L"\n\nClearing attributes..."
|
||||||
|
#define MMoveDelDir L"\nDeleting directory %-30s"
|
||||||
|
#define MWarErrFOpen L"\nWARNING: Cannot open %d %s"
|
||||||
|
#define MErrOpenFiles L"files"
|
||||||
|
#define MErrOpenFile L"file"
|
||||||
|
#define MAddNoFiles L"\nWARNING: No files"
|
||||||
|
#define MMdfEncrSol L"\n%s: encrypted"
|
||||||
|
#define MAddAnalyze L"\nAnalyzing archived files: "
|
||||||
|
#define MRepacking L"\nRepacking archived files: "
|
||||||
|
#define MCRCFailed L"\n%-20s - checksum error"
|
||||||
|
#define MExtrTest L"\n\nTesting archive %s\n"
|
||||||
|
#define MExtracting L"\n\nExtracting from %s\n"
|
||||||
|
#define MUseCurPsw L"\n%s - use current password ?"
|
||||||
|
#define MCreatDir L"\nCreating %-56s"
|
||||||
|
#define MExtrSkipFile L"\nSkipping %-56s"
|
||||||
|
#define MExtrTestFile L"\nTesting %-56s"
|
||||||
|
#define MExtrFile L"\nExtracting %-56s"
|
||||||
|
#define MExtrPoints L"\n... %-56s"
|
||||||
|
#define MExtrErrMkDir L"\nCannot create directory %s"
|
||||||
|
#define MExtrPrinting L"\n------ Printing %s\n\n"
|
||||||
|
#define MEncrBadCRC L"\nChecksum error in the encrypted file %s. Corrupt file or wrong password."
|
||||||
|
#define MExtrNoFiles L"\nNo files to extract"
|
||||||
|
#define MExtrAllOk L"\nAll OK"
|
||||||
|
#define MExtrTotalErr L"\nTotal errors: %ld"
|
||||||
|
#define MAskReplace L"\n\nWould you like to replace the existing file %s\n%6s bytes, modified on %s\nwith a new one\n%6s bytes, modified on %s\n"
|
||||||
|
#define MAskOverwrite L"\nOverwrite %s ?"
|
||||||
|
#define MAskNewName L"\nEnter new name: "
|
||||||
|
#define MHeaderBroken L"\nCorrupt header is found"
|
||||||
|
#define MMainHeaderBroken L"\nMain archive header is corrupt"
|
||||||
|
#define MLogFileHead L"\n%s - the file header is corrupt"
|
||||||
|
#define MLogProtectHead L"The data recovery header is corrupt"
|
||||||
|
#define MReadStdinCmt L"\nReading comment from stdin\n"
|
||||||
|
#define MReadCommFrom L"\nReading comment from %s"
|
||||||
|
#define MDelComment L"\nDeleting comment from %s"
|
||||||
|
#define MAddComment L"\nAdding comment to %s"
|
||||||
|
#define MFCommAdd L"\nAdding file comments"
|
||||||
|
#define MAskFComm L"\n\nReading comment for %s : %s from stdin\n"
|
||||||
|
#define MLogCommBrk L"\nThe archive comment is corrupt"
|
||||||
|
#define MCommAskCont L"\nPress 'Enter' to continue or 'Q' to quit:"
|
||||||
|
#define MWriteCommTo L"\nWrite comment to %s"
|
||||||
|
#define MCommNotPres L"\nComment is not present"
|
||||||
|
#define MDelFrom L"\nDeleting from %s"
|
||||||
|
#define MDeleting L"\nDeleting %s"
|
||||||
|
#define MEraseArc L"\nErasing empty archive %s"
|
||||||
|
#define MNoDelFiles L"\nNo files to delete"
|
||||||
|
#define MLogTitle L"-------- %2d %s %d, archive %s"
|
||||||
|
#define MPathTooLong L"\nERROR: Path too long\n"
|
||||||
|
#define MListArchive L"Archive"
|
||||||
|
#define MListDetails L"Details"
|
||||||
|
#define MListSolid L"solid"
|
||||||
|
#define MListSFX L"SFX"
|
||||||
|
#define MListVolume L"volume"
|
||||||
|
#define MListRR L"recovery record"
|
||||||
|
#define MListLock L"lock"
|
||||||
|
#define MListEnc L"encrypted"
|
||||||
|
#define MListEncHead L"encrypted headers"
|
||||||
|
#define MListTitleL L" Attributes Size Date Time Name"
|
||||||
|
#define MListTitleV L" Attributes Size Packed Ratio Date Time Checksum Name"
|
||||||
|
#define MListName L"Name"
|
||||||
|
#define MListType L"Type"
|
||||||
|
#define MListFile L"File"
|
||||||
|
#define MListDir L"Directory"
|
||||||
|
#define MListUSymlink L"Unix symbolic link"
|
||||||
|
#define MListWSymlink L"Windows symbolic link"
|
||||||
|
#define MListJunction L"NTFS junction point"
|
||||||
|
#define MListHardlink L"Hard link"
|
||||||
|
#define MListCopy L"File reference"
|
||||||
|
#define MListStream L"NTFS alternate data stream"
|
||||||
|
#define MListTarget L"Target"
|
||||||
|
#define MListSize L"Size"
|
||||||
|
#define MListPacked L"Packed size"
|
||||||
|
#define MListRatio L"Ratio"
|
||||||
|
#define MListMtime L"mtime"
|
||||||
|
#define MListCtime L"ctime"
|
||||||
|
#define MListAtime L"atime"
|
||||||
|
#define MListAttr L"Attributes"
|
||||||
|
#define MListFlags L"Flags"
|
||||||
|
#define MListCompInfo L"Compression"
|
||||||
|
#define MListHostOS L"Host OS"
|
||||||
|
#define MListFileVer L"File version"
|
||||||
|
#define MListService L"Service"
|
||||||
|
#define MListUOHead L"\n Unix Owner/Group data: %-14s %-14s"
|
||||||
|
#define MListNTACLHead L"\n NTFS security data"
|
||||||
|
#define MListStrmHead L"\n NTFS stream: %s"
|
||||||
|
#define MListUnkHead L"\n Unknown subheader type: 0x%04x"
|
||||||
|
#define MFileComment L"\nComment: "
|
||||||
|
#define MYes L"Yes"
|
||||||
|
#define MNo L"No"
|
||||||
|
#define MListNoFiles L" 0 files\n"
|
||||||
|
#define MRprReconstr L"\nReconstructing %s"
|
||||||
|
#define MRprBuild L"\nBuilding %s"
|
||||||
|
#define MRprOldFormat L"\nCannot repair archive with old format"
|
||||||
|
#define MRprFind L"\nFound %s"
|
||||||
|
#define MRprAskIsSol L"\nThe archive header is corrupt. Mark archive as solid ?"
|
||||||
|
#define MRprNoFiles L"\nNo files found"
|
||||||
|
#define MLogUnexpEOF L"\nUnexpected end of archive"
|
||||||
|
#define MRepAskReconst L"\nReconstruct archive structure ?"
|
||||||
|
#define MRRSearch L"\nSearching for recovery record"
|
||||||
|
#define MAnalyzeFileData L"\nAnalyzing file data"
|
||||||
|
#define MRecRNotFound L"\nData recovery record not found"
|
||||||
|
#define MRecRFound L"\nData recovery record found"
|
||||||
|
#define MRecSecDamage L"\nSector %ld (offsets %lX...%lX) damaged"
|
||||||
|
#define MRecCorrected L" - data recovered"
|
||||||
|
#define MRecFailed L" - cannot recover data"
|
||||||
|
#define MAddRecRec L"\nAdding data recovery record"
|
||||||
|
#define MEraseForVolume L"\n\nErasing contents of drive %c:\n"
|
||||||
|
#define MGetOwnersError L"\nWARNING: Cannot get %s owner and group\n"
|
||||||
|
#define MErrGetOwnerID L"\nWARNING: Cannot get owner %s ID\n"
|
||||||
|
#define MErrGetGroupID L"\nWARNING: Cannot get group %s ID\n"
|
||||||
|
#define MOwnersBroken L"\nERROR: %s group and owner data are corrupt\n"
|
||||||
|
#define MSetOwnersError L"\nWARNING: Cannot set %s owner and group\n"
|
||||||
|
#define MErrLnkRead L"\nWARNING: Cannot read symbolic link %s"
|
||||||
|
#define MSymLinkExists L"\nWARNING: Symbolic link %s already exists"
|
||||||
|
#define MAskRetryCreate L"\nCannot create %s. Retry ?"
|
||||||
|
#define MDataBadCRC L"\n%-20s : packed data checksum error in volume %s"
|
||||||
|
#define MFileRO L"\n%s is read-only"
|
||||||
|
#define MACLGetError L"\nWARNING: Cannot get %s security data\n"
|
||||||
|
#define MACLSetError L"\nWARNING: Cannot set %s security data\n"
|
||||||
|
#define MACLBroken L"\nERROR: %s security data are corrupt\n"
|
||||||
|
#define MACLUnknown L"\nWARNING: Unknown format of %s security data\n"
|
||||||
|
#define MStreamBroken L"\nERROR: %s stream data are corrupt\n"
|
||||||
|
#define MStreamUnknown L"\nWARNING: Unknown format of %s stream data\n"
|
||||||
|
#define MInvalidName L"\nERROR: Invalid file name %s"
|
||||||
|
#define MProcessArc L"\n\nProcessing archive %s"
|
||||||
|
#define MCorrectingName L"\nWARNING: Attempting to correct the invalid file name"
|
||||||
|
#define MUnpCannotMerge L"\nWARNING: You need to start extraction from a previous volume to unpack %s"
|
||||||
|
#define MUnknownOption L"\nERROR: Unknown option: %s"
|
||||||
|
#define MSubHeadCorrupt L"\nERROR: Corrupt data header found, ignored"
|
||||||
|
#define MSubHeadUnknown L"\nWARNING: Unknown data header format, ignored"
|
||||||
|
#define MSubHeadDataCRC L"\nERROR: Corrupt %s data block"
|
||||||
|
#define MSubHeadType L"\nData header type: %s"
|
||||||
|
#define MScanError L"\nCannot read contents of %s"
|
||||||
|
#define MNotVolume L"\n%s is not volume"
|
||||||
|
#define MRecVolDiffSets L"\nERROR: %s and %s belong to different sets"
|
||||||
|
#define MRecVolMissing L"\n%d volumes missing"
|
||||||
|
#define MRecVolFound L"\n%d recovery volumes found"
|
||||||
|
#define MRecVolAllExist L"\nNothing to reconstruct"
|
||||||
|
#define MRecVolCannotFix L"\nReconstruction impossible"
|
||||||
|
#define MReconstructing L"\nReconstructing..."
|
||||||
|
#define MCreating L"\nCreating %s"
|
||||||
|
#define MRenaming L"\nRenaming %s to %s"
|
||||||
|
#define MNTFSRequired L"\nWrite error: only NTFS file system supports files larger than 4 GB"
|
||||||
|
#define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files"
|
||||||
|
#define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s"
|
||||||
|
#define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives"
|
||||||
|
#define MHeadEncMismatch L"\nCannot change the header encryption mode in already encrypted archive"
|
||||||
|
#define MCannotEmail L"\nCannot email the file %s"
|
||||||
|
#define MCopyrightS L"\nRAR SFX archive"
|
||||||
|
#define MSHelpCmd L"\n\n<Commands>"
|
||||||
|
#define MSHelpCmdE L"\n -x Extract from archive (default)"
|
||||||
|
#define MSHelpCmdT L"\n -t Test archive files"
|
||||||
|
#define MSHelpCmdV L"\n -v Verbosely list contents of archive"
|
||||||
|
#define MRecVolLimit L"\nTotal number of usual and recovery volumes must not exceed %d"
|
||||||
|
#define MVolumeNumber L"volume %d"
|
||||||
|
#define MCannotDelete L"\nCannot delete %s"
|
||||||
|
#define MRecycleFailed L"\nCannot move some files and folders to Recycle Bin"
|
||||||
|
#define MCalcCRC L"\nCalculating the checksum"
|
||||||
|
#define MTooLargeSFXArc L"\nToo large SFX archive. Windows cannot run the executable file exceeding 4 GB."
|
||||||
|
#define MCalcCRCAllVol L"\nCalculating checksums of all volumes."
|
||||||
|
#define MNotEnoughDisk L"\nERROR: Not enough disk space for %s."
|
||||||
|
#define MNewerRAR L"\nYou may need a newer version of RAR."
|
||||||
|
#define MUnkEncMethod L"\nUnknown encryption method in %s"
|
||||||
|
#define MWrongPassword L"\nThe specified password is incorrect."
|
||||||
|
#define MWrongFilePassword L"\nIncorrect password for %s"
|
||||||
|
#define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x"
|
||||||
|
#define MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated"
|
||||||
|
#define MRRDamaged L"\nRecovery record is corrupt."
|
||||||
|
#define MTestingRR L"\nTesting the recovery record"
|
||||||
|
#define MFailed L"Failed"
|
||||||
|
#define MIncompatSwitch L"\n%s switch is not supported for RAR %d.x archive format."
|
||||||
|
#define MSearchDupFiles L"\nSearching for identical files"
|
||||||
|
#define MNumFound L"%d found."
|
||||||
|
#define MUnknownExtra L"\nUnknown extra field in %s."
|
||||||
|
#define MCorruptExtra L"\nCorrupt %s extra field in %s."
|
||||||
|
#define MCopyError L"\nCannot copy %s to %s."
|
||||||
|
#define MCopyErrorHint L"\nYou need to unpack the entire archive to create file reference entries."
|
||||||
|
#define MCopyingData L"\nCopying data"
|
||||||
|
#define MErrCreateLnkS L"\nCannot create symbolic link %s"
|
||||||
|
#define MErrCreateLnkH L"\nCannot create hard link %s"
|
||||||
|
#define MErrLnkTarget L"\nYou need to unpack the link target first"
|
||||||
|
#define MNeedAdmin L"\nYou may need to run RAR as administrator"
|
||||||
|
#define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB."
|
||||||
|
#define MUseSmalllerDict L"\nPlease use a smaller compression dictionary."
|
||||||
|
#define MOpenErrAtime L"\nYou may need to remove -tsp switch to open this file."
|
37
deps/unrar/log.cpp
vendored
Normal file
37
deps/unrar/log.cpp
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
static wchar LogName[NM];
|
||||||
|
static RAR_CHARSET LogCharset=RCH_DEFAULT;
|
||||||
|
|
||||||
|
void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet)
|
||||||
|
{
|
||||||
|
wcsncpyz(LogName,LogFileName,ASIZE(LogName));
|
||||||
|
LogCharset=CSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SILENT
|
||||||
|
void Log(const wchar *ArcName,const wchar *fmt,...)
|
||||||
|
{
|
||||||
|
// Preserve the error code for possible following system error message.
|
||||||
|
int Code=ErrHandler.GetSystemErrorCode();
|
||||||
|
|
||||||
|
uiAlarm(UIALARM_ERROR);
|
||||||
|
|
||||||
|
// This buffer is for format string only, not for entire output,
|
||||||
|
// so it can be short enough.
|
||||||
|
wchar fmtw[1024];
|
||||||
|
PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
|
||||||
|
|
||||||
|
safebuf wchar Msg[2*NM+1024];
|
||||||
|
va_list arglist;
|
||||||
|
va_start(arglist,fmt);
|
||||||
|
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
eprintf(L"%ls",Msg);
|
||||||
|
ErrHandler.SetSystemErrorCode(Code);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
12
deps/unrar/log.hpp
vendored
Normal file
12
deps/unrar/log.hpp
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _RAR_LOG_
|
||||||
|
#define _RAR_LOG_
|
||||||
|
|
||||||
|
void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet);
|
||||||
|
|
||||||
|
#ifdef SILENT
|
||||||
|
inline void Log(const wchar *ArcName,const wchar *fmt,...) {}
|
||||||
|
#else
|
||||||
|
void Log(const wchar *ArcName,const wchar *fmt,...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
174
deps/unrar/makefile
vendored
Normal file
174
deps/unrar/makefile
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#
|
||||||
|
# Makefile for UNIX - unrar
|
||||||
|
|
||||||
|
# Linux using GCC
|
||||||
|
CXX=c++
|
||||||
|
CXXFLAGS=-O2 -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else
|
||||||
|
LIBFLAGS=-fPIC
|
||||||
|
DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
|
||||||
|
STRIP=strip
|
||||||
|
AR=ar
|
||||||
|
LDFLAGS=-pthread
|
||||||
|
DESTDIR=/usr
|
||||||
|
|
||||||
|
# Linux using LCC
|
||||||
|
#CXX=lcc
|
||||||
|
#CXXFLAGS=-O2
|
||||||
|
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# CYGWIN using GCC
|
||||||
|
#CXX=c++
|
||||||
|
#CXXFLAGS=-O2
|
||||||
|
#LIBFLAGS=
|
||||||
|
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#LDFLAGS=-pthread
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# HP UX using aCC
|
||||||
|
#CXX=aCC
|
||||||
|
#CXXFLAGS=-AA +O2 +Onolimit
|
||||||
|
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# IRIX using GCC
|
||||||
|
#CXX=g++
|
||||||
|
#CXXFLAGS=-O2
|
||||||
|
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# IRIX using MIPSPro (experimental)
|
||||||
|
#CXX=CC
|
||||||
|
#CXXFLAGS=-O2 -mips3 -woff 1234,1156,3284 -LANG:std
|
||||||
|
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -Dint64=int64_t
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# AIX using xlC (IBM VisualAge C++ 5.0)
|
||||||
|
#CXX=xlC
|
||||||
|
#CXXFLAGS=-O -qinline -qro -qroconst -qmaxmem=16384 -qcpluscmt
|
||||||
|
#DEFINES=-D_LARGE_FILES -D_LARGE_FILE_API
|
||||||
|
#LIBS=-lbsd
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# Solaris using CC
|
||||||
|
#CXX=CC
|
||||||
|
#CXXFLAGS=-fast -erroff=wvarhidemem
|
||||||
|
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# Solaris using GCC (optimized for UltraSPARC 1 CPU)
|
||||||
|
#CXX=g++
|
||||||
|
#CXXFLAGS=-O3 -mcpu=v9 -mtune=ultrasparc -m32
|
||||||
|
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||||
|
#STRIP=/usr/ccs/bin/strip
|
||||||
|
#AR=/usr/ccs/bin/ar
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# Tru64 5.1B using GCC3
|
||||||
|
#CXX=g++
|
||||||
|
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_XOPEN_SOURCE=500
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#LDFLAGS=-rpath /usr/local/gcc/lib
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# Tru64 5.1B using DEC C++
|
||||||
|
#CXX=cxx
|
||||||
|
#CXXFLAGS=-O4 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Dint64=long
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#LDFLAGS=
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# QNX 6.x using GCC
|
||||||
|
#CXX=g++
|
||||||
|
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fexceptions
|
||||||
|
#STRIP=strip
|
||||||
|
#AR=ar
|
||||||
|
#LDFLAGS=-fexceptions
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
# Cross-compile
|
||||||
|
# Linux using arm-linux-g++
|
||||||
|
#CXX=arm-linux-g++
|
||||||
|
#CXXFLAGS=-O2
|
||||||
|
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||||
|
#STRIP=arm-linux-strip
|
||||||
|
#AR=arm-linux-ar
|
||||||
|
#LDFLAGS=-static
|
||||||
|
#DESTDIR=/usr
|
||||||
|
|
||||||
|
##########################
|
||||||
|
|
||||||
|
COMPILE=$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES)
|
||||||
|
LINK=$(CXX)
|
||||||
|
|
||||||
|
WHAT=UNRAR
|
||||||
|
|
||||||
|
UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o qopen.o
|
||||||
|
LIB_OBJ=filestr.o scantree.o dll.o qopen.o
|
||||||
|
|
||||||
|
OBJECTS=rar.o strlist.o strfn.o pathfn.o smallfn.o global.o file.o filefn.o filcreat.o \
|
||||||
|
archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
|
||||||
|
resource.o match.o timefn.o rdwrfn.o consio.o options.o errhnd.o rarvm.o secpassword.o \
|
||||||
|
rijndael.o getbits.o sha1.o sha256.o blake2s.o hash.o extinfo.o extract.o volume.o \
|
||||||
|
list.o find.o unpack.o headers.o threadpool.o rs16.o cmddata.o ui.o
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(COMPILE) -D$(WHAT) -c $<
|
||||||
|
|
||||||
|
all: unrar
|
||||||
|
|
||||||
|
install: install-unrar
|
||||||
|
|
||||||
|
uninstall: uninstall-unrar
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f *.bak *~
|
||||||
|
@rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ)
|
||||||
|
@rm -f unrar libunrar.*
|
||||||
|
|
||||||
|
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
|
||||||
|
@rm -f unrar
|
||||||
|
$(LINK) -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
|
||||||
|
$(STRIP) unrar
|
||||||
|
|
||||||
|
sfx: WHAT=SFX_MODULE
|
||||||
|
sfx: clean $(OBJECTS)
|
||||||
|
@rm -f default.sfx
|
||||||
|
$(LINK) -o default.sfx $(LDFLAGS) $(OBJECTS)
|
||||||
|
$(STRIP) default.sfx
|
||||||
|
|
||||||
|
lib: WHAT=RARDLL
|
||||||
|
lib: CXXFLAGS+=$(LIBFLAGS)
|
||||||
|
lib: clean $(OBJECTS) $(LIB_OBJ)
|
||||||
|
@rm -f libunrar.*
|
||||||
|
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
|
||||||
|
$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
|
||||||
|
|
||||||
|
install-unrar:
|
||||||
|
install -D unrar $(DESTDIR)/bin/unrar
|
||||||
|
|
||||||
|
uninstall-unrar:
|
||||||
|
rm -f $(DESTDIR)/bin/unrar
|
||||||
|
|
||||||
|
install-lib:
|
||||||
|
install libunrar.so $(DESTDIR)/lib
|
||||||
|
install libunrar.a $(DESTDIR)/lib
|
||||||
|
|
||||||
|
uninstall-lib:
|
||||||
|
rm -f $(DESTDIR)/lib/libunrar.so
|
147
deps/unrar/match.cpp
vendored
Normal file
147
deps/unrar/match.cpp
vendored
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
static bool match(const wchar *pattern,const wchar *string,bool ForceCase);
|
||||||
|
static int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase);
|
||||||
|
static int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase);
|
||||||
|
|
||||||
|
inline uint touppercw(uint ch,bool ForceCase)
|
||||||
|
{
|
||||||
|
if (ForceCase)
|
||||||
|
return ch;
|
||||||
|
#if defined(_UNIX)
|
||||||
|
return ch;
|
||||||
|
#else
|
||||||
|
return toupperw(ch);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||||
|
{
|
||||||
|
bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0;
|
||||||
|
|
||||||
|
CmpMode&=MATCH_MODEMASK;
|
||||||
|
|
||||||
|
if (CmpMode!=MATCH_NAMES)
|
||||||
|
{
|
||||||
|
size_t WildLength=wcslen(Wildcard);
|
||||||
|
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH && CmpMode!=MATCH_ALLWILD &&
|
||||||
|
mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
|
||||||
|
{
|
||||||
|
// For all modes except MATCH_NAMES, MATCH_EXACT, MATCH_EXACTPATH, MATCH_ALLWILD,
|
||||||
|
// "path1" mask must match "path1\path2\filename.ext" and "path1" names.
|
||||||
|
wchar NextCh=Name[WildLength];
|
||||||
|
if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing more to compare for MATCH_SUBPATHONLY.
|
||||||
|
if (CmpMode==MATCH_SUBPATHONLY)
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
wchar Path1[NM],Path2[NM];
|
||||||
|
GetFilePath(Wildcard,Path1,ASIZE(Path1));
|
||||||
|
GetFilePath(Name,Path2,ASIZE(Path2));
|
||||||
|
|
||||||
|
if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
|
||||||
|
mwcsicompc(Path1,Path2,ForceCase)!=0)
|
||||||
|
return(false);
|
||||||
|
if (CmpMode==MATCH_ALLWILD)
|
||||||
|
return match(Wildcard,Name,ForceCase);
|
||||||
|
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
|
||||||
|
if (IsWildcard(Path1))
|
||||||
|
return(match(Wildcard,Name,ForceCase));
|
||||||
|
else
|
||||||
|
if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard))
|
||||||
|
{
|
||||||
|
if (*Path1 && mwcsnicompc(Path1,Path2,wcslen(Path1),ForceCase)!=0)
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (mwcsicompc(Path1,Path2,ForceCase)!=0)
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
wchar *Name1=PointToName(Wildcard);
|
||||||
|
wchar *Name2=PointToName(Name);
|
||||||
|
|
||||||
|
// Always return false for RAR temporary files to exclude them
|
||||||
|
// from archiving operations.
|
||||||
|
// if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
|
||||||
|
// return(false);
|
||||||
|
|
||||||
|
if (CmpMode==MATCH_EXACT)
|
||||||
|
return(mwcsicompc(Name1,Name2,ForceCase)==0);
|
||||||
|
|
||||||
|
return(match(Name1,Name2,ForceCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool match(const wchar *pattern,const wchar *string,bool ForceCase)
|
||||||
|
{
|
||||||
|
for (;; ++string)
|
||||||
|
{
|
||||||
|
wchar stringc=touppercw(*string,ForceCase);
|
||||||
|
wchar patternc=touppercw(*pattern++,ForceCase);
|
||||||
|
switch (patternc)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return(stringc==0);
|
||||||
|
case '?':
|
||||||
|
if (stringc == 0)
|
||||||
|
return(false);
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
if (*pattern==0)
|
||||||
|
return(true);
|
||||||
|
if (*pattern=='.')
|
||||||
|
{
|
||||||
|
if (pattern[1]=='*' && pattern[2]==0)
|
||||||
|
return(true);
|
||||||
|
const wchar *dot=wcschr(string,'.');
|
||||||
|
if (pattern[1]==0)
|
||||||
|
return (dot==NULL || dot[1]==0);
|
||||||
|
if (dot!=NULL)
|
||||||
|
{
|
||||||
|
string=dot;
|
||||||
|
if (wcspbrk(pattern,L"*?")==NULL && wcschr(string+1,'.')==NULL)
|
||||||
|
return(mwcsicompc(pattern+1,string+1,ForceCase)==0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*string)
|
||||||
|
if (match(pattern,string++,ForceCase))
|
||||||
|
return(true);
|
||||||
|
return(false);
|
||||||
|
default:
|
||||||
|
if (patternc != stringc)
|
||||||
|
{
|
||||||
|
// Allow "name." mask match "name" and "name.\" match "name\".
|
||||||
|
if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.'))
|
||||||
|
return(match(pattern,string,ForceCase));
|
||||||
|
else
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase)
|
||||||
|
{
|
||||||
|
if (ForceCase)
|
||||||
|
return wcscmp(Str1,Str2);
|
||||||
|
return wcsicompc(Str1,Str2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase)
|
||||||
|
{
|
||||||
|
if (ForceCase)
|
||||||
|
return wcsncmp(Str1,Str2,N);
|
||||||
|
#if defined(_UNIX)
|
||||||
|
return wcsncmp(Str1,Str2,N);
|
||||||
|
#else
|
||||||
|
return wcsnicomp(Str1,Str2,N);
|
||||||
|
#endif
|
||||||
|
}
|
38
deps/unrar/match.hpp
vendored
Normal file
38
deps/unrar/match.hpp
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef _RAR_MATCH_
|
||||||
|
#define _RAR_MATCH_
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MATCH_NAMES, // Paths are ignored.
|
||||||
|
// Compares names only using wildcards.
|
||||||
|
|
||||||
|
MATCH_SUBPATHONLY, // Paths must match either exactly or path in wildcard
|
||||||
|
// must be present in the beginning of file path.
|
||||||
|
// For example, "c:\path1\*" or "c:\path1" will match
|
||||||
|
// "c:\path1\path2\file".
|
||||||
|
// Names are not compared.
|
||||||
|
|
||||||
|
MATCH_EXACT, // Paths must match exactly.
|
||||||
|
// Names must match exactly.
|
||||||
|
|
||||||
|
MATCH_ALLWILD, // Paths and names are compared using wildcards.
|
||||||
|
// Unlike MATCH_SUBPATH, paths do not match subdirs
|
||||||
|
// unless a wildcard tells so.
|
||||||
|
|
||||||
|
MATCH_EXACTPATH, // Paths must match exactly.
|
||||||
|
// Names are compared using wildcards.
|
||||||
|
|
||||||
|
MATCH_SUBPATH, // Names must be the same, but path in mask is allowed
|
||||||
|
// to be only a part of name path. In other words,
|
||||||
|
// we match all files matching the file mask
|
||||||
|
// in current folder and subfolders.
|
||||||
|
|
||||||
|
MATCH_WILDSUBPATH // Works as MATCH_SUBPATH if file mask contains
|
||||||
|
// wildcards and as MATCH_EXACTPATH otherwise.
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MATCH_MODEMASK 0x0000ffff
|
||||||
|
#define MATCH_FORCECASESENSITIVE 0x80000000
|
||||||
|
|
||||||
|
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode);
|
||||||
|
|
||||||
|
#endif
|
639
deps/unrar/model.cpp
vendored
Normal file
639
deps/unrar/model.cpp
vendored
Normal file
@ -0,0 +1,639 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* This file is part of PPMd project *
|
||||||
|
* Written and distributed to public domain by Dmitry Shkarin 1997, *
|
||||||
|
* 1999-2000 *
|
||||||
|
* Contents: model description and encoding/decoding routines *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static const int MAX_O=64; /* maximum allowed model order */
|
||||||
|
const uint TOP=1 << 24, BOT=1 << 15;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
|
||||||
|
|
||||||
|
|
||||||
|
inline RARPPM_CONTEXT* RARPPM_CONTEXT::createChild(ModelPPM *Model,RARPPM_STATE* pStats,
|
||||||
|
RARPPM_STATE& FirstState)
|
||||||
|
{
|
||||||
|
RARPPM_CONTEXT* pc = (RARPPM_CONTEXT*) Model->SubAlloc.AllocContext();
|
||||||
|
if ( pc )
|
||||||
|
{
|
||||||
|
pc->NumStats=1;
|
||||||
|
pc->OneState=FirstState;
|
||||||
|
pc->Suffix=this;
|
||||||
|
pStats->Successor=pc;
|
||||||
|
}
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModelPPM::ModelPPM()
|
||||||
|
{
|
||||||
|
MinContext=NULL;
|
||||||
|
MaxContext=NULL;
|
||||||
|
MedContext=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ModelPPM::RestartModelRare()
|
||||||
|
{
|
||||||
|
int i, k, m;
|
||||||
|
memset(CharMask,0,sizeof(CharMask));
|
||||||
|
SubAlloc.InitSubAllocator();
|
||||||
|
InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
|
||||||
|
MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext();
|
||||||
|
if (MinContext == NULL)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
MinContext->Suffix=NULL;
|
||||||
|
OrderFall=MaxOrder;
|
||||||
|
MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
|
||||||
|
FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2);
|
||||||
|
if (FoundState == NULL)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
|
||||||
|
{
|
||||||
|
MinContext->U.Stats[i].Symbol=i;
|
||||||
|
MinContext->U.Stats[i].Freq=1;
|
||||||
|
MinContext->U.Stats[i].Successor=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ushort InitBinEsc[]={
|
||||||
|
0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i=0;i < 128;i++)
|
||||||
|
for (k=0;k < 8;k++)
|
||||||
|
for (m=0;m < 64;m += 8)
|
||||||
|
BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2);
|
||||||
|
for (i=0;i < 25;i++)
|
||||||
|
for (k=0;k < 16;k++)
|
||||||
|
SEE2Cont[i][k].init(5*i+10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ModelPPM::StartModelRare(int MaxOrder)
|
||||||
|
{
|
||||||
|
int i, k, m ,Step;
|
||||||
|
EscCount=1;
|
||||||
|
/*
|
||||||
|
if (MaxOrder < 2)
|
||||||
|
{
|
||||||
|
memset(CharMask,0,sizeof(CharMask));
|
||||||
|
OrderFall=ModelPPM::MaxOrder;
|
||||||
|
MinContext=MaxContext;
|
||||||
|
while (MinContext->Suffix != NULL)
|
||||||
|
{
|
||||||
|
MinContext=MinContext->Suffix;
|
||||||
|
OrderFall--;
|
||||||
|
}
|
||||||
|
FoundState=MinContext->U.Stats;
|
||||||
|
MinContext=MaxContext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
ModelPPM::MaxOrder=MaxOrder;
|
||||||
|
RestartModelRare();
|
||||||
|
NS2BSIndx[0]=2*0;
|
||||||
|
NS2BSIndx[1]=2*1;
|
||||||
|
memset(NS2BSIndx+2,2*2,9);
|
||||||
|
memset(NS2BSIndx+11,2*3,256-11);
|
||||||
|
for (i=0;i < 3;i++)
|
||||||
|
NS2Indx[i]=i;
|
||||||
|
for (m=i, k=Step=1;i < 256;i++)
|
||||||
|
{
|
||||||
|
NS2Indx[i]=m;
|
||||||
|
if ( !--k )
|
||||||
|
{
|
||||||
|
k = ++Step;
|
||||||
|
m++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(HB2Flag,0,0x40);
|
||||||
|
memset(HB2Flag+0x40,0x08,0x100-0x40);
|
||||||
|
DummySEE2Cont.Shift=PERIOD_BITS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RARPPM_CONTEXT::rescale(ModelPPM *Model)
|
||||||
|
{
|
||||||
|
int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
|
||||||
|
RARPPM_STATE* p1, * p;
|
||||||
|
for (p=Model->FoundState;p != U.Stats;p--)
|
||||||
|
_PPMD_SWAP(p[0],p[-1]);
|
||||||
|
U.Stats->Freq += 4;
|
||||||
|
U.SummFreq += 4;
|
||||||
|
EscFreq=U.SummFreq-p->Freq;
|
||||||
|
Adder=(Model->OrderFall != 0);
|
||||||
|
U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
EscFreq -= (++p)->Freq;
|
||||||
|
U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
|
||||||
|
if (p[0].Freq > p[-1].Freq)
|
||||||
|
{
|
||||||
|
RARPPM_STATE tmp=*(p1=p);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p1[0]=p1[-1];
|
||||||
|
} while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq);
|
||||||
|
*p1=tmp;
|
||||||
|
}
|
||||||
|
} while ( --i );
|
||||||
|
if (p->Freq == 0)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
} while ((--p)->Freq == 0);
|
||||||
|
EscFreq += i;
|
||||||
|
if ((NumStats -= i) == 1)
|
||||||
|
{
|
||||||
|
RARPPM_STATE tmp=*U.Stats;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tmp.Freq-=(tmp.Freq >> 1);
|
||||||
|
EscFreq>>=1;
|
||||||
|
} while (EscFreq > 1);
|
||||||
|
Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1);
|
||||||
|
*(Model->FoundState=&OneState)=tmp; return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
U.SummFreq += (EscFreq -= (EscFreq >> 1));
|
||||||
|
int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
|
||||||
|
if (n0 != n1)
|
||||||
|
U.Stats = (RARPPM_STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
|
||||||
|
Model->FoundState=U.Stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1)
|
||||||
|
{
|
||||||
|
RARPPM_STATE UpState;
|
||||||
|
RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
|
||||||
|
RARPPM_STATE * p, * ps[MAX_O], ** pps=ps;
|
||||||
|
if ( !Skip )
|
||||||
|
{
|
||||||
|
*pps++ = FoundState;
|
||||||
|
if ( !pc->Suffix )
|
||||||
|
goto NO_LOOP;
|
||||||
|
}
|
||||||
|
if ( p1 )
|
||||||
|
{
|
||||||
|
p=p1;
|
||||||
|
pc=pc->Suffix;
|
||||||
|
goto LOOP_ENTRY;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pc=pc->Suffix;
|
||||||
|
if (pc->NumStats != 1)
|
||||||
|
{
|
||||||
|
if ((p=pc->U.Stats)->Symbol != FoundState->Symbol)
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
} while (p->Symbol != FoundState->Symbol);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p=&(pc->OneState);
|
||||||
|
LOOP_ENTRY:
|
||||||
|
if (p->Successor != UpBranch)
|
||||||
|
{
|
||||||
|
pc=p->Successor;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
// We ensure that PPM order input parameter does not exceed MAX_O (64),
|
||||||
|
// so we do not really need this check and added it for extra safety.
|
||||||
|
// See CVE-2017-17969 for details.
|
||||||
|
if (pps>=ps+ASIZE(ps))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*pps++ = p;
|
||||||
|
} while ( pc->Suffix );
|
||||||
|
NO_LOOP:
|
||||||
|
if (pps == ps)
|
||||||
|
return pc;
|
||||||
|
UpState.Symbol=*(byte*) UpBranch;
|
||||||
|
UpState.Successor=(RARPPM_CONTEXT*) (((byte*) UpBranch)+1);
|
||||||
|
if (pc->NumStats != 1)
|
||||||
|
{
|
||||||
|
if ((byte*) pc <= SubAlloc.pText)
|
||||||
|
return(NULL);
|
||||||
|
if ((p=pc->U.Stats)->Symbol != UpState.Symbol)
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
} while (p->Symbol != UpState.Symbol);
|
||||||
|
uint cf=p->Freq-1;
|
||||||
|
uint s0=pc->U.SummFreq-pc->NumStats-cf;
|
||||||
|
UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
UpState.Freq=pc->OneState.Freq;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pc = pc->createChild(this,*--pps,UpState);
|
||||||
|
if ( !pc )
|
||||||
|
return NULL;
|
||||||
|
} while (pps != ps);
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void ModelPPM::UpdateModel()
|
||||||
|
{
|
||||||
|
RARPPM_STATE fs = *FoundState, *p = NULL;
|
||||||
|
RARPPM_CONTEXT *pc, *Successor;
|
||||||
|
uint ns1, ns, cf, sf, s0;
|
||||||
|
if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
|
||||||
|
{
|
||||||
|
if (pc->NumStats != 1)
|
||||||
|
{
|
||||||
|
if ((p=pc->U.Stats)->Symbol != fs.Symbol)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
} while (p->Symbol != fs.Symbol);
|
||||||
|
if (p[0].Freq >= p[-1].Freq)
|
||||||
|
{
|
||||||
|
_PPMD_SWAP(p[0],p[-1]);
|
||||||
|
p--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p->Freq < MAX_FREQ-9)
|
||||||
|
{
|
||||||
|
p->Freq += 2;
|
||||||
|
pc->U.SummFreq += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p=&(pc->OneState);
|
||||||
|
p->Freq += (p->Freq < 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !OrderFall )
|
||||||
|
{
|
||||||
|
MinContext=MaxContext=FoundState->Successor=CreateSuccessors(TRUE,p);
|
||||||
|
if ( !MinContext )
|
||||||
|
goto RESTART_MODEL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*SubAlloc.pText++ = fs.Symbol;
|
||||||
|
Successor = (RARPPM_CONTEXT*) SubAlloc.pText;
|
||||||
|
if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
|
||||||
|
goto RESTART_MODEL;
|
||||||
|
if ( fs.Successor )
|
||||||
|
{
|
||||||
|
if ((byte*) fs.Successor <= SubAlloc.pText &&
|
||||||
|
(fs.Successor=CreateSuccessors(FALSE,p)) == NULL)
|
||||||
|
goto RESTART_MODEL;
|
||||||
|
if ( !--OrderFall )
|
||||||
|
{
|
||||||
|
Successor=fs.Successor;
|
||||||
|
SubAlloc.pText -= (MaxContext != MinContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FoundState->Successor=Successor;
|
||||||
|
fs.Successor=MinContext;
|
||||||
|
}
|
||||||
|
s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1);
|
||||||
|
for (pc=MaxContext;pc != MinContext;pc=pc->Suffix)
|
||||||
|
{
|
||||||
|
if ((ns1=pc->NumStats) != 1)
|
||||||
|
{
|
||||||
|
if ((ns1 & 1) == 0)
|
||||||
|
{
|
||||||
|
pc->U.Stats=(RARPPM_STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
|
||||||
|
if ( !pc->U.Stats )
|
||||||
|
goto RESTART_MODEL;
|
||||||
|
}
|
||||||
|
pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p=(RARPPM_STATE*) SubAlloc.AllocUnits(1);
|
||||||
|
if ( !p )
|
||||||
|
goto RESTART_MODEL;
|
||||||
|
*p=pc->OneState;
|
||||||
|
pc->U.Stats=p;
|
||||||
|
if (p->Freq < MAX_FREQ/4-1)
|
||||||
|
p->Freq += p->Freq;
|
||||||
|
else
|
||||||
|
p->Freq = MAX_FREQ-4;
|
||||||
|
pc->U.SummFreq=p->Freq+InitEsc+(ns > 3);
|
||||||
|
}
|
||||||
|
cf=2*fs.Freq*(pc->U.SummFreq+6);
|
||||||
|
sf=s0+pc->U.SummFreq;
|
||||||
|
if (cf < 6*sf)
|
||||||
|
{
|
||||||
|
cf=1+(cf > sf)+(cf >= 4*sf);
|
||||||
|
pc->U.SummFreq += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf);
|
||||||
|
pc->U.SummFreq += cf;
|
||||||
|
}
|
||||||
|
p=pc->U.Stats+ns1;
|
||||||
|
p->Successor=Successor;
|
||||||
|
p->Symbol = fs.Symbol;
|
||||||
|
p->Freq = cf;
|
||||||
|
pc->NumStats=++ns1;
|
||||||
|
}
|
||||||
|
MaxContext=MinContext=fs.Successor;
|
||||||
|
return;
|
||||||
|
RESTART_MODEL:
|
||||||
|
RestartModelRare();
|
||||||
|
EscCount=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tabulated escapes for exponential symbol distribution
|
||||||
|
static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||||
|
#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
||||||
|
{
|
||||||
|
RARPPM_STATE& rs=OneState;
|
||||||
|
Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
|
||||||
|
ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
|
||||||
|
Model->NS2BSIndx[Suffix->NumStats-1]+
|
||||||
|
Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+
|
||||||
|
((Model->RunLength >> 26) & 0x20)];
|
||||||
|
if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs)
|
||||||
|
{
|
||||||
|
Model->FoundState=&rs;
|
||||||
|
rs.Freq += (rs.Freq < 128);
|
||||||
|
Model->Coder.SubRange.LowCount=0;
|
||||||
|
Model->Coder.SubRange.HighCount=bs;
|
||||||
|
bs = GET_SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
|
||||||
|
Model->PrevSuccess=1;
|
||||||
|
Model->RunLength++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Model->Coder.SubRange.LowCount=bs;
|
||||||
|
bs = GET_SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
|
||||||
|
Model->Coder.SubRange.HighCount=BIN_SCALE;
|
||||||
|
Model->InitEsc=ExpEscape[bs >> 10];
|
||||||
|
Model->NumMasked=1;
|
||||||
|
Model->CharMask[rs.Symbol]=Model->EscCount;
|
||||||
|
Model->PrevSuccess=0;
|
||||||
|
Model->FoundState=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RARPPM_CONTEXT::update1(ModelPPM *Model,RARPPM_STATE* p)
|
||||||
|
{
|
||||||
|
(Model->FoundState=p)->Freq += 4;
|
||||||
|
U.SummFreq += 4;
|
||||||
|
if (p[0].Freq > p[-1].Freq)
|
||||||
|
{
|
||||||
|
_PPMD_SWAP(p[0],p[-1]);
|
||||||
|
Model->FoundState=--p;
|
||||||
|
if (p->Freq > MAX_FREQ)
|
||||||
|
rescale(Model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool RARPPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
|
||||||
|
{
|
||||||
|
Model->Coder.SubRange.scale=U.SummFreq;
|
||||||
|
RARPPM_STATE* p=U.Stats;
|
||||||
|
int i, HiCnt;
|
||||||
|
int count=Model->Coder.GetCurrentCount();
|
||||||
|
if (count>=(int)Model->Coder.SubRange.scale)
|
||||||
|
return(false);
|
||||||
|
if (count < (HiCnt=p->Freq))
|
||||||
|
{
|
||||||
|
Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale);
|
||||||
|
Model->RunLength += Model->PrevSuccess;
|
||||||
|
(Model->FoundState=p)->Freq=(HiCnt += 4);
|
||||||
|
U.SummFreq += 4;
|
||||||
|
if (HiCnt > MAX_FREQ)
|
||||||
|
rescale(Model);
|
||||||
|
Model->Coder.SubRange.LowCount=0;
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (Model->FoundState==NULL)
|
||||||
|
return(false);
|
||||||
|
Model->PrevSuccess=0;
|
||||||
|
i=NumStats-1;
|
||||||
|
while ((HiCnt += (++p)->Freq) <= count)
|
||||||
|
if (--i == 0)
|
||||||
|
{
|
||||||
|
Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
|
||||||
|
Model->Coder.SubRange.LowCount=HiCnt;
|
||||||
|
Model->CharMask[p->Symbol]=Model->EscCount;
|
||||||
|
i=(Model->NumMasked=NumStats)-1;
|
||||||
|
Model->FoundState=NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Model->CharMask[(--p)->Symbol]=Model->EscCount;
|
||||||
|
} while ( --i );
|
||||||
|
Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
|
||||||
|
update1(Model,p);
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RARPPM_CONTEXT::update2(ModelPPM *Model,RARPPM_STATE* p)
|
||||||
|
{
|
||||||
|
(Model->FoundState=p)->Freq += 4;
|
||||||
|
U.SummFreq += 4;
|
||||||
|
if (p->Freq > MAX_FREQ)
|
||||||
|
rescale(Model);
|
||||||
|
Model->EscCount++;
|
||||||
|
Model->RunLength=Model->InitRL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline RARPPM_SEE2_CONTEXT* RARPPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
|
||||||
|
{
|
||||||
|
RARPPM_SEE2_CONTEXT* psee2c;
|
||||||
|
if (NumStats != 256)
|
||||||
|
{
|
||||||
|
psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
|
||||||
|
(Diff < Suffix->NumStats-NumStats)+
|
||||||
|
2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+
|
||||||
|
Model->HiBitsFlag;
|
||||||
|
Model->Coder.SubRange.scale=psee2c->getMean();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psee2c=&Model->DummySEE2Cont;
|
||||||
|
Model->Coder.SubRange.scale=1;
|
||||||
|
}
|
||||||
|
return psee2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||||
|
{
|
||||||
|
int count, HiCnt, i=NumStats-Model->NumMasked;
|
||||||
|
RARPPM_SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
|
||||||
|
RARPPM_STATE* ps[256], ** pps=ps, * p=U.Stats-1;
|
||||||
|
HiCnt=0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
} while (Model->CharMask[p->Symbol] == Model->EscCount);
|
||||||
|
HiCnt += p->Freq;
|
||||||
|
|
||||||
|
// We do not reuse PPMd coder in unstable state, so we do not really need
|
||||||
|
// this check and added it for extra safety. See CVE-2017-17969 for details.
|
||||||
|
if (pps>=ps+ASIZE(ps))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*pps++ = p;
|
||||||
|
} while ( --i );
|
||||||
|
Model->Coder.SubRange.scale += HiCnt;
|
||||||
|
count=Model->Coder.GetCurrentCount();
|
||||||
|
if (count>=(int)Model->Coder.SubRange.scale)
|
||||||
|
return(false);
|
||||||
|
p=*(pps=ps);
|
||||||
|
if (count < HiCnt)
|
||||||
|
{
|
||||||
|
HiCnt=0;
|
||||||
|
while ((HiCnt += p->Freq) <= count)
|
||||||
|
{
|
||||||
|
pps++;
|
||||||
|
if (pps>=ps+ASIZE(ps)) // Extra safety check.
|
||||||
|
return false;
|
||||||
|
p=*pps;
|
||||||
|
}
|
||||||
|
Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
|
||||||
|
psee2c->update();
|
||||||
|
update2(Model,p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Model->Coder.SubRange.LowCount=HiCnt;
|
||||||
|
Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
|
||||||
|
i=NumStats-Model->NumMasked;
|
||||||
|
pps--;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pps++;
|
||||||
|
if (pps>=ps+ASIZE(ps)) // Extra safety check.
|
||||||
|
return false;
|
||||||
|
Model->CharMask[(*pps)->Symbol]=Model->EscCount;
|
||||||
|
} while ( --i );
|
||||||
|
psee2c->Summ += Model->Coder.SubRange.scale;
|
||||||
|
Model->NumMasked = NumStats;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void ModelPPM::ClearMask()
|
||||||
|
{
|
||||||
|
EscCount=1;
|
||||||
|
memset(CharMask,0,sizeof(CharMask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// reset PPM variables after data error allowing safe resuming
|
||||||
|
// of further data processing
|
||||||
|
void ModelPPM::CleanUp()
|
||||||
|
{
|
||||||
|
SubAlloc.StopSubAllocator();
|
||||||
|
SubAlloc.StartSubAllocator(1);
|
||||||
|
StartModelRare(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
|
||||||
|
{
|
||||||
|
int MaxOrder=UnpackRead->GetChar();
|
||||||
|
bool Reset=(MaxOrder & 0x20)!=0;
|
||||||
|
|
||||||
|
int MaxMB;
|
||||||
|
if (Reset)
|
||||||
|
MaxMB=UnpackRead->GetChar();
|
||||||
|
else
|
||||||
|
if (SubAlloc.GetAllocatedMemory()==0)
|
||||||
|
return(false);
|
||||||
|
if (MaxOrder & 0x40)
|
||||||
|
EscChar=UnpackRead->GetChar();
|
||||||
|
Coder.InitDecoder(UnpackRead);
|
||||||
|
if (Reset)
|
||||||
|
{
|
||||||
|
MaxOrder=(MaxOrder & 0x1f)+1;
|
||||||
|
if (MaxOrder>16)
|
||||||
|
MaxOrder=16+(MaxOrder-16)*3;
|
||||||
|
if (MaxOrder==1)
|
||||||
|
{
|
||||||
|
SubAlloc.StopSubAllocator();
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
SubAlloc.StartSubAllocator(MaxMB+1);
|
||||||
|
StartModelRare(MaxOrder);
|
||||||
|
}
|
||||||
|
return(MinContext!=NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ModelPPM::DecodeChar()
|
||||||
|
{
|
||||||
|
if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
|
||||||
|
return(-1);
|
||||||
|
if (MinContext->NumStats != 1)
|
||||||
|
{
|
||||||
|
if ((byte*)MinContext->U.Stats <= SubAlloc.pText || (byte*)MinContext->U.Stats>SubAlloc.HeapEnd)
|
||||||
|
return(-1);
|
||||||
|
if (!MinContext->decodeSymbol1(this))
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MinContext->decodeBinSymbol(this);
|
||||||
|
Coder.Decode();
|
||||||
|
while ( !FoundState )
|
||||||
|
{
|
||||||
|
ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
OrderFall++;
|
||||||
|
MinContext=MinContext->Suffix;
|
||||||
|
if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
|
||||||
|
return(-1);
|
||||||
|
} while (MinContext->NumStats == NumMasked);
|
||||||
|
if (!MinContext->decodeSymbol2(this))
|
||||||
|
return(-1);
|
||||||
|
Coder.Decode();
|
||||||
|
}
|
||||||
|
int Symbol=FoundState->Symbol;
|
||||||
|
if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText)
|
||||||
|
MinContext=MaxContext=FoundState->Successor;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateModel();
|
||||||
|
if (EscCount == 0)
|
||||||
|
ClearMask();
|
||||||
|
}
|
||||||
|
ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
|
||||||
|
return(Symbol);
|
||||||
|
}
|
122
deps/unrar/model.hpp
vendored
Normal file
122
deps/unrar/model.hpp
vendored
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#ifndef _RAR_PPMMODEL_
|
||||||
|
#define _RAR_PPMMODEL_
|
||||||
|
|
||||||
|
#include "coder.hpp"
|
||||||
|
#include "suballoc.hpp"
|
||||||
|
|
||||||
|
#ifdef ALLOW_MISALIGNED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct RARPPM_DEF
|
||||||
|
{
|
||||||
|
static const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
|
||||||
|
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
|
||||||
|
{ // SEE-contexts for PPM-contexts with masked symbols
|
||||||
|
ushort Summ;
|
||||||
|
byte Shift, Count;
|
||||||
|
void init(int InitVal)
|
||||||
|
{
|
||||||
|
Summ=InitVal << (Shift=PERIOD_BITS-4);
|
||||||
|
Count=4;
|
||||||
|
}
|
||||||
|
uint getMean()
|
||||||
|
{
|
||||||
|
uint RetVal=GET_SHORT16(Summ) >> Shift;
|
||||||
|
Summ -= RetVal;
|
||||||
|
return RetVal+(RetVal == 0);
|
||||||
|
}
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
if (Shift < PERIOD_BITS && --Count == 0)
|
||||||
|
{
|
||||||
|
Summ += Summ;
|
||||||
|
Count=3 << Shift++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModelPPM;
|
||||||
|
struct RARPPM_CONTEXT;
|
||||||
|
|
||||||
|
struct RARPPM_STATE
|
||||||
|
{
|
||||||
|
byte Symbol;
|
||||||
|
byte Freq;
|
||||||
|
RARPPM_CONTEXT* Successor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct RARPPM_CONTEXT : RARPPM_DEF
|
||||||
|
{
|
||||||
|
ushort NumStats;
|
||||||
|
|
||||||
|
struct FreqData
|
||||||
|
{
|
||||||
|
ushort SummFreq;
|
||||||
|
RARPPM_STATE RARPPM_PACK_ATTR * Stats;
|
||||||
|
};
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FreqData U;
|
||||||
|
RARPPM_STATE OneState;
|
||||||
|
};
|
||||||
|
|
||||||
|
RARPPM_CONTEXT* Suffix;
|
||||||
|
inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
|
||||||
|
inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
|
||||||
|
inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
|
||||||
|
inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
|
||||||
|
inline bool decodeSymbol1(ModelPPM *Model); // other orders:
|
||||||
|
inline bool decodeSymbol2(ModelPPM *Model); // BCD context
|
||||||
|
inline void update1(ModelPPM *Model,RARPPM_STATE* p); // CD suffix
|
||||||
|
inline void update2(ModelPPM *Model,RARPPM_STATE* p); // BCDE successor
|
||||||
|
void rescale(ModelPPM *Model);
|
||||||
|
inline RARPPM_CONTEXT* createChild(ModelPPM *Model,RARPPM_STATE* pStats,RARPPM_STATE& FirstState);
|
||||||
|
inline RARPPM_SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ALLOW_MISALIGNED
|
||||||
|
#ifdef _AIX
|
||||||
|
#pragma pack(pop)
|
||||||
|
#else
|
||||||
|
#pragma pack()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ModelPPM : RARPPM_DEF
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
friend struct RARPPM_CONTEXT;
|
||||||
|
|
||||||
|
RARPPM_SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
|
||||||
|
|
||||||
|
struct RARPPM_CONTEXT *MinContext, *MedContext, *MaxContext;
|
||||||
|
RARPPM_STATE* FoundState; // found next state transition
|
||||||
|
int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
|
||||||
|
byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
||||||
|
byte EscCount, PrevSuccess, HiBitsFlag;
|
||||||
|
ushort BinSumm[128][64]; // binary SEE-contexts
|
||||||
|
|
||||||
|
RangeCoder Coder;
|
||||||
|
SubAllocator SubAlloc;
|
||||||
|
|
||||||
|
void RestartModelRare();
|
||||||
|
void StartModelRare(int MaxOrder);
|
||||||
|
inline RARPPM_CONTEXT* CreateSuccessors(bool Skip,RARPPM_STATE* p1);
|
||||||
|
|
||||||
|
inline void UpdateModel();
|
||||||
|
inline void ClearMask();
|
||||||
|
public:
|
||||||
|
ModelPPM();
|
||||||
|
void CleanUp(); // reset PPM variables after data error
|
||||||
|
bool DecodeInit(Unpack *UnpackRead,int &EscChar);
|
||||||
|
int DecodeChar();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
35
deps/unrar/options.cpp
vendored
Normal file
35
deps/unrar/options.cpp
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
RAROptions::RAROptions()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RAROptions::~RAROptions()
|
||||||
|
{
|
||||||
|
// It is important for security reasons, so we do not have the unnecessary
|
||||||
|
// password data left in memory.
|
||||||
|
memset(this,0,sizeof(RAROptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RAROptions::Init()
|
||||||
|
{
|
||||||
|
memset(this,0,sizeof(RAROptions));
|
||||||
|
WinSize=0x2000000;
|
||||||
|
Overwrite=OVERWRITE_DEFAULT;
|
||||||
|
Method=3;
|
||||||
|
MsgStream=MSG_STDOUT;
|
||||||
|
ConvertNames=NAMES_ORIGINALCASE;
|
||||||
|
xmtime=EXTTIME_MAX;
|
||||||
|
FileSizeLess=INT64NDF;
|
||||||
|
FileSizeMore=INT64NDF;
|
||||||
|
HashType=HASH_CRC32;
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
Threads=GetNumberOfThreads();
|
||||||
|
#endif
|
||||||
|
#ifdef USE_QOPEN
|
||||||
|
QOpenMode=QOPEN_AUTO;
|
||||||
|
#endif
|
||||||
|
}
|
214
deps/unrar/options.hpp
vendored
Normal file
214
deps/unrar/options.hpp
vendored
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
#ifndef _RAR_OPTIONS_
|
||||||
|
#define _RAR_OPTIONS_
|
||||||
|
|
||||||
|
#define DEFAULT_RECOVERY -3
|
||||||
|
|
||||||
|
#define DEFAULT_RECVOLUMES -10
|
||||||
|
|
||||||
|
#define VOLSIZE_AUTO INT64NDF // Automatically detect the volume size.
|
||||||
|
|
||||||
|
enum PATH_EXCL_MODE {
|
||||||
|
EXCL_UNCHANGED=0, // Process paths as is (default).
|
||||||
|
EXCL_SKIPWHOLEPATH, // -ep (exclude the path completely)
|
||||||
|
EXCL_BASEPATH, // -ep1 (exclude the base part of path)
|
||||||
|
EXCL_SAVEFULLPATH, // -ep2 (the full path without the disk letter)
|
||||||
|
EXCL_ABSPATH // -ep3 (the full path with the disk letter)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
|
||||||
|
SOLID_VOLUME_DEPENDENT=8,SOLID_VOLUME_INDEPENDENT=16};
|
||||||
|
|
||||||
|
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
|
||||||
|
|
||||||
|
enum EXTTIME_MODE {
|
||||||
|
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
|
||||||
|
|
||||||
|
enum MESSAGE_TYPE {MSG_STDOUT=0,MSG_STDERR,MSG_ERRONLY,MSG_NULL};
|
||||||
|
|
||||||
|
enum RECURSE_MODE
|
||||||
|
{
|
||||||
|
RECURSE_NONE=0, // no recurse switches
|
||||||
|
RECURSE_DISABLE, // switch -r-
|
||||||
|
RECURSE_ALWAYS, // switch -r
|
||||||
|
RECURSE_WILDCARDS, // switch -r0
|
||||||
|
};
|
||||||
|
|
||||||
|
enum OVERWRITE_MODE
|
||||||
|
{
|
||||||
|
OVERWRITE_DEFAULT=0, // Ask when extracting, silently overwrite when archiving.
|
||||||
|
OVERWRITE_ALL,
|
||||||
|
OVERWRITE_NONE,
|
||||||
|
OVERWRITE_AUTORENAME,
|
||||||
|
OVERWRITE_FORCE_ASK
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum QOPEN_MODE { QOPEN_NONE, QOPEN_AUTO, QOPEN_ALWAYS };
|
||||||
|
|
||||||
|
enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE,RCH_UTF8 };
|
||||||
|
|
||||||
|
#define MAX_FILTER_TYPES 16
|
||||||
|
enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE};
|
||||||
|
|
||||||
|
|
||||||
|
enum SAVECOPY_MODE {
|
||||||
|
SAVECOPY_NONE=0, SAVECOPY_SILENT, SAVECOPY_LIST, SAVECOPY_LISTEXIT,
|
||||||
|
SAVECOPY_DUPLISTEXIT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum APPENDARCNAME_MODE
|
||||||
|
{
|
||||||
|
APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNDIR
|
||||||
|
};
|
||||||
|
|
||||||
|
enum POWER_MODE {
|
||||||
|
POWERMODE_KEEP=0,POWERMODE_OFF,POWERMODE_HIBERNATE,POWERMODE_SLEEP,
|
||||||
|
POWERMODE_RESTART
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Need "forced off" state to turn off sound in GUI command line.
|
||||||
|
enum SOUND_NOTIFY_MODE {SOUND_NOTIFY_DEFAULT=0,SOUND_NOTIFY_ON,SOUND_NOTIFY_OFF};
|
||||||
|
|
||||||
|
struct FilterMode
|
||||||
|
{
|
||||||
|
FilterState State;
|
||||||
|
int Param1;
|
||||||
|
int Param2;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_GENERATE_MASK 128
|
||||||
|
|
||||||
|
|
||||||
|
class RAROptions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RAROptions();
|
||||||
|
~RAROptions();
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
uint ExclFileAttr;
|
||||||
|
uint InclFileAttr;
|
||||||
|
|
||||||
|
// We handle -ed and -e+d with special flags instead of attribute mask,
|
||||||
|
// so it works with both Windows and Unix archives.
|
||||||
|
bool ExclDir;
|
||||||
|
bool InclDir;
|
||||||
|
|
||||||
|
bool InclAttrSet;
|
||||||
|
size_t WinSize;
|
||||||
|
wchar TempPath[NM];
|
||||||
|
wchar SFXModule[NM];
|
||||||
|
|
||||||
|
#ifdef USE_QOPEN
|
||||||
|
QOPEN_MODE QOpenMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool ConfigDisabled; // Switch -cfg-.
|
||||||
|
wchar ExtrPath[NM];
|
||||||
|
wchar CommentFile[NM];
|
||||||
|
RAR_CHARSET CommentCharset;
|
||||||
|
RAR_CHARSET FilelistCharset;
|
||||||
|
RAR_CHARSET ErrlogCharset;
|
||||||
|
RAR_CHARSET RedirectCharset;
|
||||||
|
|
||||||
|
wchar ArcPath[NM];
|
||||||
|
SecPassword Password;
|
||||||
|
bool EncryptHeaders;
|
||||||
|
|
||||||
|
bool ManualPassword; // Password entered manually during operation, might need to clean for next archive.
|
||||||
|
|
||||||
|
wchar LogName[NM];
|
||||||
|
MESSAGE_TYPE MsgStream;
|
||||||
|
SOUND_NOTIFY_MODE Sound;
|
||||||
|
OVERWRITE_MODE Overwrite;
|
||||||
|
int Method;
|
||||||
|
HASH_TYPE HashType;
|
||||||
|
int Recovery;
|
||||||
|
int RecVolNumber;
|
||||||
|
bool DisablePercentage;
|
||||||
|
bool DisableCopyright;
|
||||||
|
bool DisableDone;
|
||||||
|
bool PrintVersion;
|
||||||
|
int Solid;
|
||||||
|
int SolidCount;
|
||||||
|
bool ClearArc;
|
||||||
|
bool AddArcOnly;
|
||||||
|
bool DisableComment;
|
||||||
|
bool FreshFiles;
|
||||||
|
bool UpdateFiles;
|
||||||
|
PATH_EXCL_MODE ExclPath;
|
||||||
|
RECURSE_MODE Recurse;
|
||||||
|
int64 VolSize;
|
||||||
|
Array<int64> NextVolSizes;
|
||||||
|
uint CurVolNum;
|
||||||
|
bool AllYes;
|
||||||
|
bool MoreInfo; // -im, show more information, used only in "WinRAR t" now.
|
||||||
|
bool DisableSortSolid;
|
||||||
|
int ArcTime;
|
||||||
|
int ConvertNames;
|
||||||
|
bool ProcessOwners;
|
||||||
|
bool SaveSymLinks;
|
||||||
|
bool SaveHardLinks;
|
||||||
|
bool AbsoluteLinks;
|
||||||
|
int Priority;
|
||||||
|
int SleepTime;
|
||||||
|
bool KeepBroken;
|
||||||
|
bool OpenShared;
|
||||||
|
bool DeleteFiles;
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool AllowIncompatNames; // Allow names with trailing dots and spaces.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
bool GenerateArcName;
|
||||||
|
wchar GenerateMask[MAX_GENERATE_MASK];
|
||||||
|
wchar DefGenerateMask[MAX_GENERATE_MASK];
|
||||||
|
#endif
|
||||||
|
bool SyncFiles;
|
||||||
|
bool ProcessEA;
|
||||||
|
bool SaveStreams;
|
||||||
|
bool SetCompressedAttr;
|
||||||
|
bool IgnoreGeneralAttr;
|
||||||
|
RarTime FileMtimeBefore,FileCtimeBefore,FileAtimeBefore;
|
||||||
|
bool FileMtimeBeforeOR,FileCtimeBeforeOR,FileAtimeBeforeOR;
|
||||||
|
RarTime FileMtimeAfter,FileCtimeAfter,FileAtimeAfter;
|
||||||
|
bool FileMtimeAfterOR,FileCtimeAfterOR,FileAtimeAfterOR;
|
||||||
|
int64 FileSizeLess;
|
||||||
|
int64 FileSizeMore;
|
||||||
|
bool Lock;
|
||||||
|
bool Test;
|
||||||
|
bool VolumePause;
|
||||||
|
FilterMode FilterModes[MAX_FILTER_TYPES];
|
||||||
|
wchar EmailTo[NM];
|
||||||
|
uint VersionControl;
|
||||||
|
APPENDARCNAME_MODE AppendArcNameToPath;
|
||||||
|
POWER_MODE Shutdown;
|
||||||
|
EXTTIME_MODE xmtime; // Extended time modes (time precision to store).
|
||||||
|
EXTTIME_MODE xctime;
|
||||||
|
EXTTIME_MODE xatime;
|
||||||
|
bool PreserveAtime;
|
||||||
|
wchar CompressStdin[NM];
|
||||||
|
|
||||||
|
uint Threads; // We use it to init hash even if RAR_SMP is not defined.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RARDLL
|
||||||
|
wchar DllDestName[NM];
|
||||||
|
int DllOpMode;
|
||||||
|
int DllError;
|
||||||
|
LPARAM UserData;
|
||||||
|
UNRARCALLBACK Callback;
|
||||||
|
CHANGEVOLPROC ChangeVolProc;
|
||||||
|
PROCESSDATAPROC ProcessDataProc;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
269
deps/unrar/os.hpp
vendored
Normal file
269
deps/unrar/os.hpp
vendored
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
#ifndef _RAR_OS_
|
||||||
|
#define _RAR_OS_
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
#ifdef __EMX__
|
||||||
|
#define INCL_BASE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(RARDLL) && !defined(SILENT)
|
||||||
|
#define SILENT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) || defined(_EMX)
|
||||||
|
|
||||||
|
#define LITTLE_ENDIAN
|
||||||
|
#define NM 2048
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
|
||||||
|
|
||||||
|
// We got a report that just "#define STRICT" is incompatible with
|
||||||
|
// "#define STRICT 1" in Windows 10 SDK minwindef.h and depending on the order
|
||||||
|
// in which these statements are reached this may cause a compiler warning
|
||||||
|
// and build break for other projects incorporating this source.
|
||||||
|
// So we changed it to "#define STRICT 1".
|
||||||
|
#ifndef STRICT
|
||||||
|
#define STRICT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 'ifndef' check here is needed for unrar.dll header to avoid macro
|
||||||
|
// re-definition warnings in third party projects.
|
||||||
|
#ifndef UNICODE
|
||||||
|
#define UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef WINVER
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define WINVER 0x0501
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
|
||||||
|
#if !defined(ZIPSFX)
|
||||||
|
#define RAR_SMP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <prsht.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
#include <PowrProf.h>
|
||||||
|
#pragma comment(lib, "PowrProf.lib")
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <winioctl.h>
|
||||||
|
#include <wincrypt.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _WIN_ALL
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dos.h>
|
||||||
|
|
||||||
|
#if !defined(_EMX) && !defined(_MSC_VER)
|
||||||
|
#include <dir.h>
|
||||||
|
#endif
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if _MSC_VER<1500
|
||||||
|
#define for if (0) ; else for
|
||||||
|
#endif
|
||||||
|
#include <direct.h>
|
||||||
|
#include <intrin.h>
|
||||||
|
|
||||||
|
#define USE_SSE
|
||||||
|
#define SSE_ALIGNMENT 16
|
||||||
|
#else
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SAVE_LINKS
|
||||||
|
|
||||||
|
#define ENABLE_ACCESS
|
||||||
|
|
||||||
|
#define DefConfigName L"rar.ini"
|
||||||
|
#define DefLogName L"rar.log"
|
||||||
|
|
||||||
|
|
||||||
|
#define SPATHDIVIDER L"\\"
|
||||||
|
#define CPATHDIVIDER '\\'
|
||||||
|
#define MASKALL L"*"
|
||||||
|
|
||||||
|
#define READBINARY "rb"
|
||||||
|
#define READTEXT "rt"
|
||||||
|
#define UPDATEBINARY "r+b"
|
||||||
|
#define CREATEBINARY "w+b"
|
||||||
|
#define WRITEBINARY "wb"
|
||||||
|
#define APPENDTEXT "at"
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL)
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define _stdfunction __cdecl
|
||||||
|
#define _forceinline __forceinline
|
||||||
|
#else
|
||||||
|
#define _stdfunction _USERENTRY
|
||||||
|
#define _forceinline inline
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define _stdfunction
|
||||||
|
#define _forceinline inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(_WIN_ALL) || defined(_EMX)
|
||||||
|
|
||||||
|
#ifdef _UNIX
|
||||||
|
|
||||||
|
#define NM 2048
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#if defined(__QNXNTO__)
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
#if defined(RAR_SMP) && defined(__APPLE__)
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#endif
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <utime.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef S_IFLNK
|
||||||
|
#define SAVE_LINKS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux) || defined(__FreeBSD__)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#define USE_LUTIMES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ENABLE_ACCESS
|
||||||
|
|
||||||
|
#define DefConfigName L".rarrc"
|
||||||
|
#define DefLogName L".rarlog"
|
||||||
|
|
||||||
|
|
||||||
|
#define SPATHDIVIDER L"/"
|
||||||
|
#define CPATHDIVIDER '/'
|
||||||
|
#define MASKALL L"*"
|
||||||
|
|
||||||
|
#define READBINARY "r"
|
||||||
|
#define READTEXT "r"
|
||||||
|
#define UPDATEBINARY "r+"
|
||||||
|
#define CREATEBINARY "w+"
|
||||||
|
#define WRITEBINARY "w"
|
||||||
|
#define APPENDTEXT "a"
|
||||||
|
|
||||||
|
#define _stdfunction
|
||||||
|
#define _forceinline inline
|
||||||
|
|
||||||
|
#ifdef _APPLE
|
||||||
|
#if defined(__BIG_ENDIAN__) && !defined(BIG_ENDIAN)
|
||||||
|
#define BIG_ENDIAN
|
||||||
|
#undef LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
#if defined(__i386__) && !defined(LITTLE_ENDIAN)
|
||||||
|
#define LITTLE_ENDIAN
|
||||||
|
#undef BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__sparc) || defined(sparc) || defined(__hpux)
|
||||||
|
#ifndef BIG_ENDIAN
|
||||||
|
#define BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _POSIX_C_SOURCE >= 200809L
|
||||||
|
#define UNIX_TIME_NS // Nanosecond time precision in Unix.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _UNIX
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define MSGID_INT
|
||||||
|
typedef int MSGID;
|
||||||
|
#else
|
||||||
|
typedef const wchar* MSGID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SSE_ALIGNMENT // No SSE use and no special data alignment is required.
|
||||||
|
#define SSE_ALIGNMENT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define safebuf static
|
||||||
|
|
||||||
|
// Solaris defines _LITTLE_ENDIAN or _BIG_ENDIAN.
|
||||||
|
#if defined(_LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN)
|
||||||
|
#define LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
#if defined(_BIG_ENDIAN) && !defined(BIG_ENDIAN)
|
||||||
|
#define BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
|
||||||
|
#if defined(__i386) || defined(i386) || defined(__i386__) || defined(__x86_64)
|
||||||
|
#define LITTLE_ENDIAN
|
||||||
|
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN || defined(__LITTLE_ENDIAN__)
|
||||||
|
#define LITTLE_ENDIAN
|
||||||
|
#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN || defined(__BIG_ENDIAN__)
|
||||||
|
#define BIG_ENDIAN
|
||||||
|
#else
|
||||||
|
#error "Neither LITTLE_ENDIAN nor BIG_ENDIAN are defined. Define one of them."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
|
||||||
|
#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
|
||||||
|
#undef LITTLE_ENDIAN
|
||||||
|
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
#undef BIG_ENDIAN
|
||||||
|
#else
|
||||||
|
#error "Both LITTLE_ENDIAN and BIG_ENDIAN are defined. Undef one of them."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BIG_ENDIAN) && defined(_WIN_ALL) || defined(__i386__) || defined(__x86_64__)
|
||||||
|
// Allow not aligned integer access, increases speed in some operations.
|
||||||
|
#define ALLOW_MISALIGNED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _RAR_OS_
|
1009
deps/unrar/pathfn.cpp
vendored
Normal file
1009
deps/unrar/pathfn.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
76
deps/unrar/pathfn.hpp
vendored
Normal file
76
deps/unrar/pathfn.hpp
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef _RAR_PATHFN_
|
||||||
|
#define _RAR_PATHFN_
|
||||||
|
|
||||||
|
wchar* PointToName(const wchar *Path);
|
||||||
|
wchar* PointToLastChar(const wchar *Path);
|
||||||
|
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize);
|
||||||
|
void SetName(wchar *FullName,const wchar *Name,size_t MaxSize);
|
||||||
|
void SetExt(wchar *Name,const wchar *NewExt,size_t MaxSize);
|
||||||
|
void SetSFXExt(wchar *SFXName,size_t MaxSize);
|
||||||
|
wchar *GetExt(const wchar *Name);
|
||||||
|
bool CmpExt(const wchar *Name,const wchar *Ext);
|
||||||
|
bool IsWildcard(const wchar *Str);
|
||||||
|
bool IsPathDiv(int Ch);
|
||||||
|
bool IsDriveDiv(int Ch);
|
||||||
|
bool IsDriveLetter(const wchar *Path);
|
||||||
|
int GetPathDisk(const wchar *Path);
|
||||||
|
void AddEndSlash(wchar *Path,size_t MaxLength);
|
||||||
|
void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize);
|
||||||
|
void GetFilePath(const wchar *FullName,wchar *Path,size_t MaxLength);
|
||||||
|
void RemoveNameFromPath(wchar *Path);
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
|
bool GetAppDataPath(wchar *Path,size_t MaxSize,bool Create);
|
||||||
|
void GetRarDataPath(wchar *Path,size_t MaxSize,bool Create);
|
||||||
|
#endif
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create);
|
||||||
|
void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckExist,bool Create);
|
||||||
|
#endif
|
||||||
|
wchar* GetVolNumPart(const wchar *ArcName);
|
||||||
|
void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering);
|
||||||
|
bool IsNameUsable(const wchar *Name);
|
||||||
|
void MakeNameUsable(char *Name,bool Extended);
|
||||||
|
void MakeNameUsable(wchar *Name,bool Extended);
|
||||||
|
|
||||||
|
void UnixSlashToDos(const char *SrcName,char *DestName,size_t MaxLength);
|
||||||
|
void DosSlashToUnix(const char *SrcName,char *DestName,size_t MaxLength);
|
||||||
|
void UnixSlashToDos(const wchar *SrcName,wchar *DestName,size_t MaxLength);
|
||||||
|
void DosSlashToUnix(const wchar *SrcName,wchar *DestName,size_t MaxLength);
|
||||||
|
|
||||||
|
inline void SlashToNative(const char *SrcName,char *DestName,size_t MaxLength)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
UnixSlashToDos(SrcName,DestName,MaxLength);
|
||||||
|
#else
|
||||||
|
DosSlashToUnix(SrcName,DestName,MaxLength);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SlashToNative(const wchar *SrcName,wchar *DestName,size_t MaxLength)
|
||||||
|
{
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
UnixSlashToDos(SrcName,DestName,MaxLength);
|
||||||
|
#else
|
||||||
|
DosSlashToUnix(SrcName,DestName,MaxLength);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertNameToFull(const wchar *Src,wchar *Dest,size_t MaxSize);
|
||||||
|
bool IsFullPath(const wchar *Path);
|
||||||
|
bool IsFullRootPath(const wchar *Path);
|
||||||
|
void GetPathRoot(const wchar *Path,wchar *Root,size_t MaxSize);
|
||||||
|
int ParseVersionFileName(wchar *Name,bool Truncate);
|
||||||
|
wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,size_t MaxSize,bool NewNumbering);
|
||||||
|
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize);
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,bool Archiving);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize);
|
||||||
|
void ConvertToPrecomposed(wchar *Name,size_t NameSize);
|
||||||
|
void MakeNameCompatible(wchar *Name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
300
deps/unrar/qopen.cpp
vendored
Normal file
300
deps/unrar/qopen.cpp
vendored
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
QuickOpen::QuickOpen()
|
||||||
|
{
|
||||||
|
Buf=NULL;
|
||||||
|
Init(NULL,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QuickOpen::~QuickOpen()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
delete[] Buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QuickOpen::Init(Archive *Arc,bool WriteMode)
|
||||||
|
{
|
||||||
|
if (Arc!=NULL) // Unless called from constructor.
|
||||||
|
Close();
|
||||||
|
|
||||||
|
QuickOpen::Arc=Arc;
|
||||||
|
QuickOpen::WriteMode=WriteMode;
|
||||||
|
|
||||||
|
ListStart=NULL;
|
||||||
|
ListEnd=NULL;
|
||||||
|
|
||||||
|
if (Buf==NULL)
|
||||||
|
Buf=new byte[MaxBufSize];
|
||||||
|
|
||||||
|
CurBufSize=0; // Current size of buffered data in write mode.
|
||||||
|
|
||||||
|
Loaded=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QuickOpen::Close()
|
||||||
|
{
|
||||||
|
QuickOpenItem *Item=ListStart;
|
||||||
|
while (Item!=NULL)
|
||||||
|
{
|
||||||
|
QuickOpenItem *Next=Item->Next;
|
||||||
|
delete[] Item->Header;
|
||||||
|
delete Item;
|
||||||
|
Item=Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void QuickOpen::Load(uint64 BlockPos)
|
||||||
|
{
|
||||||
|
if (!Loaded)
|
||||||
|
{
|
||||||
|
// If loading for the first time, perform additional intialization.
|
||||||
|
SeekPos=Arc->Tell();
|
||||||
|
UnsyncSeekPos=false;
|
||||||
|
|
||||||
|
int64 SavePos=SeekPos;
|
||||||
|
Arc->Seek(BlockPos,SEEK_SET);
|
||||||
|
|
||||||
|
// If BlockPos points to original main header, we'll have the infinite
|
||||||
|
// recursion, because ReadHeader() for main header will attempt to load
|
||||||
|
// QOpen and call QuickOpen::Load again. If BlockPos points to long chain
|
||||||
|
// of other main headers, we'll have multiple recursive calls of this
|
||||||
|
// function wasting resources. So we prohibit QOpen temporarily to
|
||||||
|
// prevent this. ReadHeader() calls QOpen.Init and sets MainHead Locator
|
||||||
|
// and QOpenOffset fields, so we cannot use them to prohibit QOpen.
|
||||||
|
Arc->SetProhibitQOpen(true);
|
||||||
|
size_t ReadSize=Arc->ReadHeader();
|
||||||
|
Arc->SetProhibitQOpen(false);
|
||||||
|
|
||||||
|
if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||
|
||||||
|
!Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN))
|
||||||
|
{
|
||||||
|
Arc->Seek(SavePos,SEEK_SET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QOHeaderPos=Arc->CurBlockPos;
|
||||||
|
RawDataStart=Arc->Tell();
|
||||||
|
RawDataSize=Arc->SubHead.UnpSize;
|
||||||
|
Arc->Seek(SavePos,SEEK_SET);
|
||||||
|
|
||||||
|
Loaded=true; // Set only after all file processing calls like Tell, Seek, ReadHeader.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Arc->SubHead.Encrypted)
|
||||||
|
{
|
||||||
|
RAROptions *Cmd=Arc->GetRAROptions();
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
if (Cmd->Password.IsSet())
|
||||||
|
Crypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,Arc->SubHead.Salt,
|
||||||
|
Arc->SubHead.InitV,Arc->SubHead.Lg2Count,
|
||||||
|
Arc->SubHead.HashKey,Arc->SubHead.PswCheck);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Loaded=false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RawDataPos=0;
|
||||||
|
ReadBufSize=0;
|
||||||
|
ReadBufPos=0;
|
||||||
|
LastReadHeader.Reset();
|
||||||
|
LastReadHeaderPos=0;
|
||||||
|
|
||||||
|
ReadBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool QuickOpen::Read(void *Data,size_t Size,size_t &Result)
|
||||||
|
{
|
||||||
|
if (!Loaded)
|
||||||
|
return false;
|
||||||
|
// Find next suitable cached block.
|
||||||
|
while (LastReadHeaderPos+LastReadHeader.Size()<=SeekPos)
|
||||||
|
if (!ReadNext())
|
||||||
|
break;
|
||||||
|
if (!Loaded)
|
||||||
|
{
|
||||||
|
// If something wrong happened, let's set the correct file pointer
|
||||||
|
// and stop further quick open processing.
|
||||||
|
if (UnsyncSeekPos)
|
||||||
|
Arc->File::Seek(SeekPos,SEEK_SET);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SeekPos>=LastReadHeaderPos && SeekPos+Size<=LastReadHeaderPos+LastReadHeader.Size())
|
||||||
|
{
|
||||||
|
memcpy(Data,LastReadHeader+size_t(SeekPos-LastReadHeaderPos),Size);
|
||||||
|
Result=Size;
|
||||||
|
SeekPos+=Size;
|
||||||
|
UnsyncSeekPos=true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (UnsyncSeekPos)
|
||||||
|
{
|
||||||
|
Arc->File::Seek(SeekPos,SEEK_SET);
|
||||||
|
UnsyncSeekPos=false;
|
||||||
|
}
|
||||||
|
int ReadSize=Arc->File::Read(Data,Size);
|
||||||
|
if (ReadSize<0)
|
||||||
|
{
|
||||||
|
Loaded=false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Result=ReadSize;
|
||||||
|
SeekPos+=ReadSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool QuickOpen::Seek(int64 Offset,int Method)
|
||||||
|
{
|
||||||
|
if (!Loaded)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Normally we process an archive sequentially from beginning to end,
|
||||||
|
// so we read quick open data sequentially. But some operations like
|
||||||
|
// archive updating involve several passes. So if we detect that file
|
||||||
|
// pointer is moved back, we reload quick open data from beginning.
|
||||||
|
if (Method==SEEK_SET && (uint64)Offset<SeekPos && (uint64)Offset<LastReadHeaderPos)
|
||||||
|
Load(QOHeaderPos);
|
||||||
|
|
||||||
|
if (Method==SEEK_SET)
|
||||||
|
SeekPos=Offset;
|
||||||
|
if (Method==SEEK_CUR)
|
||||||
|
SeekPos+=Offset;
|
||||||
|
UnsyncSeekPos=true;
|
||||||
|
|
||||||
|
if (Method==SEEK_END)
|
||||||
|
{
|
||||||
|
Arc->File::Seek(Offset,SEEK_END);
|
||||||
|
SeekPos=Arc->File::Tell();
|
||||||
|
UnsyncSeekPos=false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool QuickOpen::Tell(int64 *Pos)
|
||||||
|
{
|
||||||
|
if (!Loaded)
|
||||||
|
return false;
|
||||||
|
*Pos=SeekPos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint QuickOpen::ReadBuffer()
|
||||||
|
{
|
||||||
|
int64 SavePos=Arc->Tell();
|
||||||
|
Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET);
|
||||||
|
size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize);
|
||||||
|
if (Arc->SubHead.Encrypted)
|
||||||
|
SizeToRead &= ~CRYPT_BLOCK_MASK;
|
||||||
|
int ReadSize=0;
|
||||||
|
if (SizeToRead!=0)
|
||||||
|
{
|
||||||
|
ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
|
||||||
|
if (ReadSize<=0)
|
||||||
|
ReadSize=0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
if (Arc->SubHead.Encrypted)
|
||||||
|
Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
|
||||||
|
#endif
|
||||||
|
RawDataPos+=ReadSize;
|
||||||
|
ReadBufSize+=ReadSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arc->Seek(SavePos,SEEK_SET);
|
||||||
|
return ReadSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fill RawRead object from buffer.
|
||||||
|
bool QuickOpen::ReadRaw(RawRead &Raw)
|
||||||
|
{
|
||||||
|
if (MaxBufSize-ReadBufPos<0x100) // We are close to end of buffer.
|
||||||
|
{
|
||||||
|
// Ensure that we have enough data to read CRC and header size.
|
||||||
|
size_t DataLeft=ReadBufSize-ReadBufPos;
|
||||||
|
memcpy(Buf,Buf+ReadBufPos,DataLeft);
|
||||||
|
ReadBufPos=0;
|
||||||
|
ReadBufSize=DataLeft;
|
||||||
|
ReadBuffer();
|
||||||
|
}
|
||||||
|
const size_t FirstReadSize=7;
|
||||||
|
if (ReadBufPos+FirstReadSize>ReadBufSize)
|
||||||
|
return false;
|
||||||
|
Raw.Read(Buf+ReadBufPos,FirstReadSize);
|
||||||
|
ReadBufPos+=FirstReadSize;
|
||||||
|
|
||||||
|
uint SavedCRC=Raw.Get4();
|
||||||
|
uint SizeBytes=Raw.GetVSize(4);
|
||||||
|
uint64 BlockSize=Raw.GetV();
|
||||||
|
int SizeToRead=int(BlockSize);
|
||||||
|
SizeToRead-=FirstReadSize-SizeBytes-4; // Adjust overread size bytes if any.
|
||||||
|
if (SizeToRead<0 || SizeBytes==0 || BlockSize==0)
|
||||||
|
{
|
||||||
|
Loaded=false; // Invalid data.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If rest of block data crosses Buf boundary, read it in loop.
|
||||||
|
while (SizeToRead>0)
|
||||||
|
{
|
||||||
|
size_t DataLeft=ReadBufSize-ReadBufPos;
|
||||||
|
size_t CurSizeToRead=Min(DataLeft,(size_t)SizeToRead);
|
||||||
|
Raw.Read(Buf+ReadBufPos,CurSizeToRead);
|
||||||
|
ReadBufPos+=CurSizeToRead;
|
||||||
|
SizeToRead-=int(CurSizeToRead);
|
||||||
|
if (SizeToRead>0) // We read the entire buffer and still need more data.
|
||||||
|
{
|
||||||
|
ReadBufPos=0;
|
||||||
|
ReadBufSize=0;
|
||||||
|
if (ReadBuffer()==0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SavedCRC==Raw.GetCRC50();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read next cached header.
|
||||||
|
bool QuickOpen::ReadNext()
|
||||||
|
{
|
||||||
|
RawRead Raw(NULL);
|
||||||
|
if (!ReadRaw(Raw)) // Read internal quick open header preceding stored block.
|
||||||
|
return false;
|
||||||
|
uint Flags=(uint)Raw.GetV();
|
||||||
|
uint64 Offset=Raw.GetV();
|
||||||
|
size_t HeaderSize=(size_t)Raw.GetV();
|
||||||
|
if (HeaderSize>MAX_HEADER_SIZE_RAR5)
|
||||||
|
return false;
|
||||||
|
LastReadHeader.Alloc(HeaderSize);
|
||||||
|
Raw.GetB(&LastReadHeader[0],HeaderSize);
|
||||||
|
// Calculate the absolute position as offset from quick open service header.
|
||||||
|
LastReadHeaderPos=QOHeaderPos-Offset;
|
||||||
|
return true;
|
||||||
|
}
|
61
deps/unrar/qopen.hpp
vendored
Normal file
61
deps/unrar/qopen.hpp
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef _RAR_QOPEN_
|
||||||
|
#define _RAR_QOPEN_
|
||||||
|
|
||||||
|
struct QuickOpenItem
|
||||||
|
{
|
||||||
|
byte *Header;
|
||||||
|
size_t HeaderSize;
|
||||||
|
uint64 ArcPos;
|
||||||
|
QuickOpenItem *Next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Archive;
|
||||||
|
class RawRead;
|
||||||
|
|
||||||
|
class QuickOpen
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
|
||||||
|
uint ReadBuffer();
|
||||||
|
bool ReadRaw(RawRead &Raw);
|
||||||
|
bool ReadNext();
|
||||||
|
|
||||||
|
Archive *Arc;
|
||||||
|
bool WriteMode;
|
||||||
|
|
||||||
|
QuickOpenItem *ListStart;
|
||||||
|
QuickOpenItem *ListEnd;
|
||||||
|
|
||||||
|
byte *Buf; // Read quick open data here.
|
||||||
|
static const size_t MaxBufSize=0x10000; // Buf size, must be multiple of CRYPT_BLOCK_SIZE.
|
||||||
|
size_t CurBufSize; // Current size of buffered data in write mode.
|
||||||
|
#ifndef RAR_NOCRYPT // For shell extension.
|
||||||
|
CryptData Crypt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Loaded;
|
||||||
|
uint64 QOHeaderPos; // Main QO header position.
|
||||||
|
uint64 RawDataStart; // Start of QO data, just after the main header.
|
||||||
|
uint64 RawDataSize; // Size of entire QO data.
|
||||||
|
uint64 RawDataPos; // Current read position in QO data.
|
||||||
|
size_t ReadBufSize; // Size of Buf data currently read from QO.
|
||||||
|
size_t ReadBufPos; // Current read position in Buf data.
|
||||||
|
Array<byte> LastReadHeader;
|
||||||
|
uint64 LastReadHeaderPos;
|
||||||
|
uint64 SeekPos;
|
||||||
|
bool UnsyncSeekPos; // QOpen SeekPos does not match an actual file pointer.
|
||||||
|
public:
|
||||||
|
QuickOpen();
|
||||||
|
~QuickOpen();
|
||||||
|
void Init(Archive *Arc,bool WriteMode);
|
||||||
|
void Load(uint64 BlockPos);
|
||||||
|
void Unload() { Loaded=false; }
|
||||||
|
bool Read(void *Data,size_t Size,size_t &Result);
|
||||||
|
bool Seek(int64 Offset,int Method);
|
||||||
|
bool Tell(int64 *Pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
107
deps/unrar/rar.cpp
vendored
Normal file
107
deps/unrar/rar.cpp
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#if !defined(RARDLL)
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _UNIX
|
||||||
|
setlocale(LC_ALL,"");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitConsole();
|
||||||
|
ErrHandler.SetSignalHandlers(true);
|
||||||
|
|
||||||
|
#ifdef SFX_MODULE
|
||||||
|
wchar ModuleName[NM];
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
GetModuleFileName(NULL,ModuleName,ASIZE(ModuleName));
|
||||||
|
#else
|
||||||
|
CharToWide(argv[0],ModuleName,ASIZE(ModuleName));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
|
// Must be initialized, normal initialization can be skipped in case of
|
||||||
|
// exception.
|
||||||
|
POWER_MODE ShutdownOnClose=POWERMODE_KEEP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
CommandData *Cmd=new CommandData;
|
||||||
|
#ifdef SFX_MODULE
|
||||||
|
wcsncpyz(Cmd->Command,L"X",ASIZE(Cmd->Command));
|
||||||
|
char *Switch=argc>1 ? argv[1]:NULL;
|
||||||
|
if (Switch!=NULL && Cmd->IsSwitch(Switch[0]))
|
||||||
|
{
|
||||||
|
int UpperCmd=etoupper(Switch[1]);
|
||||||
|
switch(UpperCmd)
|
||||||
|
{
|
||||||
|
case 'T':
|
||||||
|
case 'V':
|
||||||
|
Cmd->Command[0]=UpperCmd;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
Cmd->OutHelp(RARX_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cmd->AddArcName(ModuleName);
|
||||||
|
Cmd->ParseDone();
|
||||||
|
Cmd->AbsoluteLinks=true; // If users runs SFX, he trusts an archive source.
|
||||||
|
#else // !SFX_MODULE
|
||||||
|
Cmd->ParseCommandLine(true,argc,argv);
|
||||||
|
if (!Cmd->ConfigDisabled)
|
||||||
|
{
|
||||||
|
Cmd->ReadConfig();
|
||||||
|
Cmd->ParseEnvVar();
|
||||||
|
}
|
||||||
|
Cmd->ParseCommandLine(false,argc,argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
|
ShutdownOnClose=Cmd->Shutdown;
|
||||||
|
if (ShutdownOnClose)
|
||||||
|
ShutdownCheckAnother(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uiInit(Cmd->Sound);
|
||||||
|
InitLogOptions(Cmd->LogName,Cmd->ErrlogCharset);
|
||||||
|
ErrHandler.SetSilent(Cmd->AllYes || Cmd->MsgStream==MSG_NULL);
|
||||||
|
|
||||||
|
Cmd->OutTitle();
|
||||||
|
Cmd->ProcessCommand();
|
||||||
|
delete Cmd;
|
||||||
|
}
|
||||||
|
catch (RAR_EXIT ErrCode)
|
||||||
|
{
|
||||||
|
ErrHandler.SetErrorCode(ErrCode);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
ErrHandler.MemoryErrorMsg();
|
||||||
|
ErrHandler.SetErrorCode(RARX_MEMORY);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
ErrHandler.SetErrorCode(RARX_FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
|
if (ShutdownOnClose!=POWERMODE_KEEP && ErrHandler.IsShutdownEnabled() &&
|
||||||
|
!ShutdownCheckAnother(false))
|
||||||
|
Shutdown(ShutdownOnClose);
|
||||||
|
#endif
|
||||||
|
ErrHandler.MainExit=true;
|
||||||
|
return ErrHandler.GetErrorCode();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
96
deps/unrar/rar.hpp
vendored
Normal file
96
deps/unrar/rar.hpp
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#ifndef _RAR_RARCOMMON_
|
||||||
|
#define _RAR_RARCOMMON_
|
||||||
|
|
||||||
|
#include "raros.hpp"
|
||||||
|
#include "rartypes.hpp"
|
||||||
|
#include "os.hpp"
|
||||||
|
|
||||||
|
#ifdef RARDLL
|
||||||
|
#include "dll.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "version.hpp"
|
||||||
|
#include "rardefs.hpp"
|
||||||
|
#include "rarlang.hpp"
|
||||||
|
#include "unicode.hpp"
|
||||||
|
#include "errhnd.hpp"
|
||||||
|
#include "secpassword.hpp"
|
||||||
|
#include "array.hpp"
|
||||||
|
#include "timefn.hpp"
|
||||||
|
#include "sha1.hpp"
|
||||||
|
#include "sha256.hpp"
|
||||||
|
#include "blake2s.hpp"
|
||||||
|
#include "hash.hpp"
|
||||||
|
#include "options.hpp"
|
||||||
|
#include "rijndael.hpp"
|
||||||
|
#include "crypt.hpp"
|
||||||
|
#include "headers5.hpp"
|
||||||
|
#include "headers.hpp"
|
||||||
|
#include "pathfn.hpp"
|
||||||
|
#include "strfn.hpp"
|
||||||
|
#include "strlist.hpp"
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
#include "isnt.hpp"
|
||||||
|
#endif
|
||||||
|
#include "file.hpp"
|
||||||
|
#include "crc.hpp"
|
||||||
|
#include "ui.hpp"
|
||||||
|
#include "filefn.hpp"
|
||||||
|
#include "filestr.hpp"
|
||||||
|
#include "find.hpp"
|
||||||
|
#include "scantree.hpp"
|
||||||
|
#include "getbits.hpp"
|
||||||
|
#include "rdwrfn.hpp"
|
||||||
|
#ifdef USE_QOPEN
|
||||||
|
#include "qopen.hpp"
|
||||||
|
#endif
|
||||||
|
#include "archive.hpp"
|
||||||
|
#include "match.hpp"
|
||||||
|
#include "cmddata.hpp"
|
||||||
|
#include "filcreat.hpp"
|
||||||
|
#include "consio.hpp"
|
||||||
|
#include "system.hpp"
|
||||||
|
#include "log.hpp"
|
||||||
|
#include "rawint.hpp"
|
||||||
|
#include "rawread.hpp"
|
||||||
|
#include "encname.hpp"
|
||||||
|
#include "resource.hpp"
|
||||||
|
#include "compress.hpp"
|
||||||
|
|
||||||
|
#include "rarvm.hpp"
|
||||||
|
#include "model.hpp"
|
||||||
|
|
||||||
|
#include "threadpool.hpp"
|
||||||
|
|
||||||
|
#include "unpack.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "extinfo.hpp"
|
||||||
|
#include "extract.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "list.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "rs.hpp"
|
||||||
|
#include "rs16.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "recvol.hpp"
|
||||||
|
#include "volume.hpp"
|
||||||
|
#include "smallfn.hpp"
|
||||||
|
|
||||||
|
#include "global.hpp"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include "benchmark.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
31
deps/unrar/rardefs.hpp
vendored
Normal file
31
deps/unrar/rardefs.hpp
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef _RAR_DEFS_
|
||||||
|
#define _RAR_DEFS_
|
||||||
|
|
||||||
|
#define Min(x,y) (((x)<(y)) ? (x):(y))
|
||||||
|
#define Max(x,y) (((x)>(y)) ? (x):(y))
|
||||||
|
|
||||||
|
// Universal replacement of abs function.
|
||||||
|
#define Abs(x) (((x)<0) ? -(x):(x))
|
||||||
|
|
||||||
|
#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
|
||||||
|
// MAXPASSWORD is expected to be multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE (16)
|
||||||
|
// for CryptProtectMemory in SecPassword.
|
||||||
|
#define MAXPASSWORD 128
|
||||||
|
|
||||||
|
#define MAXSFXSIZE 0x200000
|
||||||
|
|
||||||
|
#define MAXCMTSIZE 0x40000
|
||||||
|
|
||||||
|
#define DefSFXName L"default.sfx"
|
||||||
|
#define DefSortListName L"rarfiles.lst"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SFX_MODULE
|
||||||
|
#define USE_QOPEN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Produce the value, which is equal or larger than 'v' and aligned to 'a'.
|
||||||
|
#define ALIGN_VALUE(v,a) (size_t(v) + ( (~size_t(v) + 1) & (a - 1) ) )
|
||||||
|
|
||||||
|
#endif
|
10
deps/unrar/rarlang.hpp
vendored
Normal file
10
deps/unrar/rarlang.hpp
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _RAR_LANG_
|
||||||
|
#define _RAR_LANG_
|
||||||
|
|
||||||
|
#ifdef USE_RC
|
||||||
|
#include "rarres.hpp"
|
||||||
|
#else
|
||||||
|
#include "loclang.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
36
deps/unrar/raros.hpp
vendored
Normal file
36
deps/unrar/raros.hpp
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef _RAR_RAROS_
|
||||||
|
#define _RAR_RAROS_
|
||||||
|
|
||||||
|
#ifdef __EMX__
|
||||||
|
#define _EMX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DJGPP__
|
||||||
|
#define _DJGPP
|
||||||
|
#define _EMX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__WIN32__) || defined(_WIN32)
|
||||||
|
#define _WIN_ALL // Defined for all Windows platforms, 32 and 64 bit, mobile and desktop.
|
||||||
|
#ifdef _M_X64
|
||||||
|
#define _WIN_64
|
||||||
|
#else
|
||||||
|
#define _WIN_32
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ANDROID) || defined(__ANDROID__)
|
||||||
|
#define _UNIX
|
||||||
|
#define _ANDROID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define _UNIX
|
||||||
|
#define _APPLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_EMX) && !defined(_WIN_ALL) && !defined(_BEOS) && !defined(_APPLE)
|
||||||
|
#define _UNIX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
2
deps/unrar/rarpch.cpp
vendored
Normal file
2
deps/unrar/rarpch.cpp
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// We use rarpch.cpp to create precompiled headers for MS Visual C++.
|
||||||
|
#include "rar.hpp"
|
32
deps/unrar/rartypes.hpp
vendored
Normal file
32
deps/unrar/rartypes.hpp
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef _RAR_TYPES_
|
||||||
|
#define _RAR_TYPES_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint8_t byte; // Unsigned 8 bits.
|
||||||
|
typedef uint16_t ushort; // Preferably 16 bits, but can be more.
|
||||||
|
typedef unsigned int uint; // 32 bits or more.
|
||||||
|
typedef uint32_t uint32; // 32 bits exactly.
|
||||||
|
typedef int32_t int32; // Signed 32 bits exactly.
|
||||||
|
typedef uint64_t uint64; // 64 bits exactly.
|
||||||
|
typedef int64_t int64; // Signed 64 bits exactly.
|
||||||
|
typedef wchar_t wchar; // Unicode character
|
||||||
|
|
||||||
|
// Get lowest 16 bits.
|
||||||
|
#define GET_SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
|
||||||
|
|
||||||
|
// Make 64 bit integer from two 32 bit.
|
||||||
|
#define INT32TO64(high,low) ((((uint64)(high))<<32)+((uint64)low))
|
||||||
|
|
||||||
|
// Maximum int64 value.
|
||||||
|
#define MAX_INT64 int64(INT32TO64(0x7fffffff,0xffffffff))
|
||||||
|
|
||||||
|
// Special int64 value, large enough to never be found in real life
|
||||||
|
// and small enough to fit to both signed and unsigned 64-bit ints.
|
||||||
|
// We use it in situations, when we need to indicate that parameter
|
||||||
|
// is not defined and probably should be calculated inside of function.
|
||||||
|
// Lower part is intentionally 0x7fffffff, not 0xffffffff, to make it
|
||||||
|
// compatible with 32 bit int64 if 64 bit type is not supported.
|
||||||
|
#define INT64NDF INT32TO64(0x7fffffff,0x7fffffff)
|
||||||
|
|
||||||
|
#endif
|
364
deps/unrar/rarvm.cpp
vendored
Normal file
364
deps/unrar/rarvm.cpp
vendored
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
RarVM::RarVM()
|
||||||
|
{
|
||||||
|
Mem=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RarVM::~RarVM()
|
||||||
|
{
|
||||||
|
delete[] Mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RarVM::Init()
|
||||||
|
{
|
||||||
|
if (Mem==NULL)
|
||||||
|
Mem=new byte[VM_MEMSIZE+4];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RarVM::Execute(VM_PreparedProgram *Prg)
|
||||||
|
{
|
||||||
|
memcpy(R,Prg->InitR,sizeof(Prg->InitR));
|
||||||
|
Prg->FilteredData=NULL;
|
||||||
|
if (Prg->Type!=VMSF_NONE)
|
||||||
|
{
|
||||||
|
bool Success=ExecuteStandardFilter(Prg->Type);
|
||||||
|
uint BlockSize=Prg->InitR[4] & VM_MEMMASK;
|
||||||
|
Prg->FilteredDataSize=BlockSize;
|
||||||
|
if (Prg->Type==VMSF_DELTA || Prg->Type==VMSF_RGB || Prg->Type==VMSF_AUDIO)
|
||||||
|
Prg->FilteredData=2*BlockSize>VM_MEMSIZE || !Success ? Mem:Mem+BlockSize;
|
||||||
|
else
|
||||||
|
Prg->FilteredData=Mem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RarVM::Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg)
|
||||||
|
{
|
||||||
|
// Calculate the single byte XOR checksum to check validity of VM code.
|
||||||
|
byte XorSum=0;
|
||||||
|
for (uint I=1;I<CodeSize;I++)
|
||||||
|
XorSum^=Code[I];
|
||||||
|
|
||||||
|
if (XorSum!=Code[0])
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct StandardFilters
|
||||||
|
{
|
||||||
|
uint Length;
|
||||||
|
uint CRC;
|
||||||
|
VM_StandardFilters Type;
|
||||||
|
} static StdList[]={
|
||||||
|
53, 0xad576887, VMSF_E8,
|
||||||
|
57, 0x3cd7e57e, VMSF_E8E9,
|
||||||
|
120, 0x3769893f, VMSF_ITANIUM,
|
||||||
|
29, 0x0e06077d, VMSF_DELTA,
|
||||||
|
149, 0x1c2c5dc8, VMSF_RGB,
|
||||||
|
216, 0xbc85e701, VMSF_AUDIO
|
||||||
|
};
|
||||||
|
uint CodeCRC=CRC32(0xffffffff,Code,CodeSize)^0xffffffff;
|
||||||
|
for (uint I=0;I<ASIZE(StdList);I++)
|
||||||
|
if (StdList[I].CRC==CodeCRC && StdList[I].Length==CodeSize)
|
||||||
|
{
|
||||||
|
Prg->Type=StdList[I].Type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint RarVM::ReadData(BitInput &Inp)
|
||||||
|
{
|
||||||
|
uint Data=Inp.fgetbits();
|
||||||
|
switch(Data&0xc000)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Inp.faddbits(6);
|
||||||
|
return (Data>>10)&0xf;
|
||||||
|
case 0x4000:
|
||||||
|
if ((Data&0x3c00)==0)
|
||||||
|
{
|
||||||
|
Data=0xffffff00|((Data>>2)&0xff);
|
||||||
|
Inp.faddbits(14);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Data=(Data>>6)&0xff;
|
||||||
|
Inp.faddbits(10);
|
||||||
|
}
|
||||||
|
return Data;
|
||||||
|
case 0x8000:
|
||||||
|
Inp.faddbits(2);
|
||||||
|
Data=Inp.fgetbits();
|
||||||
|
Inp.faddbits(16);
|
||||||
|
return Data;
|
||||||
|
default:
|
||||||
|
Inp.faddbits(2);
|
||||||
|
Data=(Inp.fgetbits()<<16);
|
||||||
|
Inp.faddbits(16);
|
||||||
|
Data|=Inp.fgetbits();
|
||||||
|
Inp.faddbits(16);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RarVM::SetMemory(size_t Pos,byte *Data,size_t DataSize)
|
||||||
|
{
|
||||||
|
if (Pos<VM_MEMSIZE && Data!=Mem+Pos)
|
||||||
|
{
|
||||||
|
// We can have NULL Data for invalid filters with DataSize==0. While most
|
||||||
|
// sensible memmove implementations do not care about data if size is 0,
|
||||||
|
// let's follow the standard and check the size first.
|
||||||
|
size_t CopySize=Min(DataSize,VM_MEMSIZE-Pos);
|
||||||
|
if (CopySize!=0)
|
||||||
|
memmove(Mem+Pos,Data,CopySize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
||||||
|
{
|
||||||
|
switch(FilterType)
|
||||||
|
{
|
||||||
|
case VMSF_E8:
|
||||||
|
case VMSF_E8E9:
|
||||||
|
{
|
||||||
|
byte *Data=Mem;
|
||||||
|
uint DataSize=R[4],FileOffset=R[6];
|
||||||
|
|
||||||
|
if (DataSize>VM_MEMSIZE || DataSize<4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const uint FileSize=0x1000000;
|
||||||
|
byte CmpByte2=FilterType==VMSF_E8E9 ? 0xe9:0xe8;
|
||||||
|
for (uint CurPos=0;CurPos<DataSize-4;)
|
||||||
|
{
|
||||||
|
byte CurByte=*(Data++);
|
||||||
|
CurPos++;
|
||||||
|
if (CurByte==0xe8 || CurByte==CmpByte2)
|
||||||
|
{
|
||||||
|
uint Offset=CurPos+FileOffset;
|
||||||
|
uint Addr=RawGet4(Data);
|
||||||
|
|
||||||
|
// We check 0x80000000 bit instead of '< 0' comparison
|
||||||
|
// not assuming int32 presence or uint size and endianness.
|
||||||
|
if ((Addr & 0x80000000)!=0) // Addr<0
|
||||||
|
{
|
||||||
|
if (((Addr+Offset) & 0x80000000)==0) // Addr+Offset>=0
|
||||||
|
RawPut4(Addr+FileSize,Data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (((Addr-FileSize) & 0x80000000)!=0) // Addr<FileSize
|
||||||
|
RawPut4(Addr-Offset,Data);
|
||||||
|
Data+=4;
|
||||||
|
CurPos+=4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VMSF_ITANIUM:
|
||||||
|
{
|
||||||
|
byte *Data=Mem;
|
||||||
|
uint DataSize=R[4],FileOffset=R[6];
|
||||||
|
|
||||||
|
if (DataSize>VM_MEMSIZE || DataSize<21)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint CurPos=0;
|
||||||
|
|
||||||
|
FileOffset>>=4;
|
||||||
|
|
||||||
|
while (CurPos<DataSize-21)
|
||||||
|
{
|
||||||
|
int Byte=(Data[0]&0x1f)-0x10;
|
||||||
|
if (Byte>=0)
|
||||||
|
{
|
||||||
|
static byte Masks[16]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
|
||||||
|
byte CmdMask=Masks[Byte];
|
||||||
|
if (CmdMask!=0)
|
||||||
|
for (uint I=0;I<=2;I++)
|
||||||
|
if (CmdMask & (1<<I))
|
||||||
|
{
|
||||||
|
uint StartPos=I*41+5;
|
||||||
|
uint OpType=FilterItanium_GetBits(Data,StartPos+37,4);
|
||||||
|
if (OpType==5)
|
||||||
|
{
|
||||||
|
uint Offset=FilterItanium_GetBits(Data,StartPos+13,20);
|
||||||
|
FilterItanium_SetBits(Data,(Offset-FileOffset)&0xfffff,StartPos+13,20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data+=16;
|
||||||
|
CurPos+=16;
|
||||||
|
FileOffset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VMSF_DELTA:
|
||||||
|
{
|
||||||
|
uint DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
|
||||||
|
if (DataSize>VM_MEMSIZE/2 || Channels>MAX3_UNPACK_CHANNELS || Channels==0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Bytes from same channels are grouped to continual data blocks,
|
||||||
|
// so we need to place them back to their interleaving positions.
|
||||||
|
for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
|
||||||
|
{
|
||||||
|
byte PrevByte=0;
|
||||||
|
for (uint DestPos=DataSize+CurChannel;DestPos<Border;DestPos+=Channels)
|
||||||
|
Mem[DestPos]=(PrevByte-=Mem[SrcPos++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VMSF_RGB:
|
||||||
|
{
|
||||||
|
uint DataSize=R[4],Width=R[0]-3,PosR=R[1];
|
||||||
|
if (DataSize>VM_MEMSIZE/2 || DataSize<3 || Width>DataSize || PosR>2)
|
||||||
|
return false;
|
||||||
|
byte *SrcData=Mem,*DestData=SrcData+DataSize;
|
||||||
|
const uint Channels=3;
|
||||||
|
for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
|
||||||
|
{
|
||||||
|
uint PrevByte=0;
|
||||||
|
|
||||||
|
for (uint I=CurChannel;I<DataSize;I+=Channels)
|
||||||
|
{
|
||||||
|
uint Predicted;
|
||||||
|
if (I>=Width+3)
|
||||||
|
{
|
||||||
|
byte *UpperData=DestData+I-Width;
|
||||||
|
uint UpperByte=*UpperData;
|
||||||
|
uint UpperLeftByte=*(UpperData-3);
|
||||||
|
Predicted=PrevByte+UpperByte-UpperLeftByte;
|
||||||
|
int pa=abs((int)(Predicted-PrevByte));
|
||||||
|
int pb=abs((int)(Predicted-UpperByte));
|
||||||
|
int pc=abs((int)(Predicted-UpperLeftByte));
|
||||||
|
if (pa<=pb && pa<=pc)
|
||||||
|
Predicted=PrevByte;
|
||||||
|
else
|
||||||
|
if (pb<=pc)
|
||||||
|
Predicted=UpperByte;
|
||||||
|
else
|
||||||
|
Predicted=UpperLeftByte;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Predicted=PrevByte;
|
||||||
|
DestData[I]=PrevByte=(byte)(Predicted-*(SrcData++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint I=PosR,Border=DataSize-2;I<Border;I+=3)
|
||||||
|
{
|
||||||
|
byte G=DestData[I+1];
|
||||||
|
DestData[I]+=G;
|
||||||
|
DestData[I+2]+=G;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VMSF_AUDIO:
|
||||||
|
{
|
||||||
|
uint DataSize=R[4],Channels=R[0];
|
||||||
|
byte *SrcData=Mem,*DestData=SrcData+DataSize;
|
||||||
|
// In fact, audio channels never exceed 4.
|
||||||
|
if (DataSize>VM_MEMSIZE/2 || Channels>128 || Channels==0)
|
||||||
|
return false;
|
||||||
|
for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
|
||||||
|
{
|
||||||
|
uint PrevByte=0,PrevDelta=0,Dif[7];
|
||||||
|
int D1=0,D2=0,D3;
|
||||||
|
int K1=0,K2=0,K3=0;
|
||||||
|
memset(Dif,0,sizeof(Dif));
|
||||||
|
|
||||||
|
for (uint I=CurChannel,ByteCount=0;I<DataSize;I+=Channels,ByteCount++)
|
||||||
|
{
|
||||||
|
D3=D2;
|
||||||
|
D2=PrevDelta-D1;
|
||||||
|
D1=PrevDelta;
|
||||||
|
|
||||||
|
uint Predicted=8*PrevByte+K1*D1+K2*D2+K3*D3;
|
||||||
|
Predicted=(Predicted>>3) & 0xff;
|
||||||
|
|
||||||
|
uint CurByte=*(SrcData++);
|
||||||
|
|
||||||
|
Predicted-=CurByte;
|
||||||
|
DestData[I]=Predicted;
|
||||||
|
PrevDelta=(signed char)(Predicted-PrevByte);
|
||||||
|
PrevByte=Predicted;
|
||||||
|
|
||||||
|
int D=(signed char)CurByte;
|
||||||
|
// Left shift of negative value is undefined behavior in C++,
|
||||||
|
// so we cast it to unsigned to follow the standard.
|
||||||
|
D=(uint)D<<3;
|
||||||
|
|
||||||
|
Dif[0]+=abs(D);
|
||||||
|
Dif[1]+=abs(D-D1);
|
||||||
|
Dif[2]+=abs(D+D1);
|
||||||
|
Dif[3]+=abs(D-D2);
|
||||||
|
Dif[4]+=abs(D+D2);
|
||||||
|
Dif[5]+=abs(D-D3);
|
||||||
|
Dif[6]+=abs(D+D3);
|
||||||
|
|
||||||
|
if ((ByteCount & 0x1f)==0)
|
||||||
|
{
|
||||||
|
uint MinDif=Dif[0],NumMinDif=0;
|
||||||
|
Dif[0]=0;
|
||||||
|
for (uint J=1;J<ASIZE(Dif);J++)
|
||||||
|
{
|
||||||
|
if (Dif[J]<MinDif)
|
||||||
|
{
|
||||||
|
MinDif=Dif[J];
|
||||||
|
NumMinDif=J;
|
||||||
|
}
|
||||||
|
Dif[J]=0;
|
||||||
|
}
|
||||||
|
switch(NumMinDif)
|
||||||
|
{
|
||||||
|
case 1: if (K1>=-16) K1--; break;
|
||||||
|
case 2: if (K1 < 16) K1++; break;
|
||||||
|
case 3: if (K2>=-16) K2--; break;
|
||||||
|
case 4: if (K2 < 16) K2++; break;
|
||||||
|
case 5: if (K3>=-16) K3--; break;
|
||||||
|
case 6: if (K3 < 16) K3++; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint RarVM::FilterItanium_GetBits(byte *Data,uint BitPos,uint BitCount)
|
||||||
|
{
|
||||||
|
uint InAddr=BitPos/8;
|
||||||
|
uint InBit=BitPos&7;
|
||||||
|
uint BitField=(uint)Data[InAddr++];
|
||||||
|
BitField|=(uint)Data[InAddr++] << 8;
|
||||||
|
BitField|=(uint)Data[InAddr++] << 16;
|
||||||
|
BitField|=(uint)Data[InAddr] << 24;
|
||||||
|
BitField >>= InBit;
|
||||||
|
return BitField & (0xffffffff>>(32-BitCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RarVM::FilterItanium_SetBits(byte *Data,uint BitField,uint BitPos,uint BitCount)
|
||||||
|
{
|
||||||
|
uint InAddr=BitPos/8;
|
||||||
|
uint InBit=BitPos&7;
|
||||||
|
uint AndMask=0xffffffff>>(32-BitCount);
|
||||||
|
AndMask=~(AndMask<<InBit);
|
||||||
|
|
||||||
|
BitField<<=InBit;
|
||||||
|
|
||||||
|
for (uint I=0;I<4;I++)
|
||||||
|
{
|
||||||
|
Data[InAddr+I]&=AndMask;
|
||||||
|
Data[InAddr+I]|=BitField;
|
||||||
|
AndMask=(AndMask>>8)|0xff000000;
|
||||||
|
BitField>>=8;
|
||||||
|
}
|
||||||
|
}
|
44
deps/unrar/rarvm.hpp
vendored
Normal file
44
deps/unrar/rarvm.hpp
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef _RAR_VM_
|
||||||
|
#define _RAR_VM_
|
||||||
|
|
||||||
|
#define VM_MEMSIZE 0x40000
|
||||||
|
#define VM_MEMMASK (VM_MEMSIZE-1)
|
||||||
|
|
||||||
|
enum VM_StandardFilters {
|
||||||
|
VMSF_NONE, VMSF_E8, VMSF_E8E9, VMSF_ITANIUM, VMSF_RGB, VMSF_AUDIO,
|
||||||
|
VMSF_DELTA
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VM_PreparedProgram
|
||||||
|
{
|
||||||
|
VM_PreparedProgram()
|
||||||
|
{
|
||||||
|
FilteredDataSize=0;
|
||||||
|
Type=VMSF_NONE;
|
||||||
|
}
|
||||||
|
VM_StandardFilters Type;
|
||||||
|
uint InitR[7];
|
||||||
|
byte *FilteredData;
|
||||||
|
uint FilteredDataSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RarVM
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool ExecuteStandardFilter(VM_StandardFilters FilterType);
|
||||||
|
uint FilterItanium_GetBits(byte *Data,uint BitPos,uint BitCount);
|
||||||
|
void FilterItanium_SetBits(byte *Data,uint BitField,uint BitPos,uint BitCount);
|
||||||
|
|
||||||
|
byte *Mem;
|
||||||
|
uint R[8];
|
||||||
|
public:
|
||||||
|
RarVM();
|
||||||
|
~RarVM();
|
||||||
|
void Init();
|
||||||
|
void Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg);
|
||||||
|
void Execute(VM_PreparedProgram *Prg);
|
||||||
|
void SetMemory(size_t Pos,byte *Data,size_t DataSize);
|
||||||
|
static uint ReadData(BitInput &Inp);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
122
deps/unrar/rawint.hpp
vendored
Normal file
122
deps/unrar/rawint.hpp
vendored
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#ifndef _RAR_RAWINT_
|
||||||
|
#define _RAR_RAWINT_
|
||||||
|
|
||||||
|
#define rotls(x,n,xsize) (((x)<<(n)) | ((x)>>(xsize-(n))))
|
||||||
|
#define rotrs(x,n,xsize) (((x)>>(n)) | ((x)<<(xsize-(n))))
|
||||||
|
#define rotl32(x,n) rotls(x,n,32)
|
||||||
|
#define rotr32(x,n) rotrs(x,n,32)
|
||||||
|
|
||||||
|
inline uint RawGet2(const void *Data)
|
||||||
|
{
|
||||||
|
byte *D=(byte *)Data;
|
||||||
|
return D[0]+(D[1]<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint32 RawGet4(const void *Data)
|
||||||
|
{
|
||||||
|
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
|
||||||
|
byte *D=(byte *)Data;
|
||||||
|
return D[0]+(D[1]<<8)+(D[2]<<16)+(D[3]<<24);
|
||||||
|
#else
|
||||||
|
return *(uint32 *)Data;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint64 RawGet8(const void *Data)
|
||||||
|
{
|
||||||
|
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
|
||||||
|
byte *D=(byte *)Data;
|
||||||
|
return INT32TO64(RawGet4(D+4),RawGet4(D));
|
||||||
|
#else
|
||||||
|
return *(uint64 *)Data;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RawPut2(uint Field,void *Data)
|
||||||
|
{
|
||||||
|
byte *D=(byte *)Data;
|
||||||
|
D[0]=(byte)(Field);
|
||||||
|
D[1]=(byte)(Field>>8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RawPut4(uint32 Field,void *Data)
|
||||||
|
{
|
||||||
|
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
|
||||||
|
byte *D=(byte *)Data;
|
||||||
|
D[0]=(byte)(Field);
|
||||||
|
D[1]=(byte)(Field>>8);
|
||||||
|
D[2]=(byte)(Field>>16);
|
||||||
|
D[3]=(byte)(Field>>24);
|
||||||
|
#else
|
||||||
|
*(uint32 *)Data=Field;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RawPut8(uint64 Field,void *Data)
|
||||||
|
{
|
||||||
|
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
|
||||||
|
byte *D=(byte *)Data;
|
||||||
|
D[0]=(byte)(Field);
|
||||||
|
D[1]=(byte)(Field>>8);
|
||||||
|
D[2]=(byte)(Field>>16);
|
||||||
|
D[3]=(byte)(Field>>24);
|
||||||
|
D[4]=(byte)(Field>>32);
|
||||||
|
D[5]=(byte)(Field>>40);
|
||||||
|
D[6]=(byte)(Field>>48);
|
||||||
|
D[7]=(byte)(Field>>56);
|
||||||
|
#else
|
||||||
|
*(uint64 *)Data=Field;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LITTLE_ENDIAN) && defined(ALLOW_MISALIGNED)
|
||||||
|
#define USE_MEM_BYTESWAP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Load 4 big endian bytes from memory and return uint32.
|
||||||
|
inline uint32 RawGetBE4(const byte *m)
|
||||||
|
{
|
||||||
|
#if defined(USE_MEM_BYTESWAP) && defined(_MSC_VER)
|
||||||
|
return _byteswap_ulong(*(uint32 *)m);
|
||||||
|
#elif defined(USE_MEM_BYTESWAP) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 2)
|
||||||
|
return __builtin_bswap32(*(uint32 *)m);
|
||||||
|
#else
|
||||||
|
return uint32(m[0]<<24) | uint32(m[1]<<16) | uint32(m[2]<<8) | m[3];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Save integer to memory as big endian.
|
||||||
|
inline void RawPutBE4(uint32 i,byte *mem)
|
||||||
|
{
|
||||||
|
#if defined(USE_MEM_BYTESWAP) && defined(_MSC_VER)
|
||||||
|
*(uint32*)mem = _byteswap_ulong(i);
|
||||||
|
#elif defined(USE_MEM_BYTESWAP) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 2)
|
||||||
|
*(uint32*)mem = __builtin_bswap32(i);
|
||||||
|
#else
|
||||||
|
mem[0]=byte(i>>24);
|
||||||
|
mem[1]=byte(i>>16);
|
||||||
|
mem[2]=byte(i>>8);
|
||||||
|
mem[3]=byte(i);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint32 ByteSwap32(uint32 i)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_ulong(i);
|
||||||
|
#elif (__GNUC__ > 3) && (__GNUC_MINOR__ > 2)
|
||||||
|
return __builtin_bswap32(i);
|
||||||
|
#else
|
||||||
|
return (rotl32(i,24)&0xFF00FF00)|(rotl32(i,8)&0x00FF00FF);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
197
deps/unrar/rawread.cpp
vendored
Normal file
197
deps/unrar/rawread.cpp
vendored
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
RawRead::RawRead()
|
||||||
|
{
|
||||||
|
RawRead::SrcFile=NULL;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RawRead::RawRead(File *SrcFile)
|
||||||
|
{
|
||||||
|
RawRead::SrcFile=SrcFile;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RawRead::Reset()
|
||||||
|
{
|
||||||
|
Data.SoftReset();
|
||||||
|
ReadPos=0;
|
||||||
|
DataSize=0;
|
||||||
|
Crypt=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t RawRead::Read(size_t Size)
|
||||||
|
{
|
||||||
|
size_t ReadSize=0;
|
||||||
|
#if !defined(RAR_NOCRYPT)
|
||||||
|
if (Crypt!=NULL)
|
||||||
|
{
|
||||||
|
// Full size of buffer with already read data including data read
|
||||||
|
// for encryption block alignment.
|
||||||
|
size_t FullSize=Data.Size();
|
||||||
|
|
||||||
|
// Data read for alignment and not processed yet.
|
||||||
|
size_t DataLeft=FullSize-DataSize;
|
||||||
|
|
||||||
|
if (Size>DataLeft) // Need to read more than we already have.
|
||||||
|
{
|
||||||
|
size_t SizeToRead=Size-DataLeft;
|
||||||
|
size_t AlignedReadSize=SizeToRead+((~SizeToRead+1) & CRYPT_BLOCK_MASK);
|
||||||
|
Data.Add(AlignedReadSize);
|
||||||
|
ReadSize=SrcFile->Read(&Data[FullSize],AlignedReadSize);
|
||||||
|
Crypt->DecryptBlock(&Data[FullSize],AlignedReadSize);
|
||||||
|
DataSize+=ReadSize==0 ? 0:Size;
|
||||||
|
}
|
||||||
|
else // Use buffered data, no real read.
|
||||||
|
{
|
||||||
|
ReadSize=Size;
|
||||||
|
DataSize+=Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (Size!=0)
|
||||||
|
{
|
||||||
|
Data.Add(Size);
|
||||||
|
ReadSize=SrcFile->Read(&Data[DataSize],Size);
|
||||||
|
DataSize+=ReadSize;
|
||||||
|
}
|
||||||
|
return ReadSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RawRead::Read(byte *SrcData,size_t Size)
|
||||||
|
{
|
||||||
|
if (Size!=0)
|
||||||
|
{
|
||||||
|
Data.Add(Size);
|
||||||
|
memcpy(&Data[DataSize],SrcData,Size);
|
||||||
|
DataSize+=Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
byte RawRead::Get1()
|
||||||
|
{
|
||||||
|
return ReadPos<DataSize ? Data[ReadPos++]:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ushort RawRead::Get2()
|
||||||
|
{
|
||||||
|
if (ReadPos+1<DataSize)
|
||||||
|
{
|
||||||
|
ushort Result=Data[ReadPos]+(Data[ReadPos+1]<<8);
|
||||||
|
ReadPos+=2;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint RawRead::Get4()
|
||||||
|
{
|
||||||
|
if (ReadPos+3<DataSize)
|
||||||
|
{
|
||||||
|
uint Result=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
|
||||||
|
(Data[ReadPos+3]<<24);
|
||||||
|
ReadPos+=4;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64 RawRead::Get8()
|
||||||
|
{
|
||||||
|
uint Low=Get4(),High=Get4();
|
||||||
|
return INT32TO64(High,Low);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64 RawRead::GetV()
|
||||||
|
{
|
||||||
|
uint64 Result=0;
|
||||||
|
// Need to check Shift<64, because for shift greater than or equal to
|
||||||
|
// the width of the promoted left operand, the behavior is undefined.
|
||||||
|
for (uint Shift=0;ReadPos<DataSize && Shift<64;Shift+=7)
|
||||||
|
{
|
||||||
|
byte CurByte=Data[ReadPos++];
|
||||||
|
Result+=uint64(CurByte & 0x7f)<<Shift;
|
||||||
|
if ((CurByte & 0x80)==0)
|
||||||
|
return Result; // Decoded successfully.
|
||||||
|
}
|
||||||
|
return 0; // Out of buffer border.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Return a number of bytes in current variable length integer.
|
||||||
|
uint RawRead::GetVSize(size_t Pos)
|
||||||
|
{
|
||||||
|
for (size_t CurPos=Pos;CurPos<DataSize;CurPos++)
|
||||||
|
if ((Data[CurPos] & 0x80)==0)
|
||||||
|
return int(CurPos-Pos+1);
|
||||||
|
return 0; // Buffer overflow.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t RawRead::GetB(void *Field,size_t Size)
|
||||||
|
{
|
||||||
|
byte *F=(byte *)Field;
|
||||||
|
size_t CopySize=Min(DataSize-ReadPos,Size);
|
||||||
|
if (CopySize>0)
|
||||||
|
memcpy(F,&Data[ReadPos],CopySize);
|
||||||
|
if (Size>CopySize)
|
||||||
|
memset(F+CopySize,0,Size-CopySize);
|
||||||
|
ReadPos+=CopySize;
|
||||||
|
return CopySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RawRead::GetW(wchar *Field,size_t Size)
|
||||||
|
{
|
||||||
|
if (ReadPos+2*Size-1<DataSize)
|
||||||
|
{
|
||||||
|
RawToWide(&Data[ReadPos],Field,Size);
|
||||||
|
ReadPos+=sizeof(wchar)*Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memset(Field,0,sizeof(wchar)*Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint RawRead::GetCRC15(bool ProcessedOnly) // RAR 1.5 block CRC.
|
||||||
|
{
|
||||||
|
if (DataSize<=2)
|
||||||
|
return 0;
|
||||||
|
uint HeaderCRC=CRC32(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2);
|
||||||
|
return ~HeaderCRC & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint RawRead::GetCRC50() // RAR 5.0 block CRC.
|
||||||
|
{
|
||||||
|
if (DataSize<=4)
|
||||||
|
return 0xffffffff;
|
||||||
|
return CRC32(0xffffffff,&Data[4],DataSize-4) ^ 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read vint from arbitrary byte array.
|
||||||
|
uint64 RawGetV(const byte *Data,uint &ReadPos,uint DataSize,bool &Overflow)
|
||||||
|
{
|
||||||
|
Overflow=false;
|
||||||
|
uint64 Result=0;
|
||||||
|
for (uint Shift=0;ReadPos<DataSize;Shift+=7)
|
||||||
|
{
|
||||||
|
byte CurByte=Data[ReadPos++];
|
||||||
|
Result+=uint64(CurByte & 0x7f)<<Shift;
|
||||||
|
if ((CurByte & 0x80)==0)
|
||||||
|
return Result; // Decoded successfully.
|
||||||
|
}
|
||||||
|
Overflow=true;
|
||||||
|
return 0; // Out of buffer border.
|
||||||
|
}
|
41
deps/unrar/rawread.hpp
vendored
Normal file
41
deps/unrar/rawread.hpp
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef _RAR_RAWREAD_
|
||||||
|
#define _RAR_RAWREAD_
|
||||||
|
|
||||||
|
class RawRead
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Array<byte> Data;
|
||||||
|
File *SrcFile;
|
||||||
|
size_t DataSize;
|
||||||
|
size_t ReadPos;
|
||||||
|
CryptData *Crypt;
|
||||||
|
public:
|
||||||
|
RawRead();
|
||||||
|
RawRead(File *SrcFile);
|
||||||
|
void Reset();
|
||||||
|
size_t Read(size_t Size);
|
||||||
|
void Read(byte *SrcData,size_t Size);
|
||||||
|
byte Get1();
|
||||||
|
ushort Get2();
|
||||||
|
uint Get4();
|
||||||
|
uint64 Get8();
|
||||||
|
uint64 GetV();
|
||||||
|
uint GetVSize(size_t Pos);
|
||||||
|
size_t GetB(void *Field,size_t Size);
|
||||||
|
void GetW(wchar *Field,size_t Size);
|
||||||
|
uint GetCRC15(bool ProcessedOnly);
|
||||||
|
uint GetCRC50();
|
||||||
|
byte* GetDataPtr() {return &Data[0];}
|
||||||
|
size_t Size() {return DataSize;}
|
||||||
|
size_t PaddedSize() {return Data.Size()-DataSize;}
|
||||||
|
size_t DataLeft() {return DataSize-ReadPos;}
|
||||||
|
size_t GetPos() {return ReadPos;}
|
||||||
|
void SetPos(size_t Pos) {ReadPos=Pos;}
|
||||||
|
void Skip(size_t Size) {ReadPos+=Size;}
|
||||||
|
void Rewind() {SetPos(0);}
|
||||||
|
void SetCrypt(CryptData *Crypt) {RawRead::Crypt=Crypt;}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64 RawGetV(const byte *Data,uint &ReadPos,uint DataSize,bool &Overflow);
|
||||||
|
|
||||||
|
#endif
|
321
deps/unrar/rdwrfn.cpp
vendored
Normal file
321
deps/unrar/rdwrfn.cpp
vendored
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
ComprDataIO::ComprDataIO()
|
||||||
|
{
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
Crypt=new CryptData;
|
||||||
|
Decrypt=new CryptData;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ComprDataIO::Init()
|
||||||
|
{
|
||||||
|
UnpackFromMemory=false;
|
||||||
|
UnpackToMemory=false;
|
||||||
|
UnpPackedSize=0;
|
||||||
|
ShowProgress=true;
|
||||||
|
TestMode=false;
|
||||||
|
SkipUnpCRC=false;
|
||||||
|
NoFileHeader=false;
|
||||||
|
PackVolume=false;
|
||||||
|
UnpVolume=false;
|
||||||
|
NextVolumeMissing=false;
|
||||||
|
SrcFile=NULL;
|
||||||
|
DestFile=NULL;
|
||||||
|
UnpWrAddr=NULL;
|
||||||
|
UnpWrSize=0;
|
||||||
|
Command=NULL;
|
||||||
|
Encryption=false;
|
||||||
|
Decryption=false;
|
||||||
|
CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=0;
|
||||||
|
LastPercent=-1;
|
||||||
|
SubHead=NULL;
|
||||||
|
SubHeadPos=NULL;
|
||||||
|
CurrentCommand=0;
|
||||||
|
ProcessedArcSize=TotalArcSize=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ComprDataIO::~ComprDataIO()
|
||||||
|
{
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
delete Crypt;
|
||||||
|
delete Decrypt;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||||
|
{
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
// In case of encryption we need to align read size to encryption
|
||||||
|
// block size. We can do it by simple masking, because unpack read code
|
||||||
|
// always reads more than CRYPT_BLOCK_SIZE, so we do not risk to make it 0.
|
||||||
|
if (Decryption)
|
||||||
|
Count &= ~CRYPT_BLOCK_MASK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int ReadSize=0,TotalRead=0;
|
||||||
|
byte *ReadAddr;
|
||||||
|
ReadAddr=Addr;
|
||||||
|
while (Count > 0)
|
||||||
|
{
|
||||||
|
Archive *SrcArc=(Archive *)SrcFile;
|
||||||
|
|
||||||
|
if (UnpackFromMemory)
|
||||||
|
{
|
||||||
|
memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize);
|
||||||
|
ReadSize=(int)UnpackFromMemorySize;
|
||||||
|
UnpackFromMemorySize=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t SizeToRead=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count;
|
||||||
|
if (SizeToRead > 0)
|
||||||
|
{
|
||||||
|
if (UnpVolume && Decryption && (int64)Count>UnpPackedSize)
|
||||||
|
{
|
||||||
|
// We need aligned blocks for decryption and we want "Keep broken
|
||||||
|
// files" to work efficiently with missing encrypted volumes.
|
||||||
|
// So for last data block in volume we adjust the size to read to
|
||||||
|
// next equal or smaller block producing aligned total block size.
|
||||||
|
// So we'll ask for next volume only when processing few unaligned
|
||||||
|
// bytes left in the end, when most of data is already extracted.
|
||||||
|
size_t NewTotalRead = TotalRead + SizeToRead;
|
||||||
|
size_t Adjust = NewTotalRead - (NewTotalRead & ~CRYPT_BLOCK_MASK);
|
||||||
|
size_t NewSizeToRead = SizeToRead - Adjust;
|
||||||
|
if ((int)NewSizeToRead > 0)
|
||||||
|
SizeToRead = NewSizeToRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SrcFile->IsOpened())
|
||||||
|
return -1;
|
||||||
|
ReadSize=SrcFile->Read(ReadAddr,SizeToRead);
|
||||||
|
FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead;
|
||||||
|
if (!NoFileHeader && hd->SplitAfter)
|
||||||
|
PackedDataHash.Update(ReadAddr,ReadSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CurUnpRead+=ReadSize;
|
||||||
|
TotalRead+=ReadSize;
|
||||||
|
#ifndef NOVOLUME
|
||||||
|
// These variable are not used in NOVOLUME mode, so it is better
|
||||||
|
// to exclude commands below to avoid compiler warnings.
|
||||||
|
ReadAddr+=ReadSize;
|
||||||
|
Count-=ReadSize;
|
||||||
|
#endif
|
||||||
|
UnpPackedSize-=ReadSize;
|
||||||
|
|
||||||
|
// Do not ask for next volume if we read something from current volume.
|
||||||
|
// If next volume is missing, we need to process all data from current
|
||||||
|
// volume before aborting. It helps to recover all possible data
|
||||||
|
// in "Keep broken files" mode. But if we process encrypted data,
|
||||||
|
// we ask for next volume also if we have non-aligned encryption block.
|
||||||
|
// Since we adjust data size for decryption earlier above,
|
||||||
|
// it does not hurt "Keep broken files" mode efficiency.
|
||||||
|
if (UnpVolume && UnpPackedSize == 0 &&
|
||||||
|
(ReadSize==0 || Decryption && (TotalRead & CRYPT_BLOCK_MASK) != 0) )
|
||||||
|
{
|
||||||
|
#ifndef NOVOLUME
|
||||||
|
if (!MergeArchive(*SrcArc,this,true,CurrentCommand))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
NextVolumeMissing=true;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Archive *SrcArc=(Archive *)SrcFile;
|
||||||
|
if (SrcArc!=NULL)
|
||||||
|
ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize);
|
||||||
|
if (ReadSize!=-1)
|
||||||
|
{
|
||||||
|
ReadSize=TotalRead;
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
if (Decryption)
|
||||||
|
Decrypt->DecryptBlock(Addr,ReadSize);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
Wait();
|
||||||
|
return ReadSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
|
||||||
|
// Disable the run time stack check for unrar.dll, so we can manipulate
|
||||||
|
// with ProcessDataProc call type below. Run time check would intercept
|
||||||
|
// a wrong ESP before we restore it.
|
||||||
|
#pragma runtime_checks( "s", off )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef RARDLL
|
||||||
|
RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
|
||||||
|
if (Cmd->DllOpMode!=RAR_SKIP)
|
||||||
|
{
|
||||||
|
if (Cmd->Callback!=NULL &&
|
||||||
|
Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1)
|
||||||
|
ErrHandler.Exit(RARX_USERBREAK);
|
||||||
|
if (Cmd->ProcessDataProc!=NULL)
|
||||||
|
{
|
||||||
|
// Here we preserve ESP value. It is necessary for those developers,
|
||||||
|
// who still define ProcessDataProc callback as "C" type function,
|
||||||
|
// even though in year 2001 we announced in unrar.dll whatsnew.txt
|
||||||
|
// that it will be PASCAL type (for compatibility with Visual Basic).
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#ifndef _WIN_64
|
||||||
|
__asm mov ebx,esp
|
||||||
|
#endif
|
||||||
|
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||||
|
_EBX=_ESP;
|
||||||
|
#endif
|
||||||
|
int RetCode=Cmd->ProcessDataProc(Addr,(int)Count);
|
||||||
|
|
||||||
|
// Restore ESP after ProcessDataProc with wrongly defined calling
|
||||||
|
// convention broken it.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#ifndef _WIN_64
|
||||||
|
__asm mov esp,ebx
|
||||||
|
#endif
|
||||||
|
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||||
|
_ESP=_EBX;
|
||||||
|
#endif
|
||||||
|
if (RetCode==0)
|
||||||
|
ErrHandler.Exit(RARX_USERBREAK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // RARDLL
|
||||||
|
|
||||||
|
UnpWrAddr=Addr;
|
||||||
|
UnpWrSize=Count;
|
||||||
|
if (UnpackToMemory)
|
||||||
|
{
|
||||||
|
if (Count <= UnpackToMemorySize)
|
||||||
|
{
|
||||||
|
memcpy(UnpackToMemoryAddr,Addr,Count);
|
||||||
|
UnpackToMemoryAddr+=Count;
|
||||||
|
UnpackToMemorySize-=Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!TestMode)
|
||||||
|
DestFile->Write(Addr,Count);
|
||||||
|
CurUnpWrite+=Count;
|
||||||
|
if (!SkipUnpCRC)
|
||||||
|
UnpHash.Update(Addr,Count);
|
||||||
|
ShowUnpWrite();
|
||||||
|
Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
|
||||||
|
// Restore the run time stack check for unrar.dll.
|
||||||
|
#pragma runtime_checks( "s", restore )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
|
||||||
|
{
|
||||||
|
if (ShowProgress && SrcFile!=NULL)
|
||||||
|
{
|
||||||
|
if (TotalArcSize!=0)
|
||||||
|
{
|
||||||
|
// important when processing several archives or multivolume archive
|
||||||
|
ArcSize=TotalArcSize;
|
||||||
|
ArcPos+=ProcessedArcSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Archive *SrcArc=(Archive *)SrcFile;
|
||||||
|
RAROptions *Cmd=SrcArc->GetRAROptions();
|
||||||
|
|
||||||
|
int CurPercent=ToPercent(ArcPos,ArcSize);
|
||||||
|
if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
|
||||||
|
{
|
||||||
|
uiExtractProgress(CurUnpWrite,SrcArc->FileHead.UnpSize,ArcPos,ArcSize);
|
||||||
|
LastPercent=CurPercent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ComprDataIO::ShowUnpWrite()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ComprDataIO::SetFiles(File *SrcFile,File *DestFile)
|
||||||
|
{
|
||||||
|
if (SrcFile!=NULL)
|
||||||
|
ComprDataIO::SrcFile=SrcFile;
|
||||||
|
if (DestFile!=NULL)
|
||||||
|
ComprDataIO::DestFile=DestFile;
|
||||||
|
LastPercent=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size)
|
||||||
|
{
|
||||||
|
*Data=UnpWrAddr;
|
||||||
|
*Size=UnpWrSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ComprDataIO::SetEncryption(bool Encrypt,CRYPT_METHOD Method,
|
||||||
|
SecPassword *Password,const byte *Salt,const byte *InitV,
|
||||||
|
uint Lg2Cnt,byte *HashKey,byte *PswCheck)
|
||||||
|
{
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
if (Encrypt)
|
||||||
|
Encryption=Crypt->SetCryptKeys(true,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
|
||||||
|
else
|
||||||
|
Decryption=Decrypt->SetCryptKeys(false,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
|
||||||
|
void ComprDataIO::SetAV15Encryption()
|
||||||
|
{
|
||||||
|
Decryption=true;
|
||||||
|
Decrypt->SetAV15Encryption();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
|
||||||
|
void ComprDataIO::SetCmt13Encryption()
|
||||||
|
{
|
||||||
|
Decryption=true;
|
||||||
|
Decrypt->SetCmt13Encryption();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size)
|
||||||
|
{
|
||||||
|
UnpackToMemory=true;
|
||||||
|
UnpackToMemoryAddr=Addr;
|
||||||
|
UnpackToMemorySize=Size;
|
||||||
|
}
|
100
deps/unrar/rdwrfn.hpp
vendored
Normal file
100
deps/unrar/rdwrfn.hpp
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef _RAR_DATAIO_
|
||||||
|
#define _RAR_DATAIO_
|
||||||
|
|
||||||
|
class CmdAdd;
|
||||||
|
class Unpack;
|
||||||
|
class ArcFileSearch;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// We use external i/o calls for Benchmark command.
|
||||||
|
#define COMPRDATAIO_EXTIO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ComprDataIO
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void ShowUnpRead(int64 ArcPos,int64 ArcSize);
|
||||||
|
void ShowUnpWrite();
|
||||||
|
|
||||||
|
|
||||||
|
bool UnpackFromMemory;
|
||||||
|
size_t UnpackFromMemorySize;
|
||||||
|
byte *UnpackFromMemoryAddr;
|
||||||
|
|
||||||
|
bool UnpackToMemory;
|
||||||
|
size_t UnpackToMemorySize;
|
||||||
|
byte *UnpackToMemoryAddr;
|
||||||
|
|
||||||
|
size_t UnpWrSize;
|
||||||
|
byte *UnpWrAddr;
|
||||||
|
|
||||||
|
int64 UnpPackedSize;
|
||||||
|
|
||||||
|
bool ShowProgress;
|
||||||
|
bool TestMode;
|
||||||
|
bool SkipUnpCRC;
|
||||||
|
bool NoFileHeader;
|
||||||
|
|
||||||
|
File *SrcFile;
|
||||||
|
File *DestFile;
|
||||||
|
|
||||||
|
CmdAdd *Command;
|
||||||
|
|
||||||
|
FileHeader *SubHead;
|
||||||
|
int64 *SubHeadPos;
|
||||||
|
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
|
CryptData *Crypt;
|
||||||
|
CryptData *Decrypt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int LastPercent;
|
||||||
|
|
||||||
|
wchar CurrentCommand;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ComprDataIO();
|
||||||
|
~ComprDataIO();
|
||||||
|
void Init();
|
||||||
|
int UnpRead(byte *Addr,size_t Count);
|
||||||
|
void UnpWrite(byte *Addr,size_t Count);
|
||||||
|
void EnableShowProgress(bool Show) {ShowProgress=Show;}
|
||||||
|
void GetUnpackedData(byte **Data,size_t *Size);
|
||||||
|
void SetPackedSizeToRead(int64 Size) {UnpPackedSize=Size;}
|
||||||
|
void SetTestMode(bool Mode) {TestMode=Mode;}
|
||||||
|
void SetSkipUnpCRC(bool Skip) {SkipUnpCRC=Skip;}
|
||||||
|
void SetNoFileHeader(bool Mode) {NoFileHeader=Mode;}
|
||||||
|
void SetFiles(File *SrcFile,File *DestFile);
|
||||||
|
void SetCommand(CmdAdd *Cmd) {Command=Cmd;}
|
||||||
|
void SetSubHeader(FileHeader *hd,int64 *Pos) {SubHead=hd;SubHeadPos=Pos;}
|
||||||
|
void SetEncryption(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
|
||||||
|
const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck);
|
||||||
|
void SetAV15Encryption();
|
||||||
|
void SetCmt13Encryption();
|
||||||
|
void SetUnpackToMemory(byte *Addr,uint Size);
|
||||||
|
void SetCurrentCommand(wchar Cmd) {CurrentCommand=Cmd;}
|
||||||
|
|
||||||
|
|
||||||
|
bool PackVolume;
|
||||||
|
bool UnpVolume;
|
||||||
|
bool NextVolumeMissing;
|
||||||
|
int64 UnpArcSize;
|
||||||
|
int64 CurPackRead,CurPackWrite,CurUnpRead,CurUnpWrite;
|
||||||
|
|
||||||
|
|
||||||
|
// Size of already processed archives.
|
||||||
|
// Used to calculate the total operation progress.
|
||||||
|
int64 ProcessedArcSize;
|
||||||
|
|
||||||
|
int64 TotalArcSize;
|
||||||
|
|
||||||
|
DataHash PackedDataHash; // Packed write and unpack read hash.
|
||||||
|
DataHash PackHash; // Pack read hash.
|
||||||
|
DataHash UnpHash; // Unpack write hash.
|
||||||
|
|
||||||
|
bool Encryption;
|
||||||
|
bool Decryption;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
50
deps/unrar/readme.txt
vendored
Normal file
50
deps/unrar/readme.txt
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
Portable UnRAR version
|
||||||
|
|
||||||
|
|
||||||
|
1. General
|
||||||
|
|
||||||
|
This package includes freeware Unrar C++ source and makefile for
|
||||||
|
several Unix compilers.
|
||||||
|
|
||||||
|
Unrar source is subset of RAR and generated from RAR source automatically,
|
||||||
|
by a small program removing blocks like '#ifndef UNRAR ... #endif'.
|
||||||
|
Such method is not perfect and you may find some RAR related stuff
|
||||||
|
unnecessary in Unrar, especially in header files.
|
||||||
|
|
||||||
|
If you wish to port Unrar to a new platform, you may need to edit
|
||||||
|
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
|
||||||
|
in rartypes.hpp.
|
||||||
|
|
||||||
|
if computer architecture does not allow not aligned data access,
|
||||||
|
you need to undefine ALLOW_NOT_ALIGNED_INT and define
|
||||||
|
STRICT_ALIGNMENT_REQUIRED in os.h.
|
||||||
|
|
||||||
|
UnRAR.vcproj and UnRARDll.vcproj are projects for Microsoft Visual C++.
|
||||||
|
UnRARDll.vcproj lets to build unrar.dll library.
|
||||||
|
|
||||||
|
|
||||||
|
2. Unrar binaries
|
||||||
|
|
||||||
|
If you compiled Unrar for OS, which is not present in "Downloads"
|
||||||
|
and "RAR extras" on www.rarlab.com, we will appreciate if you send
|
||||||
|
us the compiled executable to place it to our site.
|
||||||
|
|
||||||
|
|
||||||
|
3. Acknowledgements
|
||||||
|
|
||||||
|
This source includes parts of code written by other authors.
|
||||||
|
Please see acknow.txt file for details.
|
||||||
|
|
||||||
|
|
||||||
|
4. Legal stuff
|
||||||
|
|
||||||
|
Unrar source may be used in any software to handle RAR archives
|
||||||
|
without limitations free of charge, but cannot be used to re-create
|
||||||
|
the RAR compression algorithm, which is proprietary. Distribution
|
||||||
|
of modified Unrar source in separate form or as a part of other
|
||||||
|
software is permitted, provided that it is clearly stated in
|
||||||
|
the documentation and source comments that the code may not be used
|
||||||
|
to develop a RAR (WinRAR) compatible archiver.
|
||||||
|
|
||||||
|
More detailed license text is available in license.txt.
|
111
deps/unrar/recvol.cpp
vendored
Normal file
111
deps/unrar/recvol.cpp
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#include "recvol3.cpp"
|
||||||
|
#include "recvol5.cpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
|
{
|
||||||
|
Archive Arc(Cmd);
|
||||||
|
if (!Arc.Open(Name))
|
||||||
|
{
|
||||||
|
if (!Silent)
|
||||||
|
ErrHandler.OpenErrorMsg(Name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RARFORMAT Fmt=RARFMT15;
|
||||||
|
if (Arc.IsArchive(true))
|
||||||
|
Fmt=Arc.Format;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte Sign[REV5_SIGN_SIZE];
|
||||||
|
Arc.Seek(0,SEEK_SET);
|
||||||
|
if (Arc.Read(Sign,REV5_SIGN_SIZE)==REV5_SIGN_SIZE && memcmp(Sign,REV5_SIGN,REV5_SIGN_SIZE)==0)
|
||||||
|
Fmt=RARFMT50;
|
||||||
|
}
|
||||||
|
Arc.Close();
|
||||||
|
|
||||||
|
// We define RecVol as local variable for proper stack unwinding when
|
||||||
|
// handling exceptions. So it can close and delete files on Cancel.
|
||||||
|
if (Fmt==RARFMT15)
|
||||||
|
{
|
||||||
|
RecVolumes3 RecVol(Cmd,false);
|
||||||
|
return RecVol.Restore(Cmd,Name,Silent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RecVolumes5 RecVol(Cmd,false);
|
||||||
|
return RecVol.Restore(Cmd,Name,Silent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name)
|
||||||
|
{
|
||||||
|
wchar RevName[NM];
|
||||||
|
*RevName=0;
|
||||||
|
if (Arc!=NULL)
|
||||||
|
{
|
||||||
|
// We received .rar or .exe volume as a parameter, trying to find
|
||||||
|
// the matching .rev file number 1.
|
||||||
|
bool NewNumbering=Arc->NewNumbering;
|
||||||
|
|
||||||
|
wchar ArcName[NM];
|
||||||
|
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
||||||
|
|
||||||
|
wchar *VolNumStart=VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),NewNumbering);
|
||||||
|
wchar RecVolMask[NM];
|
||||||
|
wcsncpyz(RecVolMask,ArcName,ASIZE(RecVolMask));
|
||||||
|
size_t BaseNamePartLength=VolNumStart-ArcName;
|
||||||
|
wcsncpyz(RecVolMask+BaseNamePartLength,L"*.rev",ASIZE(RecVolMask)-BaseNamePartLength);
|
||||||
|
|
||||||
|
FindFile Find;
|
||||||
|
Find.SetMask(RecVolMask);
|
||||||
|
FindData RecData;
|
||||||
|
|
||||||
|
while (Find.Next(&RecData))
|
||||||
|
{
|
||||||
|
wchar *Num=GetVolNumPart(RecData.Name);
|
||||||
|
if (*Num!='1') // Name must have "0...01" numeric part.
|
||||||
|
continue;
|
||||||
|
bool FirstVol=true;
|
||||||
|
while (--Num>=RecData.Name && IsDigit(*Num))
|
||||||
|
if (*Num!='0')
|
||||||
|
{
|
||||||
|
FirstVol=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (FirstVol)
|
||||||
|
{
|
||||||
|
wcsncpyz(RevName,RecData.Name,ASIZE(RevName));
|
||||||
|
Name=RevName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*RevName==0) // First .rev file not found.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File RevFile;
|
||||||
|
if (!RevFile.Open(Name))
|
||||||
|
{
|
||||||
|
ErrHandler.OpenErrorMsg(Name); // It also sets RARX_OPEN.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mprintf(L"\n");
|
||||||
|
byte Sign[REV5_SIGN_SIZE];
|
||||||
|
bool Rev5=RevFile.Read(Sign,REV5_SIGN_SIZE)==REV5_SIGN_SIZE && memcmp(Sign,REV5_SIGN,REV5_SIGN_SIZE)==0;
|
||||||
|
RevFile.Close();
|
||||||
|
if (Rev5)
|
||||||
|
{
|
||||||
|
RecVolumes5 RecVol(Cmd,true);
|
||||||
|
RecVol.Test(Cmd,Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RecVolumes3 RecVol(Cmd,true);
|
||||||
|
RecVol.Test(Cmd,Name);
|
||||||
|
}
|
||||||
|
}
|
88
deps/unrar/recvol.hpp
vendored
Normal file
88
deps/unrar/recvol.hpp
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#ifndef _RAR_RECVOL_
|
||||||
|
#define _RAR_RECVOL_
|
||||||
|
|
||||||
|
#define REV5_SIGN "Rar!\x1aRev"
|
||||||
|
#define REV5_SIGN_SIZE 8
|
||||||
|
|
||||||
|
class RecVolumes3
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
File *SrcFile[256];
|
||||||
|
Array<byte> Buf;
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
ThreadPool *RSThreadPool;
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
RecVolumes3(RAROptions *Cmd,bool TestOnly);
|
||||||
|
~RecVolumes3();
|
||||||
|
void Make(RAROptions *Cmd,wchar *ArcName);
|
||||||
|
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||||
|
void Test(RAROptions *Cmd,const wchar *Name);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct RecVolItem
|
||||||
|
{
|
||||||
|
File *f;
|
||||||
|
wchar Name[NM];
|
||||||
|
uint CRC;
|
||||||
|
uint64 FileSize;
|
||||||
|
bool New; // Newly created RAR volume.
|
||||||
|
bool Valid; // If existing RAR volume is valid.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RecVolumes5;
|
||||||
|
struct RecRSThreadData
|
||||||
|
{
|
||||||
|
RecVolumes5 *RecRSPtr;
|
||||||
|
RSCoder16 *RS;
|
||||||
|
bool Encode;
|
||||||
|
uint DataNum;
|
||||||
|
const byte *Data;
|
||||||
|
size_t StartPos;
|
||||||
|
size_t Size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RecVolumes5
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void ProcessRS(RAROptions *Cmd,uint DataNum,const byte *Data,uint MaxRead,bool Encode);
|
||||||
|
void ProcessRS(RAROptions *Cmd,uint MaxRead,bool Encode);
|
||||||
|
uint ReadHeader(File *RecFile,bool FirstRev);
|
||||||
|
|
||||||
|
Array<RecVolItem> RecItems;
|
||||||
|
|
||||||
|
byte *RealReadBuffer; // Real pointer returned by 'new'.
|
||||||
|
byte *ReadBuffer; // Pointer aligned for SSE instructions.
|
||||||
|
|
||||||
|
byte *RealBuf; // Real pointer returned by 'new'.
|
||||||
|
byte *Buf; // Store ECC or recovered data here, aligned for SSE.
|
||||||
|
size_t RecBufferSize; // Buffer area allocated for single volume.
|
||||||
|
|
||||||
|
uint DataCount; // Number of archives.
|
||||||
|
uint RecCount; // Number of recovery volumes.
|
||||||
|
uint TotalCount; // Total number of archives and recovery volumes.
|
||||||
|
|
||||||
|
bool *ValidFlags; // Volume validity flags for recovering.
|
||||||
|
uint MissingVolumes; // Number of missing or bad RAR volumes.
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
ThreadPool *RecThreadPool;
|
||||||
|
#endif
|
||||||
|
uint MaxUserThreads; // Maximum number of threads defined by user.
|
||||||
|
RecRSThreadData *ThreadData; // Array to store thread parameters.
|
||||||
|
public: // 'public' only because called from thread functions.
|
||||||
|
void ProcessAreaRS(RecRSThreadData *td);
|
||||||
|
public:
|
||||||
|
RecVolumes5(RAROptions *Cmd,bool TestOnly);
|
||||||
|
~RecVolumes5();
|
||||||
|
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||||
|
void Test(RAROptions *Cmd,const wchar *Name);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||||
|
void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name);
|
||||||
|
|
||||||
|
#endif
|
544
deps/unrar/recvol3.cpp
vendored
Normal file
544
deps/unrar/recvol3.cpp
vendored
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
// Buffer size for all volumes involved.
|
||||||
|
static const size_t TotalBufferSize=0x4000000;
|
||||||
|
|
||||||
|
class RSEncode // Encode or decode data area, one object per one thread.
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
RSCoder RSC;
|
||||||
|
public:
|
||||||
|
void EncodeBuf();
|
||||||
|
void DecodeBuf();
|
||||||
|
|
||||||
|
void Init(int RecVolNumber) {RSC.Init(RecVolNumber);}
|
||||||
|
byte *Buf;
|
||||||
|
byte *OutBuf;
|
||||||
|
int BufStart;
|
||||||
|
int BufEnd;
|
||||||
|
int FileNumber;
|
||||||
|
int RecVolNumber;
|
||||||
|
size_t RecBufferSize;
|
||||||
|
int *Erasures;
|
||||||
|
int EraSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
THREAD_PROC(RSEncodeThread)
|
||||||
|
{
|
||||||
|
RSEncode *rs=(RSEncode *)Data;
|
||||||
|
rs->EncodeBuf();
|
||||||
|
}
|
||||||
|
|
||||||
|
THREAD_PROC(RSDecodeThread)
|
||||||
|
{
|
||||||
|
RSEncode *rs=(RSEncode *)Data;
|
||||||
|
rs->DecodeBuf();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly)
|
||||||
|
{
|
||||||
|
memset(SrcFile,0,sizeof(SrcFile));
|
||||||
|
if (TestOnly)
|
||||||
|
{
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
RSThreadPool=NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Buf.Alloc(TotalBufferSize);
|
||||||
|
memset(SrcFile,0,sizeof(SrcFile));
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
RSThreadPool=new ThreadPool(Cmd->Threads);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RecVolumes3::~RecVolumes3()
|
||||||
|
{
|
||||||
|
for (size_t I=0;I<ASIZE(SrcFile);I++)
|
||||||
|
delete SrcFile[I];
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
delete RSThreadPool;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void RSEncode::EncodeBuf()
|
||||||
|
{
|
||||||
|
for (int BufPos=BufStart;BufPos<BufEnd;BufPos++)
|
||||||
|
{
|
||||||
|
byte Data[256],Code[256];
|
||||||
|
for (int I=0;I<FileNumber;I++)
|
||||||
|
Data[I]=Buf[I*RecBufferSize+BufPos];
|
||||||
|
RSC.Encode(Data,FileNumber,Code);
|
||||||
|
for (int I=0;I<RecVolNumber;I++)
|
||||||
|
OutBuf[I*RecBufferSize+BufPos]=Code[I];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check for names like arc5_3_1.rev created by RAR 3.0.
|
||||||
|
static bool IsNewStyleRev(const wchar *Name)
|
||||||
|
{
|
||||||
|
wchar *Ext=GetExt(Name);
|
||||||
|
if (Ext==NULL)
|
||||||
|
return true;
|
||||||
|
int DigitGroup=0;
|
||||||
|
for (Ext--;Ext>Name;Ext--)
|
||||||
|
if (!IsDigit(*Ext))
|
||||||
|
if (*Ext=='_' && IsDigit(*(Ext-1)))
|
||||||
|
DigitGroup++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
return DigitGroup<2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
|
{
|
||||||
|
wchar ArcName[NM];
|
||||||
|
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
||||||
|
wchar *Ext=GetExt(ArcName);
|
||||||
|
bool NewStyle=false; // New style .rev volumes are supported since RAR 3.10.
|
||||||
|
bool RevName=Ext!=NULL && wcsicomp(Ext,L".rev")==0;
|
||||||
|
if (RevName)
|
||||||
|
{
|
||||||
|
NewStyle=IsNewStyleRev(ArcName);
|
||||||
|
while (Ext>ArcName+1 && (IsDigit(*(Ext-1)) || *(Ext-1)=='_'))
|
||||||
|
Ext--;
|
||||||
|
wcsncpyz(Ext,L"*.*",ASIZE(ArcName)-(Ext-ArcName));
|
||||||
|
|
||||||
|
FindFile Find;
|
||||||
|
Find.SetMask(ArcName);
|
||||||
|
FindData fd;
|
||||||
|
while (Find.Next(&fd))
|
||||||
|
{
|
||||||
|
Archive Arc(Cmd);
|
||||||
|
if (Arc.WOpen(fd.Name) && Arc.IsArchive(true))
|
||||||
|
{
|
||||||
|
wcsncpyz(ArcName,fd.Name,ASIZE(ArcName));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Archive Arc(Cmd);
|
||||||
|
if (!Arc.WCheckOpen(ArcName))
|
||||||
|
return false;
|
||||||
|
if (!Arc.Volume)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_NOTVOLUME,ArcName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool NewNumbering=Arc.NewNumbering;
|
||||||
|
Arc.Close();
|
||||||
|
|
||||||
|
wchar *VolNumStart=VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),NewNumbering);
|
||||||
|
wchar RecVolMask[NM];
|
||||||
|
wcsncpyz(RecVolMask,ArcName,ASIZE(RecVolMask));
|
||||||
|
size_t BaseNamePartLength=VolNumStart-ArcName;
|
||||||
|
wcsncpyz(RecVolMask+BaseNamePartLength,L"*.rev",ASIZE(RecVolMask)-BaseNamePartLength);
|
||||||
|
|
||||||
|
int64 RecFileSize=0;
|
||||||
|
|
||||||
|
// We cannot display "Calculating CRC..." message here, because we do not
|
||||||
|
// know if we'll find any recovery volumes. We'll display it after finding
|
||||||
|
// the first recovery volume.
|
||||||
|
bool CalcCRCMessageDone=false;
|
||||||
|
|
||||||
|
FindFile Find;
|
||||||
|
Find.SetMask(RecVolMask);
|
||||||
|
FindData RecData;
|
||||||
|
int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0;
|
||||||
|
wchar PrevName[NM];
|
||||||
|
while (Find.Next(&RecData))
|
||||||
|
{
|
||||||
|
wchar *CurName=RecData.Name;
|
||||||
|
int P[3];
|
||||||
|
if (!RevName && !NewStyle)
|
||||||
|
{
|
||||||
|
NewStyle=true;
|
||||||
|
|
||||||
|
wchar *Dot=GetExt(CurName);
|
||||||
|
if (Dot!=NULL)
|
||||||
|
{
|
||||||
|
int LineCount=0;
|
||||||
|
Dot--;
|
||||||
|
while (Dot>CurName && *Dot!='.')
|
||||||
|
{
|
||||||
|
if (*Dot=='_')
|
||||||
|
LineCount++;
|
||||||
|
Dot--;
|
||||||
|
}
|
||||||
|
if (LineCount==2)
|
||||||
|
NewStyle=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NewStyle)
|
||||||
|
{
|
||||||
|
if (!CalcCRCMessageDone)
|
||||||
|
{
|
||||||
|
uiMsg(UIMSG_RECVOLCALCCHECKSUM);
|
||||||
|
CalcCRCMessageDone=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiMsg(UIMSG_STRING,CurName);
|
||||||
|
|
||||||
|
File CurFile;
|
||||||
|
CurFile.TOpen(CurName);
|
||||||
|
CurFile.Seek(0,SEEK_END);
|
||||||
|
int64 Length=CurFile.Tell();
|
||||||
|
CurFile.Seek(Length-7,SEEK_SET);
|
||||||
|
for (int I=0;I<3;I++)
|
||||||
|
P[2-I]=CurFile.GetByte()+1;
|
||||||
|
uint FileCRC=0;
|
||||||
|
for (int I=0;I<4;I++)
|
||||||
|
FileCRC|=CurFile.GetByte()<<(I*8);
|
||||||
|
uint CalcCRC;
|
||||||
|
CalcFileSum(&CurFile,&CalcCRC,NULL,Cmd->Threads,Length-4);
|
||||||
|
if (FileCRC!=CalcCRC)
|
||||||
|
{
|
||||||
|
uiMsg(UIMSG_CHECKSUM,CurName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wchar *Dot=GetExt(CurName);
|
||||||
|
if (Dot==NULL)
|
||||||
|
continue;
|
||||||
|
bool WrongParam=false;
|
||||||
|
for (size_t I=0;I<ASIZE(P);I++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Dot--;
|
||||||
|
} while (IsDigit(*Dot) && Dot>=CurName+BaseNamePartLength);
|
||||||
|
P[I]=atoiw(Dot+1);
|
||||||
|
if (P[I]==0 || P[I]>255)
|
||||||
|
WrongParam=true;
|
||||||
|
}
|
||||||
|
if (WrongParam)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (P[1]+P[2]>255)
|
||||||
|
continue;
|
||||||
|
if (RecVolNumber!=0 && RecVolNumber!=P[1] || FileNumber!=0 && FileNumber!=P[2])
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_RECVOLDIFFSETS,CurName,PrevName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RecVolNumber=P[1];
|
||||||
|
FileNumber=P[2];
|
||||||
|
wcsncpyz(PrevName,CurName,ASIZE(PrevName));
|
||||||
|
File *NewFile=new File;
|
||||||
|
NewFile->TOpen(CurName);
|
||||||
|
SrcFile[FileNumber+P[0]-1]=NewFile;
|
||||||
|
FoundRecVolumes++;
|
||||||
|
|
||||||
|
if (RecFileSize==0)
|
||||||
|
RecFileSize=NewFile->FileLength();
|
||||||
|
}
|
||||||
|
if (!Silent || FoundRecVolumes!=0)
|
||||||
|
uiMsg(UIMSG_RECVOLFOUND,FoundRecVolumes);
|
||||||
|
if (FoundRecVolumes==0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool WriteFlags[256];
|
||||||
|
memset(WriteFlags,0,sizeof(WriteFlags));
|
||||||
|
|
||||||
|
wchar LastVolName[NM];
|
||||||
|
*LastVolName=0;
|
||||||
|
|
||||||
|
for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++)
|
||||||
|
{
|
||||||
|
Archive *NewFile=new Archive(Cmd);
|
||||||
|
bool ValidVolume=FileExist(ArcName);
|
||||||
|
if (ValidVolume)
|
||||||
|
{
|
||||||
|
NewFile->TOpen(ArcName);
|
||||||
|
ValidVolume=NewFile->IsArchive(false);
|
||||||
|
if (ValidVolume)
|
||||||
|
{
|
||||||
|
while (NewFile->ReadHeader()!=0)
|
||||||
|
{
|
||||||
|
if (NewFile->GetHeaderType()==HEAD_ENDARC)
|
||||||
|
{
|
||||||
|
uiMsg(UIMSG_STRING,ArcName);
|
||||||
|
|
||||||
|
if (NewFile->EndArcHead.DataCRC)
|
||||||
|
{
|
||||||
|
uint CalcCRC;
|
||||||
|
CalcFileSum(NewFile,&CalcCRC,NULL,Cmd->Threads,NewFile->CurBlockPos);
|
||||||
|
if (NewFile->EndArcHead.ArcDataCRC!=CalcCRC)
|
||||||
|
{
|
||||||
|
ValidVolume=false;
|
||||||
|
uiMsg(UIMSG_CHECKSUM,ArcName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NewFile->SeekToNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ValidVolume)
|
||||||
|
{
|
||||||
|
NewFile->Close();
|
||||||
|
wchar NewName[NM];
|
||||||
|
wcsncpyz(NewName,ArcName,ASIZE(NewName));
|
||||||
|
wcsncatz(NewName,L".bad",ASIZE(NewName));
|
||||||
|
|
||||||
|
uiMsg(UIMSG_BADARCHIVE,ArcName);
|
||||||
|
uiMsg(UIMSG_RENAMING,ArcName,NewName);
|
||||||
|
RenameFile(ArcName,NewName);
|
||||||
|
}
|
||||||
|
NewFile->Seek(0,SEEK_SET);
|
||||||
|
}
|
||||||
|
if (!ValidVolume)
|
||||||
|
{
|
||||||
|
// It is important to return 'false' instead of aborting here,
|
||||||
|
// so if we are called from extraction, we will be able to continue
|
||||||
|
// extracting. It may happen if .rar and .rev are on read-only disks
|
||||||
|
// like CDs.
|
||||||
|
if (!NewFile->Create(ArcName,FMF_WRITE|FMF_SHAREREAD))
|
||||||
|
{
|
||||||
|
// We need to display the title of operation before the error message,
|
||||||
|
// to make clear for user that create error is related to recovery
|
||||||
|
// volumes. This is why we cannot use WCreate call here. Title must be
|
||||||
|
// before create error, not after that.
|
||||||
|
|
||||||
|
uiMsg(UIERROR_RECVOLFOUND,FoundRecVolumes); // Intentionally not displayed in console mode.
|
||||||
|
uiMsg(UIERROR_RECONSTRUCTING);
|
||||||
|
ErrHandler.CreateErrorMsg(ArcName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteFlags[CurArcNum]=true;
|
||||||
|
MissingVolumes++;
|
||||||
|
|
||||||
|
if (CurArcNum==FileNumber-1)
|
||||||
|
wcsncpyz(LastVolName,ArcName,ASIZE(LastVolName));
|
||||||
|
|
||||||
|
uiMsg(UIMSG_MISSINGVOL,ArcName);
|
||||||
|
uiMsg(UIEVENT_NEWARCHIVE,ArcName);
|
||||||
|
}
|
||||||
|
SrcFile[CurArcNum]=(File*)NewFile;
|
||||||
|
NextVolumeName(ArcName,ASIZE(ArcName),!NewNumbering);
|
||||||
|
}
|
||||||
|
|
||||||
|
uiMsg(UIMSG_RECVOLMISSING,MissingVolumes);
|
||||||
|
|
||||||
|
if (MissingVolumes==0)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_RECVOLALLEXIST);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MissingVolumes>FoundRecVolumes)
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_RECVOLFOUND,FoundRecVolumes); // Intentionally not displayed in console mode.
|
||||||
|
uiMsg(UIERROR_RECVOLCANNOTFIX);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiMsg(UIMSG_RECONSTRUCTING);
|
||||||
|
|
||||||
|
int TotalFiles=FileNumber+RecVolNumber;
|
||||||
|
int Erasures[256],EraSize=0;
|
||||||
|
|
||||||
|
for (int I=0;I<TotalFiles;I++)
|
||||||
|
if (WriteFlags[I] || SrcFile[I]==NULL)
|
||||||
|
Erasures[EraSize++]=I;
|
||||||
|
|
||||||
|
int64 ProcessedSize=0;
|
||||||
|
int LastPercent=-1;
|
||||||
|
mprintf(L" ");
|
||||||
|
// Size of per file buffer.
|
||||||
|
size_t RecBufferSize=TotalBufferSize/TotalFiles;
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
uint ThreadNumber=Cmd->Threads;
|
||||||
|
#else
|
||||||
|
uint ThreadNumber=1;
|
||||||
|
#endif
|
||||||
|
RSEncode *rse=new RSEncode[ThreadNumber];
|
||||||
|
for (uint I=0;I<ThreadNumber;I++)
|
||||||
|
rse[I].Init(RecVolNumber);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Wait();
|
||||||
|
int MaxRead=0;
|
||||||
|
for (int I=0;I<TotalFiles;I++)
|
||||||
|
if (WriteFlags[I] || SrcFile[I]==NULL)
|
||||||
|
memset(&Buf[I*RecBufferSize],0,RecBufferSize);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int ReadSize=SrcFile[I]->Read(&Buf[I*RecBufferSize],RecBufferSize);
|
||||||
|
if ((size_t)ReadSize!=RecBufferSize)
|
||||||
|
memset(&Buf[I*RecBufferSize+ReadSize],0,RecBufferSize-ReadSize);
|
||||||
|
if (ReadSize>MaxRead)
|
||||||
|
MaxRead=ReadSize;
|
||||||
|
}
|
||||||
|
if (MaxRead==0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
int CurPercent=ToPercent(ProcessedSize,RecFileSize);
|
||||||
|
if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
|
||||||
|
{
|
||||||
|
uiProcessProgress("RC",ProcessedSize,RecFileSize);
|
||||||
|
LastPercent=CurPercent;
|
||||||
|
}
|
||||||
|
ProcessedSize+=MaxRead;
|
||||||
|
|
||||||
|
int BlockStart=0;
|
||||||
|
int BlockSize=MaxRead/ThreadNumber;
|
||||||
|
if (BlockSize<0x100)
|
||||||
|
BlockSize=MaxRead;
|
||||||
|
|
||||||
|
for (uint CurThread=0;BlockStart<MaxRead;CurThread++)
|
||||||
|
{
|
||||||
|
// Last thread processes all left data including increasement
|
||||||
|
// from rounding error.
|
||||||
|
if (CurThread==ThreadNumber-1)
|
||||||
|
BlockSize=MaxRead-BlockStart;
|
||||||
|
|
||||||
|
RSEncode *curenc=rse+CurThread;
|
||||||
|
curenc->Buf=&Buf[0];
|
||||||
|
curenc->BufStart=BlockStart;
|
||||||
|
curenc->BufEnd=BlockStart+BlockSize;
|
||||||
|
curenc->FileNumber=TotalFiles;
|
||||||
|
curenc->RecBufferSize=RecBufferSize;
|
||||||
|
curenc->Erasures=Erasures;
|
||||||
|
curenc->EraSize=EraSize;
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
if (ThreadNumber>1)
|
||||||
|
RSThreadPool->AddTask(RSDecodeThread,(void*)curenc);
|
||||||
|
else
|
||||||
|
curenc->DecodeBuf();
|
||||||
|
#else
|
||||||
|
curenc->DecodeBuf();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BlockStart+=BlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RAR_SMP
|
||||||
|
RSThreadPool->WaitDone();
|
||||||
|
#endif // RAR_SMP
|
||||||
|
|
||||||
|
for (int I=0;I<FileNumber;I++)
|
||||||
|
if (WriteFlags[I])
|
||||||
|
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
|
||||||
|
}
|
||||||
|
delete[] rse;
|
||||||
|
|
||||||
|
for (int I=0;I<RecVolNumber+FileNumber;I++)
|
||||||
|
if (SrcFile[I]!=NULL)
|
||||||
|
{
|
||||||
|
File *CurFile=SrcFile[I];
|
||||||
|
if (NewStyle && WriteFlags[I])
|
||||||
|
{
|
||||||
|
int64 Length=CurFile->Tell();
|
||||||
|
CurFile->Seek(Length-7,SEEK_SET);
|
||||||
|
for (int J=0;J<7;J++)
|
||||||
|
CurFile->PutByte(0);
|
||||||
|
}
|
||||||
|
CurFile->Close();
|
||||||
|
SrcFile[I]=NULL;
|
||||||
|
}
|
||||||
|
if (*LastVolName!=0)
|
||||||
|
{
|
||||||
|
// Truncate the last volume to its real size.
|
||||||
|
Archive Arc(Cmd);
|
||||||
|
if (Arc.Open(LastVolName,FMF_UPDATE) && Arc.IsArchive(true) &&
|
||||||
|
Arc.SearchBlock(HEAD_ENDARC))
|
||||||
|
{
|
||||||
|
Arc.Seek(Arc.NextBlockPos,SEEK_SET);
|
||||||
|
char Buf[8192];
|
||||||
|
int ReadSize=Arc.Read(Buf,sizeof(Buf));
|
||||||
|
int ZeroCount=0;
|
||||||
|
while (ZeroCount<ReadSize && Buf[ZeroCount]==0)
|
||||||
|
ZeroCount++;
|
||||||
|
if (ZeroCount==ReadSize)
|
||||||
|
{
|
||||||
|
Arc.Seek(Arc.NextBlockPos,SEEK_SET);
|
||||||
|
Arc.Truncate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if !defined(SILENT)
|
||||||
|
if (!Cmd->DisablePercentage)
|
||||||
|
mprintf(L"\b\b\b\b100%%");
|
||||||
|
if (!Silent && !Cmd->DisableDone)
|
||||||
|
mprintf(St(MDone));
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSEncode::DecodeBuf()
|
||||||
|
{
|
||||||
|
for (int BufPos=BufStart;BufPos<BufEnd;BufPos++)
|
||||||
|
{
|
||||||
|
byte Data[256];
|
||||||
|
for (int I=0;I<FileNumber;I++)
|
||||||
|
Data[I]=Buf[I*RecBufferSize+BufPos];
|
||||||
|
RSC.Decode(Data,FileNumber,Erasures,EraSize);
|
||||||
|
for (int I=0;I<EraSize;I++)
|
||||||
|
Buf[Erasures[I]*RecBufferSize+BufPos]=Data[Erasures[I]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RecVolumes3::Test(RAROptions *Cmd,const wchar *Name)
|
||||||
|
{
|
||||||
|
if (!IsNewStyleRev(Name)) // RAR 3.0 name#_#_#.rev do not include CRC32.
|
||||||
|
{
|
||||||
|
ErrHandler.UnknownMethodMsg(Name,Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar VolName[NM];
|
||||||
|
wcsncpyz(VolName,Name,ASIZE(VolName));
|
||||||
|
|
||||||
|
while (FileExist(VolName))
|
||||||
|
{
|
||||||
|
File CurFile;
|
||||||
|
if (!CurFile.Open(VolName))
|
||||||
|
{
|
||||||
|
ErrHandler.OpenErrorMsg(VolName); // It also sets RARX_OPEN.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!uiStartFileExtract(VolName,false,true,false))
|
||||||
|
return;
|
||||||
|
mprintf(St(MExtrTestFile),VolName);
|
||||||
|
mprintf(L" ");
|
||||||
|
CurFile.Seek(0,SEEK_END);
|
||||||
|
int64 Length=CurFile.Tell();
|
||||||
|
CurFile.Seek(Length-4,SEEK_SET);
|
||||||
|
uint FileCRC=0;
|
||||||
|
for (int I=0;I<4;I++)
|
||||||
|
FileCRC|=CurFile.GetByte()<<(I*8);
|
||||||
|
|
||||||
|
uint CalcCRC;
|
||||||
|
CalcFileSum(&CurFile,&CalcCRC,NULL,1,Length-4,Cmd->DisablePercentage ? 0 : CALCFSUM_SHOWPROGRESS);
|
||||||
|
if (FileCRC==CalcCRC)
|
||||||
|
{
|
||||||
|
mprintf(L"%s%s ",L"\b\b\b\b\b ",St(MOk));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_CHECKSUM,VolName,VolName);
|
||||||
|
ErrHandler.SetErrorCode(RARX_CRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
NextVolumeName(VolName,ASIZE(VolName),false);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user