mirror of
https://github.com/php-win-ext/php-rar.git
synced 2026-03-24 04:52:07 +01:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6545fdd215 | ||
|
|
08f8190e49 | ||
|
|
544f55920a | ||
|
|
24b421e0e6 | ||
|
|
05a48cbbeb | ||
|
|
6d0e583ef9 | ||
|
|
714f15cb06 | ||
|
|
58bb195ae3 | ||
|
|
5293a8f07e | ||
|
|
61edb08973 | ||
|
|
adc9fe7d39 | ||
|
|
5eb1055447 | ||
|
|
7ca7561e09 | ||
|
|
61eca15136 | ||
|
|
dc8ee65999 | ||
|
|
656c3fa69d | ||
|
|
a6bea8fec8 | ||
|
|
3b405bea8e | ||
|
|
18cd0568aa | ||
|
|
dc298847c7 | ||
|
|
246a80fdeb | ||
|
|
4b6fd31d08 | ||
|
|
44e35b8f6a | ||
|
|
fe4a94305b |
@@ -1,643 +0,0 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="UnRAR"
|
||||
ProjectGUID="{95CC809B-03FC-4EDB-BB20-FD07A698C05F}"
|
||||
RootNamespace="UnRAR"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="build\unrar32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrar32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="UNRAR"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
CallingConvention="2"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="build\unrar64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrar64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="UNRAR"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="2"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="build\unrar32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrar32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="UNRAR"
|
||||
MinimalRebuild="false"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="0"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
FloatingPointModel="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="2"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="build\unrar64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrar64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="1"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="UNRAR"
|
||||
StringPooling="false"
|
||||
MinimalRebuild="false"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="2"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="archive.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="arcread.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="blake2s.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="cmddata.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="consio.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="crc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="crypt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="encname.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="errhnd.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extinfo.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extract.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filcreat.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="file.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filefn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filestr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="find.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="getbits.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="global.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="hash.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="headers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="isnt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="list.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="match.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="options.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="pathfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="qopen.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rar.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rarpch.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rarvm.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rawread.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rdwrfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="recvol.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="resource.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rijndael.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rs.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rs16.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scantree.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="secpassword.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sha1.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sha256.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="smallfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="strfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="strlist.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="system.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="threadpool.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="timefn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ui.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="unicode.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="unpack.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="volume.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,876 +0,0 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="UnRAR"
|
||||
ProjectGUID="{E815C46C-36C4-499F-BBC2-E772C6B17971}"
|
||||
RootNamespace="UnRAR"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="build\unrardll32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
StructMemberAlignment="3"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="build\unrardll64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
StructMemberAlignment="3"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar64.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="build\unrardll32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
FloatingPointModel="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/SAFESEH"
|
||||
OutputFile="$(OutDir)\unrar.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="build\unrardll64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
StringPooling="false"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar64.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="release_nocrypt|Win32"
|
||||
OutputDirectory="build\unrardll32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT;RAR_NOCRYPT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
FloatingPointModel="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/SAFESEH"
|
||||
OutputFile="$(OutDir)\unrar_nocrypt.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll_nocrypt.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="release_nocrypt|x64"
|
||||
OutputDirectory="build\unrardll64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT;RAR_NOCRYPT"
|
||||
StringPooling="false"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="2"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar64_nocrypt.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll_nocrypt.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="archive.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="arcread.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="blake2s.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="cmddata.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="consio.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="crc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="crypt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="dll.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="encname.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="errhnd.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extinfo.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extract.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filcreat.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="file.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filefn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filestr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="find.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="getbits.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="global.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="hash.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="headers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="isnt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="match.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="options.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="pathfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="qopen.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rar.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rarpch.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rarvm.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rawread.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rdwrfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rijndael.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rs.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rs16.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scantree.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="secpassword.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sha1.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sha256.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="smallfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="strfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="strlist.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="system.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="threadpool.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="timefn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ui.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="unicode.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="unpack.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="volume.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="rar.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath="dll.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -4,10 +4,17 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
{
|
||||
if (!MainComment)
|
||||
return false;
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 SavePos=Tell();
|
||||
bool Success=DoGetComment(CmtData);
|
||||
Seek(SavePos,SEEK_SET);
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
bool Archive::DoGetComment(Array<wchar> *CmtData)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
ushort CmtLength;
|
||||
uint CmtLength;
|
||||
if (Format==RARFMT14)
|
||||
{
|
||||
Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
|
||||
@@ -22,7 +29,8 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
// Old style (RAR 2.9) archive comment embedded into the main
|
||||
// archive header.
|
||||
Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
|
||||
ReadHeader();
|
||||
if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -33,7 +41,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
#ifndef SFX_MODULE
|
||||
// Old style (RAR 2.9) comment header embedded into the main
|
||||
// archive header.
|
||||
if (BrokenHeader)
|
||||
if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
|
||||
{
|
||||
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||
return false;
|
||||
@@ -52,10 +60,12 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
if (Format==RARFMT14)
|
||||
{
|
||||
#ifdef RAR_NOCRYPT
|
||||
return(false);
|
||||
return false;
|
||||
#else
|
||||
UnpCmtLength=GetByte();
|
||||
UnpCmtLength+=(GetByte()<<8);
|
||||
if (CmtLength<2)
|
||||
return false;
|
||||
CmtLength-=2;
|
||||
DataIO.SetCmt13Encryption();
|
||||
CommHead.UnpVer=15;
|
||||
@@ -67,6 +77,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
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);
|
||||
@@ -83,21 +94,31 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
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);
|
||||
// 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)));
|
||||
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);
|
||||
Read(&CmtRaw[0],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))
|
||||
{
|
||||
@@ -111,7 +132,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
// 4x memory for OEM to UTF-8 output here.
|
||||
OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
|
||||
#endif
|
||||
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtLength);
|
||||
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
||||
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||
}
|
||||
#endif
|
||||
@@ -122,7 +143,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
bool Archive::ReadCommentData(Array<wchar> *CmtData)
|
||||
{
|
||||
Array<byte> CmtRaw;
|
||||
if (!ReadSubData(&CmtRaw,NULL))
|
||||
if (!ReadSubData(&CmtRaw,NULL,false))
|
||||
return false;
|
||||
size_t CmtSize=CmtRaw.Size();
|
||||
CmtRaw.Push(0);
|
||||
|
||||
@@ -30,8 +30,6 @@ Archive::Archive(RAROptions *InitCmd)
|
||||
CurBlockPos=0;
|
||||
NextBlockPos=0;
|
||||
|
||||
RecoverySize=-1;
|
||||
RecoveryPercent=-1;
|
||||
|
||||
memset(&MainHead,0,sizeof(MainHead));
|
||||
memset(&CryptHead,0,sizeof(CryptHead));
|
||||
@@ -48,6 +46,10 @@ Archive::Archive(RAROptions *InitCmd)
|
||||
|
||||
SilentOpen=false;
|
||||
|
||||
#ifdef USE_QOPEN
|
||||
ProhibitQOpen=false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +116,7 @@ RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
|
||||
if (D[6]==1)
|
||||
Type=RARFMT50;
|
||||
else
|
||||
if (D[6]==2)
|
||||
if (D[6]>1 && D[6]<5)
|
||||
Type=RARFMT_FUTURE;
|
||||
}
|
||||
return Type;
|
||||
@@ -175,8 +177,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
}
|
||||
if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
|
||||
{
|
||||
Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
|
||||
if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
|
||||
if (Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1)!=1 || MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
|
||||
return false;
|
||||
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
|
||||
}
|
||||
@@ -192,27 +193,31 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
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 (ReadHeader()!=0)
|
||||
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.
|
||||
if (Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT)
|
||||
StartFound=Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT;
|
||||
if (StartFound)
|
||||
break;
|
||||
SeekToNext();
|
||||
}
|
||||
|
||||
// This check allows to make RS based recovery even if password is incorrect.
|
||||
// But we should not do it for EnableBroken or we'll get 'not RAR archive'
|
||||
|
||||
// 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;
|
||||
|
||||
SeekToNext();
|
||||
if (BrokenHeader) // Main archive header is corrupt.
|
||||
if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing.
|
||||
{
|
||||
uiMsg(UIERROR_MHEADERBROKEN,FileName);
|
||||
if (!FailedHeaderDecryption) // If not reported a wrong password already.
|
||||
uiMsg(UIERROR_MHEADERBROKEN,FileName);
|
||||
if (!EnableBroken)
|
||||
return false;
|
||||
}
|
||||
@@ -226,9 +231,9 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
// 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 (!SilentOpen || !Encrypted)
|
||||
if (HeadersLeft && (!SilentOpen || !Encrypted))
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 SavePos=Tell();
|
||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
||||
|
||||
@@ -257,9 +262,10 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
CurBlockPos=SaveCurBlockPos;
|
||||
NextBlockPos=SaveNextBlockPos;
|
||||
CurHeaderType=SaveCurHeaderType;
|
||||
Seek(SavePos,SEEK_SET);
|
||||
}
|
||||
if (!Volume || FirstVolume)
|
||||
wcscpy(FirstVolumeName,FileName);
|
||||
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -20,13 +20,15 @@ enum ADDSUBDATA_FLAGS
|
||||
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);
|
||||
void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
|
||||
size_t ReadHeader14();
|
||||
size_t ReadHeader15();
|
||||
size_t ReadHeader50();
|
||||
@@ -34,8 +36,8 @@ class Archive:public File
|
||||
void RequestArcPassword();
|
||||
void UnexpEndArcMsg();
|
||||
void BrokenHeaderMsg();
|
||||
void UnkEncVerMsg(const wchar *Name);
|
||||
void UnkEncVerMsg();
|
||||
void UnkEncVerMsg(const wchar *Name,const wchar *Info);
|
||||
bool DoGetComment(Array<wchar> *CmtData);
|
||||
bool ReadCommentData(Array<wchar> *CmtData);
|
||||
|
||||
#if !defined(RAR_NOCRYPT)
|
||||
@@ -45,8 +47,6 @@ class Archive:public File
|
||||
bool DummyCmd;
|
||||
RAROptions *Cmd;
|
||||
|
||||
int64 RecoverySize;
|
||||
int RecoveryPercent;
|
||||
|
||||
RarTime LatestTime;
|
||||
int LastReadBlock;
|
||||
@@ -55,6 +55,7 @@ class Archive:public File
|
||||
bool SilentOpen;
|
||||
#ifdef USE_QOPEN
|
||||
QuickOpen QOpen;
|
||||
bool ProhibitQOpen;
|
||||
#endif
|
||||
public:
|
||||
Archive(RAROptions *InitCmd=NULL);
|
||||
@@ -64,8 +65,6 @@ class Archive:public File
|
||||
size_t SearchBlock(HEADER_TYPE HeaderType);
|
||||
size_t SearchSubBlock(const wchar *Type);
|
||||
size_t SearchRR();
|
||||
void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false);
|
||||
void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);}
|
||||
size_t ReadHeader();
|
||||
void CheckArc(bool EnableBroken);
|
||||
void CheckOpen(const wchar *Name);
|
||||
@@ -82,8 +81,8 @@ class Archive:public File
|
||||
int64 GetStartPos();
|
||||
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
|
||||
const wchar *Name,uint Flags);
|
||||
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
|
||||
HEADER_TYPE GetHeaderType() {return CurHeaderType;};
|
||||
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
|
||||
@@ -95,6 +94,7 @@ class Archive:public File
|
||||
void Seek(int64 Offset,int Method);
|
||||
int64 Tell();
|
||||
void QOpenUnload() {QOpen.Unload();}
|
||||
void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;}
|
||||
#endif
|
||||
|
||||
BaseBlock ShortBlock;
|
||||
@@ -107,10 +107,7 @@ class Archive:public File
|
||||
FileHeader SubHead;
|
||||
CommentHeader CommHead;
|
||||
ProtectHeader ProtectHead;
|
||||
AVHeader AVHead;
|
||||
SignHeader SignHead;
|
||||
UnixOwnersHeader UOHead;
|
||||
MacFInfoHeader MACHead;
|
||||
EAHeader EAHead;
|
||||
StreamHeader StreamHead;
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ size_t Archive::ReadHeader()
|
||||
|
||||
CurBlockPos=Tell();
|
||||
|
||||
size_t ReadSize;
|
||||
// Other developers asked us to initialize it to suppress "may be used
|
||||
// uninitialized" warning in code below in some compilers.
|
||||
size_t ReadSize=0;
|
||||
|
||||
switch(Format)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
@@ -26,11 +29,18 @@ size_t Archive::ReadHeader()
|
||||
break;
|
||||
}
|
||||
|
||||
// It is important to check ReadSize>0 here, because it is normal
|
||||
// for RAR2 and RAR3 archives without end of archive block to have
|
||||
// NextBlockPos==CurBlockPos after the end of archive has reached.
|
||||
if (ReadSize>0 && NextBlockPos<=CurBlockPos)
|
||||
{
|
||||
BrokenHeaderMsg();
|
||||
return 0;
|
||||
ReadSize=0;
|
||||
}
|
||||
|
||||
if (ReadSize==0)
|
||||
CurHeaderType=HEAD_UNKNOWN;
|
||||
|
||||
return ReadSize;
|
||||
}
|
||||
|
||||
@@ -106,13 +116,24 @@ void Archive::BrokenHeaderMsg()
|
||||
}
|
||||
|
||||
|
||||
void Archive::UnkEncVerMsg(const wchar *Name)
|
||||
void Archive::UnkEncVerMsg(const wchar *Name,const wchar *Info)
|
||||
{
|
||||
uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name);
|
||||
uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name,Info);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
}
|
||||
|
||||
|
||||
// Return f in case of signed integer overflow or negative parameters
|
||||
// or v1+v2 otherwise. We use it for file offsets, which are signed
|
||||
// for compatibility with off_t in POSIX file functions and third party code.
|
||||
// Signed integer overflow is the undefined behavior according to
|
||||
// C++ standard and it causes fuzzers to complain.
|
||||
inline int64 SafeAdd(int64 v1,int64 v2,int64 f)
|
||||
{
|
||||
return v1>=0 && v2>=0 && v1<=MAX_INT64-v2 ? v1+v2 : f;
|
||||
}
|
||||
|
||||
|
||||
size_t Archive::ReadHeader15()
|
||||
{
|
||||
RawRead Raw(this);
|
||||
@@ -183,7 +204,7 @@ size_t Archive::ReadHeader15()
|
||||
if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0)
|
||||
{
|
||||
// Old style (up to RAR 2.9) main archive comment embedded into
|
||||
// the main archive header found. While we can read the entire
|
||||
// the main archive header found. While we can read the entire
|
||||
// ShortBlock.HeadSize here and remove this part of "if", it would be
|
||||
// waste of memory, because we'll read and process this comment data
|
||||
// in other function anyway and we do not need them here now.
|
||||
@@ -209,7 +230,7 @@ size_t Archive::ReadHeader15()
|
||||
Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0;
|
||||
Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0;
|
||||
MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
|
||||
|
||||
|
||||
// Only for encrypted 3.0+ archives. 2.x archives did not have this
|
||||
// flag, so for non-encrypted archives, we'll set it later based on
|
||||
// file attributes.
|
||||
@@ -236,7 +257,7 @@ size_t Archive::ReadHeader15()
|
||||
hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
|
||||
hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
|
||||
hd->Version=(hd->Flags & LHD_VERSION)!=0;
|
||||
|
||||
|
||||
hd->DataSize=Raw.Get4();
|
||||
uint LowUnpSize=Raw.Get4();
|
||||
hd->HostOS=Raw.Get1();
|
||||
@@ -246,17 +267,22 @@ size_t Archive::ReadHeader15()
|
||||
|
||||
uint FileTime=Raw.Get4();
|
||||
hd->UnpVer=Raw.Get1();
|
||||
|
||||
hd->Method=Raw.Get1()-0x30;
|
||||
size_t NameSize=Raw.Get2();
|
||||
hd->FileAttr=Raw.Get4();
|
||||
|
||||
// RAR15 did not use the special dictionary size to mark dirs.
|
||||
if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0)
|
||||
hd->Dir=true;
|
||||
|
||||
hd->CryptMethod=CRYPT_NONE;
|
||||
if (hd->Encrypted)
|
||||
switch(hd->UnpVer)
|
||||
{
|
||||
case 13: hd->CryptMethod=CRYPT_RAR13; break;
|
||||
case 15: hd->CryptMethod=CRYPT_RAR15; break;
|
||||
case 20:
|
||||
case 20:
|
||||
case 26: hd->CryptMethod=CRYPT_RAR20; break;
|
||||
default: hd->CryptMethod=CRYPT_RAR30; break;
|
||||
}
|
||||
@@ -278,7 +304,7 @@ size_t Archive::ReadHeader15()
|
||||
}
|
||||
|
||||
hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
|
||||
|
||||
|
||||
hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;
|
||||
|
||||
uint HighPackSize,HighUnpSize;
|
||||
@@ -288,7 +314,7 @@ size_t Archive::ReadHeader15()
|
||||
HighUnpSize=Raw.Get4();
|
||||
hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
HighPackSize=HighUnpSize=0;
|
||||
// UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
|
||||
@@ -308,17 +334,17 @@ size_t Archive::ReadHeader15()
|
||||
|
||||
if (FileBlock)
|
||||
{
|
||||
*hd->FileName=0;
|
||||
if ((hd->Flags & LHD_UNICODE)!=0)
|
||||
{
|
||||
EncodeFileName NameCoder;
|
||||
size_t Length=strlen(FileName);
|
||||
Length++;
|
||||
NameCoder.Decode(FileName,(byte *)FileName+Length,
|
||||
NameSize-Length,hd->FileName,
|
||||
ASIZE(hd->FileName));
|
||||
if (ReadNameSize>Length)
|
||||
NameCoder.Decode(FileName,ReadNameSize,(byte *)FileName+Length,
|
||||
ReadNameSize-Length,hd->FileName,
|
||||
ASIZE(hd->FileName));
|
||||
}
|
||||
else
|
||||
*hd->FileName=0;
|
||||
|
||||
if (*hd->FileName==0)
|
||||
ArcCharToWide(FileName,hd->FileName,ASIZE(hd->FileName),ACTW_OEM);
|
||||
@@ -343,17 +369,7 @@ size_t Archive::ReadHeader15()
|
||||
// They are stored after the file name and before salt.
|
||||
hd->SubData.Alloc(DataSize);
|
||||
Raw.GetB(&hd->SubData[0],DataSize);
|
||||
if (hd->CmpName(SUBHEAD_TYPE_RR))
|
||||
{
|
||||
byte *D=&hd->SubData[8];
|
||||
RecoverySize=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
|
||||
RecoverySize*=512; // Sectors to size.
|
||||
int64 CurPos=Tell();
|
||||
RecoveryPercent=ToPercent(RecoverySize,CurPos);
|
||||
// Round fractional percent exceeding .5 to upper value.
|
||||
if (ToPercent(RecoverySize+CurPos/200,CurPos)>RecoveryPercent)
|
||||
RecoveryPercent++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (hd->CmpName(SUBHEAD_TYPE_CMT))
|
||||
@@ -386,8 +402,8 @@ size_t Archive::ReadHeader15()
|
||||
if (rmode & 4)
|
||||
rlt.Second++;
|
||||
rlt.Reminder=0;
|
||||
int count=rmode&3;
|
||||
for (int J=0;J<count;J++)
|
||||
uint count=rmode&3;
|
||||
for (uint J=0;J<count;J++)
|
||||
{
|
||||
byte CurByte=Raw.Get1();
|
||||
rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
|
||||
@@ -397,7 +413,9 @@ size_t Archive::ReadHeader15()
|
||||
CurTime->SetLocal(&rlt);
|
||||
}
|
||||
}
|
||||
NextBlockPos+=hd->PackSize;
|
||||
// Set to 0 in case of overflow, so end of ReadHeader cares about it.
|
||||
NextBlockPos=SafeAdd(NextBlockPos,hd->PackSize,0);
|
||||
|
||||
bool CRCProcessedOnly=hd->CommentInHeader;
|
||||
ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly);
|
||||
if (hd->HeadCRC!=HeaderCRC)
|
||||
@@ -434,19 +452,6 @@ size_t Archive::ReadHeader15()
|
||||
CommHead.Method=Raw.Get1();
|
||||
CommHead.CommCRC=Raw.Get2();
|
||||
break;
|
||||
case HEAD3_SIGN:
|
||||
*(BaseBlock *)&SignHead=ShortBlock;
|
||||
SignHead.CreationTime=Raw.Get4();
|
||||
SignHead.ArcNameSize=Raw.Get2();
|
||||
SignHead.UserNameSize=Raw.Get2();
|
||||
break;
|
||||
case HEAD3_AV:
|
||||
*(BaseBlock *)&AVHead=ShortBlock;
|
||||
AVHead.UnpVer=Raw.Get1();
|
||||
AVHead.Method=Raw.Get1();
|
||||
AVHead.AVVer=Raw.Get1();
|
||||
AVHead.AVInfoCRC=Raw.Get4();
|
||||
break;
|
||||
case HEAD3_PROTECT:
|
||||
*(BaseBlock *)&ProtectHead=ShortBlock;
|
||||
ProtectHead.DataSize=Raw.Get4();
|
||||
@@ -455,9 +460,8 @@ size_t Archive::ReadHeader15()
|
||||
ProtectHead.TotalBlocks=Raw.Get4();
|
||||
Raw.GetB(ProtectHead.Mark,8);
|
||||
NextBlockPos+=ProtectHead.DataSize;
|
||||
RecoverySize=ProtectHead.RecSectors*512;
|
||||
break;
|
||||
case HEAD3_OLDSERVICE:
|
||||
case HEAD3_OLDSERVICE: // RAR 2.9 and earlier.
|
||||
*(BaseBlock *)&SubBlockHead=ShortBlock;
|
||||
SubBlockHead.DataSize=Raw.Get4();
|
||||
NextBlockPos+=SubBlockHead.DataSize;
|
||||
@@ -478,13 +482,6 @@ size_t Archive::ReadHeader15()
|
||||
UOHead.OwnerName[UOHead.OwnerNameSize]=0;
|
||||
UOHead.GroupName[UOHead.GroupNameSize]=0;
|
||||
break;
|
||||
case MAC_HEAD:
|
||||
*(SubBlockHeader *)&MACHead=SubBlockHead;
|
||||
MACHead.fileType=Raw.Get4();
|
||||
MACHead.fileCreator=Raw.Get4();
|
||||
break;
|
||||
case EA_HEAD:
|
||||
case BEEA_HEAD:
|
||||
case NTACL_HEAD:
|
||||
*(SubBlockHeader *)&EAHead=SubBlockHead;
|
||||
EAHead.UnpSize=Raw.Get4();
|
||||
@@ -512,7 +509,7 @@ size_t Archive::ReadHeader15()
|
||||
NextBlockPos+=Raw.Get4();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
ushort HeaderCRC=Raw.GetCRC15(false);
|
||||
|
||||
// Old AV header does not have header CRC properly set.
|
||||
@@ -524,7 +521,6 @@ size_t Archive::ReadHeader15()
|
||||
{
|
||||
// Last 7 bytes of recovered volume can contain zeroes, because
|
||||
// REV files store its own information (volume number, etc.) here.
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 Length=Tell();
|
||||
Seek(Length-7,SEEK_SET);
|
||||
Recovered=true;
|
||||
@@ -546,12 +542,6 @@ size_t Archive::ReadHeader15()
|
||||
}
|
||||
}
|
||||
|
||||
if (NextBlockPos<=CurBlockPos)
|
||||
{
|
||||
BrokenHeaderMsg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Raw.Size();
|
||||
}
|
||||
|
||||
@@ -567,7 +557,6 @@ size_t Archive::ReadHeader50()
|
||||
#if defined(RAR_NOCRYPT)
|
||||
return 0;
|
||||
#else
|
||||
RequestArcPassword();
|
||||
|
||||
byte HeadersInitV[SIZE_INITV];
|
||||
if (Read(HeadersInitV,SIZE_INITV)!=SIZE_INITV)
|
||||
@@ -576,15 +565,48 @@ size_t Archive::ReadHeader50()
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck);
|
||||
// Verify password validity.
|
||||
if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
|
||||
// We repeat the password request only for manually entered passwords
|
||||
// and not for -p<pwd>. Wrong password can be intentionally provided
|
||||
// in -p<pwd> to not stop batch processing for encrypted archives.
|
||||
bool GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet();
|
||||
|
||||
while (true) // Repeat the password prompt for wrong passwords.
|
||||
{
|
||||
uiMsg(UIERROR_BADPSW,FileName);
|
||||
FailedHeaderDecryption=true;
|
||||
ErrHandler.SetErrorCode(RARX_BADPWD);
|
||||
return 0;
|
||||
RequestArcPassword();
|
||||
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck);
|
||||
// Verify password validity.
|
||||
if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
|
||||
{
|
||||
if (GlobalPassword) // For -p<pwd> or Ctrl+P.
|
||||
{
|
||||
// This message is used by Android GUI to reset cached passwords.
|
||||
// Update appropriate code if changed.
|
||||
uiMsg(UIERROR_BADPSW,FileName,FileName);
|
||||
FailedHeaderDecryption=true;
|
||||
ErrHandler.SetErrorCode(RARX_BADPWD);
|
||||
return 0;
|
||||
}
|
||||
else // For passwords entered manually.
|
||||
{
|
||||
// This message is used by Android GUI and Windows GUI and SFX to
|
||||
// reset cached passwords. Update appropriate code if changed.
|
||||
uiMsg(UIWAIT_BADPSW,FileName,FileName);
|
||||
Cmd->Password.Clean();
|
||||
}
|
||||
|
||||
#ifdef RARDLL
|
||||
// Avoid new requests for unrar.dll to prevent the infinite loop
|
||||
// if app always returns the same password.
|
||||
ErrHandler.SetErrorCode(RARX_BADPWD);
|
||||
Cmd->DllError=ERAR_BAD_PASSWORD;
|
||||
ErrHandler.Exit(RARX_BADPWD);
|
||||
#else
|
||||
continue; // Request a password again.
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Raw.SetCrypt(&HeadersCrypt);
|
||||
@@ -592,8 +614,8 @@ size_t Archive::ReadHeader50()
|
||||
}
|
||||
|
||||
// Header size must not occupy more than 3 variable length integer bytes
|
||||
// resulting in 2 MB maximum header size, so here we read 4 byte CRC32
|
||||
// followed by 3 bytes or less of header size.
|
||||
// resulting in 2 MB maximum header size (MAX_HEADER_SIZE_RAR5),
|
||||
// so here we read 4 byte CRC32 followed by 3 bytes or less of header size.
|
||||
const size_t FirstReadSize=7; // Smallest possible block size.
|
||||
if (Raw.Read(FirstReadSize)<FirstReadSize)
|
||||
{
|
||||
@@ -621,7 +643,7 @@ size_t Archive::ReadHeader50()
|
||||
BrokenHeaderMsg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Raw.Read(SizeToRead);
|
||||
|
||||
if (Raw.Size()<HeaderSize)
|
||||
@@ -654,7 +676,7 @@ size_t Archive::ReadHeader50()
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64 ExtraSize=0;
|
||||
if ((ShortBlock.Flags & HFL_EXTRA)!=0)
|
||||
{
|
||||
@@ -670,7 +692,9 @@ size_t Archive::ReadHeader50()
|
||||
if ((ShortBlock.Flags & HFL_DATA)!=0)
|
||||
DataSize=Raw.GetV();
|
||||
|
||||
NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize)+DataSize;
|
||||
NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize);
|
||||
// Set to 0 in case of overflow, so end of ReadHeader cares about it.
|
||||
NextBlockPos=SafeAdd(NextBlockPos,DataSize,0);
|
||||
|
||||
switch(ShortBlock.HeaderType)
|
||||
{
|
||||
@@ -680,7 +704,9 @@ size_t Archive::ReadHeader50()
|
||||
uint CryptVersion=(uint)Raw.GetV();
|
||||
if (CryptVersion>CRYPT_VERSION)
|
||||
{
|
||||
UnkEncVerMsg(FileName);
|
||||
wchar Info[20];
|
||||
swprintf(Info,ASIZE(Info),L"h%u",CryptVersion);
|
||||
UnkEncVerMsg(FileName,Info);
|
||||
return 0;
|
||||
}
|
||||
uint EncFlags=(uint)Raw.GetV();
|
||||
@@ -688,9 +714,12 @@ size_t Archive::ReadHeader50()
|
||||
CryptHead.Lg2Count=Raw.Get1();
|
||||
if (CryptHead.Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
|
||||
{
|
||||
UnkEncVerMsg(FileName);
|
||||
wchar Info[20];
|
||||
swprintf(Info,ASIZE(Info),L"hc%u",CryptHead.Lg2Count);
|
||||
UnkEncVerMsg(FileName,Info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Raw.GetB(CryptHead.Salt,SIZE_SALT50);
|
||||
if (CryptHead.UsePswCheck)
|
||||
{
|
||||
@@ -734,14 +763,14 @@ size_t Archive::ReadHeader50()
|
||||
ProcessExtra50(&Raw,(size_t)ExtraSize,&MainHead);
|
||||
|
||||
#ifdef USE_QOPEN
|
||||
if (MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE)
|
||||
if (!ProhibitQOpen && MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE)
|
||||
{
|
||||
// We seek to QO block in the end of archive when processing
|
||||
// QOpen.Load, so we need to preserve current block positions
|
||||
// to not break normal archive processing by calling function.
|
||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
||||
|
||||
|
||||
QOpen.Init(this,false);
|
||||
QOpen.Load(MainHead.QOpenOffset);
|
||||
|
||||
@@ -766,7 +795,7 @@ size_t Archive::ReadHeader50()
|
||||
hd->PackSize=DataSize;
|
||||
hd->FileFlags=(uint)Raw.GetV();
|
||||
hd->UnpSize=Raw.GetV();
|
||||
|
||||
|
||||
hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0;
|
||||
if (hd->UnknownUnpSize)
|
||||
hd->UnpSize=INT64NDF;
|
||||
@@ -793,6 +822,8 @@ size_t Archive::ReadHeader50()
|
||||
// but it was already used in RAR 1.5 and Unpack needs to distinguish
|
||||
// them.
|
||||
hd->UnpVer=(CompInfo & 0x3f) + 50;
|
||||
if (hd->UnpVer!=50) // Only 5.0 compression is known now.
|
||||
hd->UnpVer=VER_UNKNOWN;
|
||||
|
||||
hd->HostOS=(byte)Raw.GetV();
|
||||
size_t NameSize=(size_t)Raw.GetV();
|
||||
@@ -851,7 +882,7 @@ size_t Archive::ReadHeader50()
|
||||
RecoverySize=Header.RecSectionSize*Header.RecCount;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (BadCRC) // Add the file name to broken header message displayed above.
|
||||
uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
|
||||
}
|
||||
@@ -868,11 +899,6 @@ size_t Archive::ReadHeader50()
|
||||
break;
|
||||
}
|
||||
|
||||
if (NextBlockPos<=CurBlockPos)
|
||||
{
|
||||
BrokenHeaderMsg();
|
||||
return 0;
|
||||
}
|
||||
return Raw.Size();
|
||||
}
|
||||
|
||||
@@ -908,11 +934,10 @@ void Archive::RequestArcPassword()
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
#else
|
||||
if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password) ||
|
||||
!Cmd->Password.IsSet())
|
||||
if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password))
|
||||
{
|
||||
Close();
|
||||
uiMsg(UIERROR_INCERRCOUNT);
|
||||
uiMsg(UIERROR_INCERRCOUNT); // Prevent archive deleting if delete after extraction is on.
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
#endif
|
||||
@@ -931,14 +956,17 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
Raw->SetPos(ExtraStart);
|
||||
while (Raw->DataLeft()>=2)
|
||||
{
|
||||
int64 FieldSize=Raw->GetV();
|
||||
if (FieldSize==0 || Raw->DataLeft()==0 || FieldSize>(int64)Raw->DataLeft())
|
||||
int64 FieldSize=Raw->GetV(); // Needs to be signed for check below and can be negative.
|
||||
if (FieldSize<=0 || Raw->DataLeft()==0 || FieldSize>(int64)Raw->DataLeft())
|
||||
break;
|
||||
size_t NextPos=size_t(Raw->GetPos()+FieldSize);
|
||||
uint64 FieldType=Raw->GetV();
|
||||
|
||||
FieldSize=int64(NextPos-Raw->GetPos()); // Field size without size and type fields.
|
||||
|
||||
if (FieldSize<0) // FieldType is longer than expected extra field size.
|
||||
break;
|
||||
|
||||
if (bb->HeaderType==HEAD_MAIN)
|
||||
{
|
||||
MainHeader *hd=(MainHeader *)bb;
|
||||
@@ -970,8 +998,12 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
{
|
||||
FileHeader *hd=(FileHeader *)bb;
|
||||
uint EncVersion=(uint)Raw->GetV();
|
||||
if (EncVersion > CRYPT_VERSION)
|
||||
UnkEncVerMsg(hd->FileName);
|
||||
if (EncVersion>CRYPT_VERSION)
|
||||
{
|
||||
wchar Info[20];
|
||||
swprintf(Info,ASIZE(Info),L"x%u",EncVersion);
|
||||
UnkEncVerMsg(hd->FileName,Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint Flags=(uint)Raw->GetV();
|
||||
@@ -979,7 +1011,11 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
hd->UseHashKey=(Flags & FHEXTRA_CRYPT_HASHMAC)!=0;
|
||||
hd->Lg2Count=Raw->Get1();
|
||||
if (hd->Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
|
||||
UnkEncVerMsg(hd->FileName);
|
||||
{
|
||||
wchar Info[20];
|
||||
swprintf(Info,ASIZE(Info),L"xc%u",hd->Lg2Count);
|
||||
UnkEncVerMsg(hd->FileName,Info);
|
||||
}
|
||||
Raw->GetB(hd->Salt,SIZE_SALT50);
|
||||
Raw->GetB(hd->InitV,SIZE_INITV);
|
||||
if (hd->UsePswCheck)
|
||||
@@ -1070,7 +1106,7 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
|
||||
wchar VerText[20];
|
||||
swprintf(VerText,ASIZE(VerText),L";%u",Version);
|
||||
wcsncatz(FileHead.FileName,VerText,ASIZE(FileHead.FileName));
|
||||
wcsncatz(hd->FileName,VerText,ASIZE(hd->FileName));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1136,7 +1172,7 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
// required. It did not hurt extraction, because UnRAR 5.21
|
||||
// and earlier ignored this field and set FieldSize as data left
|
||||
// in entire extra area. But now we set the correct field size
|
||||
// and set FieldSize based on actual extra record size,
|
||||
// and set FieldSize based on the actual extra record size,
|
||||
// so we need to adjust it for those older archives here.
|
||||
// FHEXTRA_SUBDATA in those archives always belongs to HEAD_SERVICE
|
||||
// and always is last in extra area. So since its size is by 1
|
||||
@@ -1145,6 +1181,9 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
if (bb->HeaderType==HEAD_SERVICE && Raw->Size()-NextPos==1)
|
||||
FieldSize++;
|
||||
|
||||
// We cannot allocate too much memory here, because above
|
||||
// we check FieldSize againt Raw size and we control that Raw size
|
||||
// is sensible when reading headers.
|
||||
hd->SubData.Alloc((size_t)FieldSize);
|
||||
Raw->GetB(hd->SubData.Addr(0),(size_t)FieldSize);
|
||||
}
|
||||
@@ -1168,6 +1207,8 @@ size_t Archive::ReadHeader14()
|
||||
byte Mark[4];
|
||||
Raw.GetB(Mark,4);
|
||||
uint HeadSize=Raw.Get2();
|
||||
if (HeadSize<7)
|
||||
return false;
|
||||
byte Flags=Raw.Get1();
|
||||
NextBlockPos=CurBlockPos+HeadSize;
|
||||
CurHeaderType=HEAD_MAIN;
|
||||
@@ -1189,6 +1230,8 @@ size_t Archive::ReadHeader14()
|
||||
FileHead.FileHash.Type=HASH_RAR14;
|
||||
FileHead.FileHash.CRC32=Raw.Get2();
|
||||
FileHead.HeadSize=Raw.Get2();
|
||||
if (FileHead.HeadSize<21)
|
||||
return false;
|
||||
uint FileTime=Raw.Get4();
|
||||
FileHead.FileAttr=Raw.Get1();
|
||||
FileHead.Flags=Raw.Get1()|LONG_BLOCK;
|
||||
@@ -1203,17 +1246,23 @@ size_t Archive::ReadHeader14()
|
||||
|
||||
FileHead.PackSize=FileHead.DataSize;
|
||||
FileHead.WinSize=0x10000;
|
||||
FileHead.Dir=(FileHead.FileAttr & 0x10)!=0;
|
||||
|
||||
FileHead.HostOS=HOST_MSDOS;
|
||||
FileHead.HSType=HSYS_WINDOWS;
|
||||
|
||||
FileHead.mtime.SetDos(FileTime);
|
||||
|
||||
Raw.Read(NameSize);
|
||||
|
||||
char FileName[NM];
|
||||
Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName)));
|
||||
FileName[NameSize]=0;
|
||||
size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
|
||||
Raw.GetB((byte *)FileName,ReadNameSize);
|
||||
FileName[ReadNameSize]=0;
|
||||
IntToExt(FileName,FileName,ASIZE(FileName));
|
||||
CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
|
||||
ConvertNameCase(FileHead.FileName);
|
||||
ConvertFileHeader(&FileHead);
|
||||
|
||||
if (Raw.Size()!=0)
|
||||
NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
|
||||
@@ -1260,7 +1309,7 @@ void Archive::ConvertAttributes()
|
||||
|
||||
if (mask == (mode_t) -1)
|
||||
{
|
||||
// umask call returns the current umask value. Argument (022) is not
|
||||
// umask call returns the current umask value. Argument (022) is not
|
||||
// really important here.
|
||||
mask = umask(022);
|
||||
|
||||
@@ -1308,8 +1357,6 @@ void Archive::ConvertAttributes()
|
||||
|
||||
void Archive::ConvertFileHeader(FileHeader *hd)
|
||||
{
|
||||
if (Format==RARFMT15 && hd->UnpVer<20 && (hd->FileAttr & 0x10))
|
||||
hd->Dir=true;
|
||||
if (hd->HSType==HSYS_UNKNOWN)
|
||||
if (hd->Dir)
|
||||
hd->FileAttr=0x10;
|
||||
@@ -1339,8 +1386,8 @@ void Archive::ConvertFileHeader(FileHeader *hd)
|
||||
|
||||
// ':' in file names is allowed in Unix, but not in Windows.
|
||||
// Even worse, file data will be written to NTFS stream on NTFS,
|
||||
// so automatic name correction on file create error in extraction
|
||||
// routine does not work. In Windows and DOS versions we better
|
||||
// so automatic name correction on file create error in extraction
|
||||
// routine does not work. In Windows and DOS versions we better
|
||||
// replace ':' now.
|
||||
if (*s==':')
|
||||
*s='_';
|
||||
@@ -1369,7 +1416,7 @@ int64 Archive::GetStartPos()
|
||||
}
|
||||
|
||||
|
||||
bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode)
|
||||
{
|
||||
if (BrokenHeader)
|
||||
{
|
||||
@@ -1417,6 +1464,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
|
||||
SubDataIO.EnableShowProgress(false);
|
||||
SubDataIO.SetFiles(this,DestFile);
|
||||
SubDataIO.SetTestMode(TestMode);
|
||||
SubDataIO.UnpVolume=SubHead.SplitAfter;
|
||||
SubDataIO.SetSubHeader(&SubHead,NULL);
|
||||
Unpack.SetDestSize(SubHead.UnpSize);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#define _RAR_BLAKE2_
|
||||
|
||||
#define BLAKE2_DIGEST_SIZE 32
|
||||
#define BLAKE2_THREADS_NUMBER 8
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
#include "cmdfilter.cpp"
|
||||
#include "cmdmix.cpp"
|
||||
|
||||
CommandData::CommandData()
|
||||
{
|
||||
Init();
|
||||
@@ -13,6 +16,7 @@ void CommandData::Init()
|
||||
*Command=0;
|
||||
*ArcName=0;
|
||||
FileLists=false;
|
||||
NoMoreSwitches=false;
|
||||
|
||||
ListMode=RCLM_AUTO;
|
||||
|
||||
@@ -96,7 +100,7 @@ void CommandData::ParseArg(wchar *Arg)
|
||||
else
|
||||
if (*Command==0)
|
||||
{
|
||||
wcsncpy(Command,Arg,ASIZE(Command));
|
||||
wcsncpyz(Command,Arg,ASIZE(Command));
|
||||
|
||||
|
||||
*Command=toupperw(*Command);
|
||||
@@ -119,6 +123,7 @@ void CommandData::ParseArg(wchar *Arg)
|
||||
wchar CmdChar=toupperw(*Command);
|
||||
bool Add=wcschr(L"AFUM",CmdChar)!=NULL;
|
||||
bool Extract=CmdChar=='X' || CmdChar=='E';
|
||||
bool Repair=CmdChar=='R' && Command[1]==0;
|
||||
if (EndSeparator && !Add)
|
||||
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
||||
else
|
||||
@@ -129,25 +134,15 @@ void CommandData::ParseArg(wchar *Arg)
|
||||
FindData FileData;
|
||||
bool Found=FindFile::FastFind(Arg,&FileData);
|
||||
if ((!Found || ListMode==RCLM_ACCEPT_LISTS) &&
|
||||
ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg))
|
||||
ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg+1))
|
||||
{
|
||||
FileLists=true;
|
||||
|
||||
RAR_CHARSET Charset=FilelistCharset;
|
||||
|
||||
#if defined(_WIN_ALL)
|
||||
// for compatibility reasons we use OEM encoding
|
||||
// in Win32 console version by default
|
||||
|
||||
// if (Charset==RCH_DEFAULT)
|
||||
// Charset=RCH_OEM;
|
||||
#endif
|
||||
|
||||
ReadTextFile(Arg+1,&FileArgs,false,true,Charset,true,true,true);
|
||||
ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true);
|
||||
|
||||
}
|
||||
else
|
||||
if (Found && FileData.IsDir && Extract && *ExtrPath==0)
|
||||
else // We use 'destpath\' when extracting and reparing.
|
||||
if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0)
|
||||
{
|
||||
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
||||
AddEndSlash(ExtrPath,ASIZE(ExtrPath));
|
||||
@@ -248,7 +243,7 @@ void CommandData::ReadConfig()
|
||||
if (C0=='R' && (C1=='R' || C1=='V'))
|
||||
Cmd[2]=0;
|
||||
wchar SwName[16+ASIZE(Cmd)];
|
||||
swprintf(SwName,ASIZE(SwName),L"switches_%s=",Cmd);
|
||||
swprintf(SwName,ASIZE(SwName),L"switches_%ls=",Cmd);
|
||||
size_t Length=wcslen(SwName);
|
||||
if (wcsnicomp(Str,SwName,Length)==0)
|
||||
ProcessSwitchesString(Str+Length);
|
||||
@@ -289,17 +284,24 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
ClearArc=true;
|
||||
break;
|
||||
case 'D':
|
||||
AppendArcNameToPath=true;
|
||||
if (Switch[2]==0)
|
||||
AppendArcNameToPath=APPENDARCNAME_DESTPATH;
|
||||
else
|
||||
if (Switch[2]=='1')
|
||||
AppendArcNameToPath=APPENDARCNAME_OWNDIR;
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case 'G':
|
||||
if (Switch[2]=='-' && Switch[3]==0)
|
||||
GenerateArcName=0;
|
||||
else
|
||||
{
|
||||
GenerateArcName=true;
|
||||
wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
||||
}
|
||||
if (toupperw(Switch[2])=='F')
|
||||
wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask));
|
||||
else
|
||||
{
|
||||
GenerateArcName=true;
|
||||
wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'I':
|
||||
@@ -311,7 +313,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
AddArcOnly=true;
|
||||
break;
|
||||
case 'P':
|
||||
wcscpy(ArcPath,Switch+2);
|
||||
wcsncpyz(ArcPath,Switch+2,ASIZE(ArcPath));
|
||||
break;
|
||||
case 'S':
|
||||
SyncFiles=true;
|
||||
@@ -374,11 +376,11 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
default:
|
||||
if (Switch[1]=='+')
|
||||
{
|
||||
InclFileAttr|=GetExclAttr(Switch+2);
|
||||
InclFileAttr|=GetExclAttr(Switch+2,InclDir);
|
||||
InclAttrSet=true;
|
||||
}
|
||||
else
|
||||
ExclFileAttr|=GetExclAttr(Switch+1);
|
||||
ExclFileAttr|=GetExclAttr(Switch+1,ExclDir);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -416,14 +418,17 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName));
|
||||
break;
|
||||
}
|
||||
if (wcsicomp(Switch+1,L"SND")==0)
|
||||
if (wcsnicomp(Switch+1,L"SND",3)==0)
|
||||
{
|
||||
Sound=true;
|
||||
Sound=Switch[4]=='-' ? SOUND_NOTIFY_OFF : SOUND_NOTIFY_ON;
|
||||
break;
|
||||
}
|
||||
if (wcsicomp(Switch+1,L"ERR")==0)
|
||||
{
|
||||
MsgStream=MSG_STDERR;
|
||||
// Set it immediately when parsing the command line, so it also
|
||||
// affects messages issued while parsing the command line.
|
||||
SetConsoleMsgStream(MSG_STDERR);
|
||||
break;
|
||||
}
|
||||
if (wcsnicomp(Switch+1,L"EML",3)==0)
|
||||
@@ -431,9 +436,15 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
wcsncpyz(EmailTo,Switch[4]!=0 ? Switch+4:L"@",ASIZE(EmailTo));
|
||||
break;
|
||||
}
|
||||
if (wcsicomp(Switch+1,L"M")==0)
|
||||
{
|
||||
MoreInfo=true;
|
||||
break;
|
||||
}
|
||||
if (wcsicomp(Switch+1,L"NUL")==0)
|
||||
{
|
||||
MsgStream=MSG_NULL;
|
||||
SetConsoleMsgStream(MSG_NULL);
|
||||
break;
|
||||
}
|
||||
if (toupperw(Switch[1])=='D')
|
||||
@@ -443,6 +454,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
{
|
||||
case 'Q':
|
||||
MsgStream=MSG_ERRONLY;
|
||||
SetConsoleMsgStream(MSG_ERRONLY);
|
||||
break;
|
||||
case 'C':
|
||||
DisableCopyright=true;
|
||||
@@ -456,9 +468,24 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (wcsicomp(Switch+1,L"OFF")==0)
|
||||
if (wcsnicomp(Switch+1,L"OFF",3)==0)
|
||||
{
|
||||
Shutdown=true;
|
||||
switch(Switch[4])
|
||||
{
|
||||
case 0:
|
||||
case '1':
|
||||
Shutdown=POWERMODE_OFF;
|
||||
break;
|
||||
case '2':
|
||||
Shutdown=POWERMODE_HIBERNATE;
|
||||
break;
|
||||
case '3':
|
||||
Shutdown=POWERMODE_SLEEP;
|
||||
break;
|
||||
case '4':
|
||||
Shutdown=POWERMODE_RESTART;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (wcsicomp(Switch+1,L"VER")==0)
|
||||
@@ -574,19 +601,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
{
|
||||
StringList *Args=toupperw(Switch[0])=='N' ? &InclArgs:&ExclArgs;
|
||||
if (Switch[1]=='@' && !IsWildcard(Switch))
|
||||
{
|
||||
RAR_CHARSET Charset=FilelistCharset;
|
||||
|
||||
#if defined(_WIN_ALL)
|
||||
// for compatibility reasons we use OEM encoding
|
||||
// in Win32 console version by default
|
||||
|
||||
// if (Charset==RCH_DEFAULT)
|
||||
// Charset=RCH_OEM;
|
||||
#endif
|
||||
|
||||
ReadTextFile(Switch+2,Args,false,true,Charset,true,true,true);
|
||||
}
|
||||
ReadTextFile(Switch+2,Args,false,true,FilelistCharset,true,true,true);
|
||||
else
|
||||
Args->AddString(Switch+1);
|
||||
}
|
||||
@@ -783,6 +798,9 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
AlreadyBad=true;
|
||||
break;
|
||||
}
|
||||
// Set it immediately when parsing the command line, so it also
|
||||
// affects messages issued while parsing the command line.
|
||||
SetConsoleRedirectCharset(RedirectCharset);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -798,51 +816,19 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
ArcTime=ARCTIME_LATEST;
|
||||
break;
|
||||
case 'O':
|
||||
FileTimeBefore.SetAgeText(Switch+2);
|
||||
SetTimeFilters(Switch+2,true,true);
|
||||
break;
|
||||
case 'N':
|
||||
FileTimeAfter.SetAgeText(Switch+2);
|
||||
SetTimeFilters(Switch+2,false,true);
|
||||
break;
|
||||
case 'B':
|
||||
FileTimeBefore.SetIsoText(Switch+2);
|
||||
SetTimeFilters(Switch+2,true,false);
|
||||
break;
|
||||
case 'A':
|
||||
FileTimeAfter.SetIsoText(Switch+2);
|
||||
SetTimeFilters(Switch+2,false,false);
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
EXTTIME_MODE Mode=EXTTIME_HIGH3;
|
||||
bool CommonMode=Switch[2]>='0' && Switch[2]<='4';
|
||||
if (CommonMode)
|
||||
Mode=(EXTTIME_MODE)(Switch[2]-'0');
|
||||
if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore.
|
||||
Mode=EXTTIME_HIGH3;
|
||||
if (Switch[2]=='-')
|
||||
Mode=EXTTIME_NONE;
|
||||
if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0)
|
||||
xmtime=xctime=xatime=Mode;
|
||||
else
|
||||
{
|
||||
if (Switch[3]>='0' && Switch[3]<='4')
|
||||
Mode=(EXTTIME_MODE)(Switch[3]-'0');
|
||||
if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore.
|
||||
Mode=EXTTIME_HIGH3;
|
||||
if (Switch[3]=='-')
|
||||
Mode=EXTTIME_NONE;
|
||||
switch(toupperw(Switch[2]))
|
||||
{
|
||||
case 'M':
|
||||
xmtime=Mode;
|
||||
break;
|
||||
case 'C':
|
||||
xctime=Mode;
|
||||
break;
|
||||
case 'A':
|
||||
xatime=Mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetStoreTimeMode(Switch+2);
|
||||
break;
|
||||
case '-':
|
||||
Test=false;
|
||||
@@ -890,7 +876,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
if (Switch[1]==0)
|
||||
{
|
||||
// If comment file is not specified, we read data from stdin.
|
||||
wcscpy(CommentFile,L"stdin");
|
||||
wcsncpyz(CommentFile,L"stdin",ASIZE(CommentFile));
|
||||
}
|
||||
else
|
||||
wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
|
||||
@@ -915,309 +901,6 @@ void CommandData::BadSwitch(const wchar *Switch)
|
||||
#endif
|
||||
|
||||
|
||||
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 (int J=0;J<sizeof(Win32Only)/sizeof(Win32Only[0]);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
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
// Return 'true' if we need to exclude the file from processing.
|
||||
bool CommandData::TimeCheck(RarTime &ft)
|
||||
{
|
||||
if (FileTimeBefore.IsSet() && ft>=FileTimeBefore)
|
||||
return true;
|
||||
if (FileTimeAfter.IsSet() && ft<=FileTimeAfter)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
#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
|
||||
|
||||
|
||||
|
||||
|
||||
int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
|
||||
wchar *MatchedArg,uint MatchedArgSize)
|
||||
{
|
||||
if (MatchedArg!=NULL && MatchedArgSize>0)
|
||||
*MatchedArg=0;
|
||||
if (wcslen(FileHead.FileName)>=NM)
|
||||
return 0;
|
||||
bool Dir=FileHead.Dir;
|
||||
if (ExclCheck(FileHead.FileName,Dir,false,true))
|
||||
return 0;
|
||||
#ifndef SFX_MODULE
|
||||
if (TimeCheck(FileHead.mtime))
|
||||
return 0;
|
||||
if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void CommandData::ProcessCommand()
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
@@ -1248,7 +931,10 @@ void CommandData::ProcessCommand()
|
||||
if (wcschr(L"AFUMD",*Command)==NULL)
|
||||
{
|
||||
if (GenerateArcName)
|
||||
GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false);
|
||||
{
|
||||
const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask;
|
||||
GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false);
|
||||
}
|
||||
|
||||
StringList ArcMasks;
|
||||
ArcMasks.AddString(ArcName);
|
||||
@@ -1267,7 +953,6 @@ void CommandData::ProcessCommand()
|
||||
case 'X':
|
||||
case 'E':
|
||||
case 'T':
|
||||
case 'I':
|
||||
{
|
||||
CmdExtract Extract(this);
|
||||
Extract.DoExtract();
|
||||
@@ -1310,7 +995,7 @@ bool CommandData::IsSwitch(int Ch)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint CommandData::GetExclAttr(const wchar *Str)
|
||||
uint CommandData::GetExclAttr(const wchar *Str,bool &Dir)
|
||||
{
|
||||
if (IsDigit(*Str))
|
||||
return wcstol(Str,NULL,0);
|
||||
@@ -1320,10 +1005,10 @@ uint CommandData::GetExclAttr(const wchar *Str)
|
||||
{
|
||||
switch(toupperw(*Str))
|
||||
{
|
||||
#ifdef _UNIX
|
||||
case 'D':
|
||||
Attr|=S_IFDIR;
|
||||
Dir=true;
|
||||
break;
|
||||
#ifdef _UNIX
|
||||
case 'V':
|
||||
Attr|=S_IFCHR;
|
||||
break;
|
||||
@@ -1337,9 +1022,6 @@ uint CommandData::GetExclAttr(const wchar *Str)
|
||||
case 'S':
|
||||
Attr|=0x4;
|
||||
break;
|
||||
case 'D':
|
||||
Attr|=0x10;
|
||||
break;
|
||||
case 'A':
|
||||
Attr|=0x20;
|
||||
break;
|
||||
|
||||
@@ -6,13 +6,19 @@
|
||||
|
||||
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);
|
||||
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;
|
||||
@@ -34,11 +40,11 @@ class CommandData:public RAROptions
|
||||
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 &ft);
|
||||
bool TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta);
|
||||
bool SizeCheck(int64 Size);
|
||||
bool AnyFiltersActive();
|
||||
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH,
|
||||
wchar *MatchedArg=NULL,uint MatchedArgSize=0);
|
||||
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);
|
||||
|
||||
352
unrar/cmdfilter.cpp
Normal file
352
unrar/cmdfilter.cpp
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
unrar/cmdmix.cpp
Normal file
118
unrar/cmdmix.cpp
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
|
||||
}
|
||||
|
||||
@@ -6,7 +6,16 @@
|
||||
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;
|
||||
|
||||
|
||||
@@ -49,9 +49,14 @@ void InitConsole()
|
||||
}
|
||||
|
||||
|
||||
void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset)
|
||||
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream)
|
||||
{
|
||||
::MsgStream=MsgStream;
|
||||
}
|
||||
|
||||
|
||||
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset)
|
||||
{
|
||||
::RedirectCharset=RedirectCharset;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#define _RAR_CONSIO_
|
||||
|
||||
void InitConsole();
|
||||
void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset);
|
||||
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream);
|
||||
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset);
|
||||
void OutComment(const wchar *Comment,size_t Size);
|
||||
|
||||
#ifndef SILENT
|
||||
|
||||
@@ -66,14 +66,14 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
||||
uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
|
||||
#else
|
||||
StartCRC ^= *(uint32 *) Data;
|
||||
uint NextData = *(uint32 *) (Data +4);
|
||||
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[2][(byte)(NextData >> 8) ] ^
|
||||
crc_tables[1][(byte)(NextData >> 16)] ^
|
||||
crc_tables[0][(byte)(NextData >> 24)];
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co
|
||||
sha1_context c;
|
||||
sha1_init(&c);
|
||||
|
||||
const int HashRounds=0x40000;
|
||||
for (int I=0;I<HashRounds;I++)
|
||||
const uint HashRounds=0x40000;
|
||||
for (uint I=0;I<HashRounds;I++)
|
||||
{
|
||||
sha1_process_rar29( &c, RawPsw, RawLength );
|
||||
byte PswNum[3];
|
||||
@@ -47,8 +47,8 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co
|
||||
}
|
||||
uint32 digest[5];
|
||||
sha1_done( &c, digest );
|
||||
for (int I=0;I<4;I++)
|
||||
for (int J=0;J<4;J++)
|
||||
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;
|
||||
|
||||
@@ -35,11 +35,14 @@ 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;
|
||||
@@ -92,36 +95,50 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
r->Flags=0;
|
||||
|
||||
if (Data->Arc.Volume)
|
||||
r->Flags|=0x01;
|
||||
r->Flags|=ROADF_VOLUME;
|
||||
if (Data->Arc.MainComment)
|
||||
r->Flags|=ROADF_COMMENT;
|
||||
if (Data->Arc.Locked)
|
||||
r->Flags|=0x04;
|
||||
r->Flags|=ROADF_LOCK;
|
||||
if (Data->Arc.Solid)
|
||||
r->Flags|=0x08;
|
||||
r->Flags|=ROADF_SOLID;
|
||||
if (Data->Arc.NewNumbering)
|
||||
r->Flags|=0x10;
|
||||
r->Flags|=ROADF_NEWNUMBERING;
|
||||
if (Data->Arc.Signed)
|
||||
r->Flags|=0x20;
|
||||
r->Flags|=ROADF_SIGNED;
|
||||
if (Data->Arc.Protected)
|
||||
r->Flags|=0x40;
|
||||
r->Flags|=ROADF_RECOVERY;
|
||||
if (Data->Arc.Encrypted)
|
||||
r->Flags|=0x80;
|
||||
r->Flags|=ROADF_ENCHEADERS;
|
||||
if (Data->Arc.FirstVolume)
|
||||
r->Flags|=0x100;
|
||||
r->Flags|=ROADF_FIRSTVOLUME;
|
||||
|
||||
Array<wchar> CmtDataW;
|
||||
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
|
||||
{
|
||||
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;
|
||||
if (r->CmtBufW!=NULL)
|
||||
{
|
||||
CmtDataW.Push(0);
|
||||
size_t Size=wcslen(&CmtDataW[0])+1;
|
||||
|
||||
r->Flags|=2;
|
||||
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
||||
if (Size<=r->CmtBufSize)
|
||||
r->CmtBuf[r->CmtSize-1]=0;
|
||||
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;
|
||||
@@ -151,9 +168,16 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
int PASCAL RARCloseArchive(HANDLE hArcData)
|
||||
{
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
bool Success=Data==NULL ? false:Data->Arc.Close();
|
||||
delete Data;
|
||||
return Success ? ERAR_SUCCESS : ERAR_ECLOSE;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,10 +268,7 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
|
||||
D->UnpSizeHigh=uint(hd->UnpSize>>32);
|
||||
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
|
||||
if (Data->Arc.Format==RARFMT50)
|
||||
D->UnpVer=Data->Arc.FileHead.UnpVer==0 ? 50 : 200; // If it is not 0, just set it to something big.
|
||||
else
|
||||
D->UnpVer=Data->Arc.FileHead.UnpVer;
|
||||
D->UnpVer=Data->Arc.FileHead.UnpVer;
|
||||
D->FileCRC=hd->FileHash.CRC32;
|
||||
D->FileTime=hd->mtime.GetDos();
|
||||
|
||||
@@ -363,7 +384,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
||||
if (DestNameW!=NULL)
|
||||
wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
|
||||
|
||||
wcscpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T");
|
||||
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);
|
||||
@@ -398,13 +419,13 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
||||
|
||||
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
|
||||
{
|
||||
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL));
|
||||
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));
|
||||
return ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName);
|
||||
}
|
||||
|
||||
|
||||
@@ -430,16 +451,16 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro
|
||||
}
|
||||
|
||||
|
||||
#ifndef RAR_NOCRYPT
|
||||
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()
|
||||
|
||||
@@ -5,6 +5,7 @@ EXPORTS
|
||||
RARReadHeader
|
||||
RARReadHeaderEx
|
||||
RARProcessFile
|
||||
RARProcessFileW
|
||||
RARSetCallback
|
||||
RARSetChangeVolProc
|
||||
RARSetProcessDataProc
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef _UNRAR_DLL_
|
||||
#define _UNRAR_DLL_
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define ERAR_SUCCESS 0
|
||||
#define ERAR_END_ARCHIVE 10
|
||||
@@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM
|
||||
#define ROADF_ENCHEADERS 0x0080
|
||||
#define ROADF_FIRSTVOLUME 0x0100
|
||||
|
||||
#define ROADOF_KEEPBROKEN 0x0001
|
||||
|
||||
struct RAROpenArchiveDataEx
|
||||
{
|
||||
char *ArcName;
|
||||
@@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx
|
||||
unsigned int Flags;
|
||||
UNRARCALLBACK Callback;
|
||||
LPARAM UserData;
|
||||
unsigned int Reserved[28];
|
||||
unsigned int OpFlags;
|
||||
wchar_t *CmtBufW;
|
||||
unsigned int Reserved[25];
|
||||
};
|
||||
|
||||
enum UNRARCALLBACK_MESSAGES {
|
||||
@@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion();
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma pack()
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
||||
10
unrar/dll.rc
10
unrar/dll.rc
@@ -2,8 +2,8 @@
|
||||
#include <commctrl.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 5, 50, 5, 2378
|
||||
PRODUCTVERSION 5, 50, 5, 2378
|
||||
FILEVERSION 5, 91, 100, 3470
|
||||
PRODUCTVERSION 5, 91, 100, 3470
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
{
|
||||
@@ -14,9 +14,9 @@ FILETYPE VFT_APP
|
||||
VALUE "CompanyName", "Alexander Roshal\0"
|
||||
VALUE "ProductName", "RAR decompression library\0"
|
||||
VALUE "FileDescription", "RAR decompression library\0"
|
||||
VALUE "FileVersion", "5.50.5\0"
|
||||
VALUE "ProductVersion", "5.50.5\0"
|
||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2017\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"
|
||||
}
|
||||
}
|
||||
|
||||
13
unrar/dll_nocrypt.def
Normal file
13
unrar/dll_nocrypt.def
Normal file
@@ -0,0 +1,13 @@
|
||||
EXPORTS
|
||||
RAROpenArchive
|
||||
RAROpenArchiveEx
|
||||
RARCloseArchive
|
||||
RARReadHeader
|
||||
RARReadHeaderEx
|
||||
RARProcessFile
|
||||
RARProcessFileW
|
||||
RARSetCallback
|
||||
RARSetChangeVolProc
|
||||
RARSetProcessDataProc
|
||||
; RARSetPassword
|
||||
RARGetDllVersion
|
||||
@@ -11,41 +11,53 @@ EncodeFileName::EncodeFileName()
|
||||
|
||||
|
||||
|
||||
void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,
|
||||
size_t MaxDecSize)
|
||||
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=EncName[EncPos++];
|
||||
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)
|
||||
if ((Length & 0x80)!=0)
|
||||
{
|
||||
if (EncPos>=EncSize)
|
||||
break;
|
||||
byte Correction=EncName[EncPos++];
|
||||
for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
|
||||
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;Length--,DecPos++)
|
||||
for (Length+=2;Length>0 && DecPos<MaxDecSize && DecPos<NameSize;Length--,DecPos++)
|
||||
NameW[DecPos]=Name[DecPos];
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -14,7 +14,7 @@ class EncodeFileName
|
||||
public:
|
||||
EncodeFileName();
|
||||
size_t Encode(char *Name,wchar *NameW,byte *EncName);
|
||||
void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
|
||||
void Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,9 +41,12 @@ void ErrorHandler::CloseError(const wchar *FileName)
|
||||
uiMsg(UIERROR_FILECLOSE,FileName);
|
||||
SysErrMsg();
|
||||
}
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Exit(RARX_FATAL);
|
||||
#endif
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,6 +158,7 @@ void ErrorHandler::OpenErrorMsg(const wchar *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);
|
||||
@@ -267,6 +271,7 @@ void _stdfunction ProcessSignal(int SigType)
|
||||
#endif
|
||||
|
||||
ErrHandler.UserBreak=true;
|
||||
ErrHandler.SetDisableShutdown();
|
||||
mprintf(St(MBreak));
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
@@ -290,7 +295,7 @@ void _stdfunction ProcessSignal(int SigType)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_MSC_VER)
|
||||
// never reached, just to avoid a compiler warning
|
||||
// Never reached, just to avoid a compiler warning
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
@@ -322,36 +327,15 @@ void ErrorHandler::Throw(RAR_EXIT Code)
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::SysErrMsg()
|
||||
bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
|
||||
{
|
||||
#if !defined(SFX_MODULE) && !defined(SILENT)
|
||||
#ifndef SILENT
|
||||
#ifdef _WIN_ALL
|
||||
wchar *lpMsgBuf=NULL;
|
||||
int ErrType=GetLastError();
|
||||
if (ErrType!=0 && FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,ErrType,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf,0,NULL))
|
||||
{
|
||||
wchar *CurMsg=lpMsgBuf;
|
||||
while (CurMsg!=NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
LocalFree( lpMsgBuf );
|
||||
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)
|
||||
@@ -360,12 +344,46 @@ void ErrorHandler::SysErrMsg()
|
||||
char *err=strerror(errno);
|
||||
if (err!=NULL)
|
||||
{
|
||||
wchar Msg[1024];
|
||||
CharToWide(err,Msg,ASIZE(Msg));
|
||||
uiMsg(UIERROR_SYSERRMSG,Msg);
|
||||
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
|
||||
}
|
||||
|
||||
@@ -56,10 +56,12 @@ class ErrorHandler
|
||||
uint GetErrorCount() {return ErrCount;}
|
||||
void SetSignalHandlers(bool Enable);
|
||||
void Throw(RAR_EXIT Code);
|
||||
void SetSilent(bool Mode) {Silent=Mode;};
|
||||
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.
|
||||
|
||||
@@ -93,6 +93,25 @@ static int CalcAllowedDepth(const wchar *Name)
|
||||
}
|
||||
|
||||
|
||||
// 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 \\?\.
|
||||
@@ -100,7 +119,25 @@ bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *Pr
|
||||
// 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.
|
||||
@@ -119,17 +156,6 @@ bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *Pr
|
||||
}
|
||||
int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName);
|
||||
|
||||
// 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++;
|
||||
}
|
||||
return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ void CmdExtract::DoExtract()
|
||||
{
|
||||
if (Cmd->ManualPassword)
|
||||
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
||||
|
||||
ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit().
|
||||
while (true)
|
||||
{
|
||||
EXTRACT_ARC_CODE Code=ExtractArchive();
|
||||
@@ -59,7 +61,11 @@ void CmdExtract::DoExtract()
|
||||
{
|
||||
if (!PasswordCancelled)
|
||||
uiMsg(UIERROR_NOFILESTOEXTRACT,ArcName);
|
||||
ErrHandler.SetErrorCode(RARX_NOFILES);
|
||||
|
||||
// Other error codes may explain a reason of "no files extracted" clearer,
|
||||
// so set it only if no other errors found (wrong mask set by user).
|
||||
if (ErrHandler.GetErrorCode()==RARX_SUCCESS)
|
||||
ErrHandler.SetErrorCode(RARX_NOFILES);
|
||||
}
|
||||
else
|
||||
if (!Cmd->DisableDone)
|
||||
@@ -83,13 +89,12 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc)
|
||||
FirstFile=true;
|
||||
#endif
|
||||
|
||||
PasswordAll=(Cmd->Password.IsSet());
|
||||
GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet();
|
||||
|
||||
DataIO.UnpVolume=false;
|
||||
|
||||
PrevProcessed=false;
|
||||
AllMatchesExact=true;
|
||||
ReconstructDone=false;
|
||||
AnySolidDataUnpackedWell=false;
|
||||
|
||||
StartTime.SetCurrentTime();
|
||||
@@ -157,7 +162,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
||||
// This size is necessary to display the correct total progress indicator.
|
||||
|
||||
wchar NextName[NM];
|
||||
wcscpy(NextName,Arc.FileName);
|
||||
wcsncpyz(NextName,Arc.FileName,ASIZE(NextName));
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -226,18 +231,6 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
||||
|
||||
bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
{
|
||||
// We can get negative sizes in corrupt archive and it is unacceptable
|
||||
// for size comparisons in CmdExtract::UnstoreFile and ComprDataIO::UnpRead,
|
||||
// where we cast sizes to size_t and can exceed another read or available
|
||||
// size. We could fix it when reading an archive. But we prefer to do it
|
||||
// here, because this function is called directly in unrar.dll, so we fix
|
||||
// bad parameters passed to dll. Also we want to see real negative sizes
|
||||
// in the listing of corrupt archive.
|
||||
if (Arc.FileHead.PackSize<0)
|
||||
Arc.FileHead.PackSize=0;
|
||||
if (Arc.FileHead.UnpSize<0)
|
||||
Arc.FileHead.UnpSize=0;
|
||||
|
||||
wchar Command=Cmd->Command[0];
|
||||
if (HeaderSize==0)
|
||||
if (DataIO.UnpVolume)
|
||||
@@ -245,8 +238,8 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
#ifdef NOVOLUME
|
||||
return false;
|
||||
#else
|
||||
// Supposing we unpack an old RAR volume without end of archive record
|
||||
// and last file is not split between volumes.
|
||||
// Supposing we unpack an old RAR volume without the end of archive
|
||||
// record and last file is not split between volumes.
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
@@ -256,11 +249,12 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||
if (HeaderType!=HEAD_FILE)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
if (HeaderType==HEAD3_OLDSERVICE && PrevProcessed)
|
||||
if (Arc.Format==RARFMT15 && HeaderType==HEAD3_OLDSERVICE && PrevProcessed)
|
||||
SetExtraInfo20(Cmd,Arc,DestFileName);
|
||||
#endif
|
||||
if (HeaderType==HEAD_SERVICE && PrevProcessed)
|
||||
@@ -268,15 +262,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
if (HeaderType==HEAD_ENDARC)
|
||||
if (Arc.EndArcHead.NextVolume)
|
||||
{
|
||||
#ifndef NOVOLUME
|
||||
#ifdef NOVOLUME
|
||||
return false;
|
||||
#else
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
Arc.Seek(Arc.CurBlockPos,SEEK_SET);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@@ -285,6 +281,19 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
}
|
||||
PrevProcessed=false;
|
||||
|
||||
// We can get negative sizes in corrupt archive and it is unacceptable
|
||||
// for size comparisons in ComprDataIO::UnpRead, where we cast sizes
|
||||
// to size_t and can exceed another read or available size. We could fix it
|
||||
// when reading an archive. But we prefer to do it here, because this
|
||||
// function is called directly in unrar.dll, so we fix bad parameters
|
||||
// passed to dll. Also we want to see real negative sizes in the listing
|
||||
// of corrupt archive. To prevent uninitialized data access perform
|
||||
// these checks after rejecting zero length and non-file headers above.
|
||||
if (Arc.FileHead.PackSize<0)
|
||||
Arc.FileHead.PackSize=0;
|
||||
if (Arc.FileHead.UnpSize<0)
|
||||
Arc.FileHead.UnpSize=0;
|
||||
|
||||
if (!Cmd->Recurse && MatchedArgs>=Cmd->FileArgs.ItemsCount() && AllMatchesExact)
|
||||
return false;
|
||||
|
||||
@@ -292,7 +301,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
|
||||
bool EqualNames=false;
|
||||
wchar MatchedArg[NM];
|
||||
int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,MatchedArg,ASIZE(MatchedArg));
|
||||
int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,0,MatchedArg,ASIZE(MatchedArg));
|
||||
bool MatchFound=MatchNumber!=0;
|
||||
#ifndef SFX_MODULE
|
||||
if (Cmd->ExclPath==EXCL_BASEPATH)
|
||||
@@ -317,6 +326,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
|
||||
if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
||||
{
|
||||
wcsncpyz(Cmd->ArcName,ArcName,ASIZE(ArcName)); // For GUI "Delete archive after extraction".
|
||||
// If first volume name does not match the current name and if such
|
||||
// volume name really exists, let's unpack from this first volume.
|
||||
Repeat=true;
|
||||
@@ -338,7 +348,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
#endif
|
||||
|
||||
wchar ArcFileName[NM];
|
||||
ConvertPath(Arc.FileHead.FileName,ArcFileName);
|
||||
ConvertPath(Arc.FileHead.FileName,ArcFileName,ASIZE(ArcFileName));
|
||||
|
||||
if (Arc.FileHead.Version)
|
||||
{
|
||||
@@ -427,7 +437,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
return !Arc.Solid; // Can try extracting next file only in non-solid archive.
|
||||
}
|
||||
|
||||
while (true) // Repeat password prompt in case of wrong password here.
|
||||
while (true) // Repeat the password prompt for wrong and empty passwords.
|
||||
{
|
||||
if (Arc.FileHead.Encrypted)
|
||||
{
|
||||
@@ -445,21 +455,8 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
// Skip only the current encrypted file if empty password is entered.
|
||||
// Actually our "cancel" code above intercepts empty passwords too now,
|
||||
// so we keep the code below just in case we'll decide process empty
|
||||
// and cancelled passwords differently sometimes.
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_MISSING_PASSWORD;
|
||||
#endif
|
||||
ExtrFile=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set a password before creating the file, so we can skip creating
|
||||
// in case of wrong password.
|
||||
SecPassword FilePassword=Cmd->Password;
|
||||
@@ -479,12 +476,24 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 &&
|
||||
!Arc.BrokenHeader)
|
||||
{
|
||||
uiMsg(UIWAIT_BADPSW,ArcFileName);
|
||||
|
||||
if (!PasswordAll) // If entered manually and not through -p<pwd>.
|
||||
if (GlobalPassword) // For -p<pwd> or Ctrl+P to avoid the infinite loop.
|
||||
{
|
||||
// This message is used by Android GUI to reset cached passwords.
|
||||
// Update appropriate code if changed.
|
||||
uiMsg(UIERROR_BADPSW,Arc.FileName,ArcFileName);
|
||||
}
|
||||
else // For passwords entered manually.
|
||||
{
|
||||
// This message is used by Android GUI and Windows GUI and SFX to
|
||||
// reset cached passwords. Update appropriate code if changed.
|
||||
uiMsg(UIWAIT_BADPSW,Arc.FileName,ArcFileName);
|
||||
Cmd->Password.Clean();
|
||||
|
||||
// Avoid new requests for unrar.dll to prevent the infinite loop
|
||||
// if app always returns the same password.
|
||||
#ifndef RARDLL
|
||||
continue; // Request a password again.
|
||||
#endif
|
||||
}
|
||||
#ifdef RARDLL
|
||||
// If we already have ERAR_EOPEN as result of missing volume,
|
||||
@@ -608,11 +617,14 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!TestMode && !Arc.BrokenHeader &&
|
||||
(Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize &&
|
||||
uint64 Preallocated=0;
|
||||
if (!TestMode && !Arc.BrokenHeader && Arc.FileHead.UnpSize>1000000 &&
|
||||
Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize &&
|
||||
(Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
|
||||
{
|
||||
CurFile.Prealloc(Arc.FileHead.UnpSize);
|
||||
|
||||
Preallocated=Arc.FileHead.UnpSize;
|
||||
}
|
||||
CurFile.SetAllowDelete(!Cmd->KeepBroken);
|
||||
|
||||
bool FileCreateMode=!TestMode && !SkipSolid && Command!='P';
|
||||
@@ -724,37 +736,52 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
else
|
||||
mprintf(L"\b\b\b\b\b ");
|
||||
|
||||
// If we successfully unpacked a hard link, we wish to set its file
|
||||
// attributes. Hard link shares file metadata with link target,
|
||||
// so we do not need to set link time or owner. But when we overwrite
|
||||
// an existing link, we can call PrepareToDelete(), which affects
|
||||
// link target attributes as well. So we set link attributes to restore
|
||||
// both target and link attributes if PrepareToDelete() changed them.
|
||||
bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess;
|
||||
|
||||
if (!TestMode && (Command=='X' || Command=='E') &&
|
||||
(!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
||||
(!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
||||
(!BrokenFile || Cmd->KeepBroken))
|
||||
{
|
||||
// We could preallocate more space that really written to broken file.
|
||||
if (BrokenFile)
|
||||
CurFile.Truncate();
|
||||
// Below we use DestFileName instead of CurFile.FileName,
|
||||
// so we can set file attributes also for hard links, which do not
|
||||
// have the open CurFile. These strings are the same for other items.
|
||||
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
if (Cmd->ClearArc)
|
||||
Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
|
||||
#endif
|
||||
if (!SetAttrOnly)
|
||||
{
|
||||
// We could preallocate more space that really written to broken file
|
||||
// or file with crafted header.
|
||||
if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated))
|
||||
CurFile.Truncate();
|
||||
|
||||
|
||||
CurFile.SetOpenFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||
CurFile.Close();
|
||||
CurFile.SetOpenFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||
CurFile.Close();
|
||||
|
||||
SetFileHeaderExtra(Cmd,Arc,DestFileName);
|
||||
|
||||
CurFile.SetCloseFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||
}
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
if (Cmd->SetCompressedAttr &&
|
||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0)
|
||||
SetFileCompression(CurFile.FileName,true);
|
||||
SetFileCompression(DestFileName,true);
|
||||
if (Cmd->ClearArc)
|
||||
Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
|
||||
#endif
|
||||
SetFileHeaderExtra(Cmd,Arc,CurFile.FileName);
|
||||
|
||||
CurFile.SetCloseFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||
if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr))
|
||||
uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName);
|
||||
if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr))
|
||||
uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName);
|
||||
|
||||
PrevProcessed=true;
|
||||
}
|
||||
@@ -779,19 +806,18 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
|
||||
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize)
|
||||
{
|
||||
// 512 KB and larger buffer reported to reduce performance on old XP
|
||||
// computers with WDC WD2000JD HDD. According to test made by user
|
||||
// 256 KB buffer is optimal.
|
||||
Array<byte> Buffer(0x40000);
|
||||
while (1)
|
||||
Array<byte> Buffer(File::CopyBufferSize());
|
||||
while (true)
|
||||
{
|
||||
uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
|
||||
if (Code==0 || (int)Code==-1)
|
||||
int ReadSize=DataIO.UnpRead(&Buffer[0],Buffer.Size());
|
||||
if (ReadSize<=0)
|
||||
break;
|
||||
Code=Code<DestUnpSize ? Code:(uint)DestUnpSize;
|
||||
DataIO.UnpWrite(&Buffer[0],Code);
|
||||
if (DestUnpSize>=0)
|
||||
DestUnpSize-=Code;
|
||||
int WriteSize=ReadSize<DestUnpSize ? ReadSize:(int)DestUnpSize;
|
||||
if (WriteSize>0)
|
||||
{
|
||||
DataIO.UnpWrite(&Buffer[0],WriteSize);
|
||||
DestUnpSize-=WriteSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,9 +872,12 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
||||
}
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
if (Cmd->AppendArcNameToPath)
|
||||
if (Cmd->AppendArcNameToPath!=APPENDARCNAME_NONE)
|
||||
{
|
||||
wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
|
||||
if (Cmd->AppendArcNameToPath==APPENDARCNAME_DESTPATH)
|
||||
wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
|
||||
else
|
||||
wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); // To archive own dir.
|
||||
SetExt(DestName,NULL,DestSize);
|
||||
AddEndSlash(DestName,DestSize);
|
||||
}
|
||||
@@ -958,19 +987,21 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
|
||||
{
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password) || !Cmd->Password.IsSet())
|
||||
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/)
|
||||
{
|
||||
// Suppress "test is ok" message in GUI if user entered
|
||||
// an empty password or cancelled a password prompt.
|
||||
uiMsg(UIERROR_INCERRCOUNT);
|
||||
|
||||
// Suppress "test is ok" message if user cancelled the password prompt.
|
||||
// 2019.03.23: If some archives are tested ok and prompt is cancelled for others,
|
||||
// do we really need to suppress "test is ok"? Also if we set an empty password
|
||||
// and "Use for all archives" in WinRAR Ctrl+P and skip some encrypted archives.
|
||||
// We commented out this UIERROR_INCERRCOUNT for now.
|
||||
// uiMsg(UIERROR_INCERRCOUNT);
|
||||
return false;
|
||||
}
|
||||
Cmd->ManualPassword=true;
|
||||
}
|
||||
#if !defined(SILENT)
|
||||
else
|
||||
if (!PasswordAll && !Arc.FileHead.Solid)
|
||||
if (!GlobalPassword && !Arc.FileHead.Solid)
|
||||
{
|
||||
eprintf(St(MUseCurPsw),ArcFileName);
|
||||
switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll)))
|
||||
@@ -982,7 +1013,7 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
|
||||
return false;
|
||||
break;
|
||||
case 3:
|
||||
PasswordAll=true;
|
||||
GlobalPassword=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1079,7 +1110,7 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
|
||||
{
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
if (Cmd->SetCompressedAttr &&
|
||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
|
||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()!=WNT_NONE)
|
||||
SetFileCompression(DestFileName,true);
|
||||
#endif
|
||||
SetFileHeaderExtra(Cmd,Arc,DestFileName);
|
||||
|
||||
@@ -43,7 +43,7 @@ class CmdExtract
|
||||
|
||||
wchar ArcName[NM];
|
||||
|
||||
bool PasswordAll;
|
||||
bool GlobalPassword;
|
||||
bool PrevProcessed; // If previous file was successfully extracted or tested.
|
||||
wchar DestFileName[NM];
|
||||
bool PasswordCancelled;
|
||||
|
||||
@@ -13,6 +13,7 @@ File::File()
|
||||
OpenShared=false;
|
||||
AllowDelete=true;
|
||||
AllowExceptions=true;
|
||||
PreserveAtime=false;
|
||||
#ifdef _WIN_ALL
|
||||
NoSequentialRead=false;
|
||||
CreateMode=FMF_UNDEFINED;
|
||||
@@ -56,6 +57,9 @@ bool File::Open(const wchar *Name,uint Mode)
|
||||
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;
|
||||
@@ -86,6 +90,11 @@ bool File::Open(const wchar *Name,uint Mode)
|
||||
}
|
||||
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);
|
||||
@@ -94,6 +103,11 @@ bool File::Open(const wchar *Name,uint Mode)
|
||||
#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));
|
||||
@@ -173,7 +187,7 @@ bool File::Create(const wchar *Name,uint Mode)
|
||||
wchar *LastChar=PointToLastChar(Name);
|
||||
bool Special=*LastChar=='.' || *LastChar==' ';
|
||||
|
||||
if (Special)
|
||||
if (Special && (Mode & FMF_STANDARDNAMES)==0)
|
||||
hFile=FILE_BAD_HANDLE;
|
||||
else
|
||||
hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
|
||||
@@ -230,7 +244,7 @@ bool File::Close()
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// We use the standard system handle for stdout in Windows
|
||||
// and it must not be closed here.
|
||||
// and it must not be closed here.
|
||||
if (HandleType==FILE_HANDLENORMAL)
|
||||
Success=CloseHandle(hFile)==TRUE;
|
||||
#else
|
||||
@@ -271,7 +285,7 @@ bool File::Rename(const wchar *NewName)
|
||||
Success=RenameFile(FileName,NewName);
|
||||
|
||||
if (Success)
|
||||
wcscpy(FileName,NewName);
|
||||
wcsncpyz(FileName,NewName,ASIZE(FileName));
|
||||
|
||||
return Success;
|
||||
}
|
||||
@@ -387,7 +401,7 @@ int File::Read(void *Data,size_t Size)
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ReadSize;
|
||||
return ReadSize; // It can return -1 only if AllowExceptions is disabled.
|
||||
}
|
||||
|
||||
|
||||
@@ -670,9 +684,11 @@ void File::GetOpenFileTime(RarTime *ft)
|
||||
|
||||
int64 File::FileLength()
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 SavePos=Tell();
|
||||
Seek(0,SEEK_END);
|
||||
return Tell();
|
||||
int64 Length=Tell();
|
||||
Seek(SavePos,SEEK_SET);
|
||||
return Length;
|
||||
}
|
||||
|
||||
|
||||
@@ -692,7 +708,7 @@ bool File::IsDevice()
|
||||
#ifndef SFX_MODULE
|
||||
int64 File::Copy(File &Dest,int64 Length)
|
||||
{
|
||||
Array<char> Buffer(0x40000);
|
||||
Array<byte> Buffer(File::CopyBufferSize());
|
||||
int64 CopySize=0;
|
||||
bool CopyAll=(Length==INT64NDF);
|
||||
|
||||
@@ -700,7 +716,7 @@ int64 File::Copy(File &Dest,int64 Length)
|
||||
{
|
||||
Wait();
|
||||
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
|
||||
char *Buf=&Buffer[0];
|
||||
byte *Buf=&Buffer[0];
|
||||
int ReadSize=Read(Buf,SizeToRead);
|
||||
if (ReadSize==0)
|
||||
break;
|
||||
|
||||
@@ -39,6 +39,9 @@ enum FILE_MODE_FLAGS {
|
||||
// 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
|
||||
};
|
||||
@@ -59,6 +62,7 @@ class File
|
||||
bool NoSequentialRead;
|
||||
uint CreateMode;
|
||||
#endif
|
||||
bool PreserveAtime;
|
||||
protected:
|
||||
bool OpenShared; // Set by 'Archive' class.
|
||||
public:
|
||||
@@ -69,13 +73,16 @@ class File
|
||||
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);
|
||||
bool Close();
|
||||
virtual bool Close(); // 'virtual' for MultiFile class.
|
||||
bool Delete();
|
||||
bool Rename(const wchar *NewName);
|
||||
bool Write(const void *Data,size_t Size);
|
||||
@@ -93,7 +100,7 @@ class File
|
||||
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
|
||||
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
|
||||
void GetOpenFileTime(RarTime *ft);
|
||||
bool IsOpened() {return hFile!=FILE_BAD_HANDLE;};
|
||||
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;}
|
||||
@@ -108,6 +115,7 @@ class File
|
||||
#ifdef _WIN_ALL
|
||||
void RemoveSequentialFlag() {NoSequentialRead=true;}
|
||||
#endif
|
||||
void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
|
||||
#ifdef _UNIX
|
||||
int GetFD()
|
||||
{
|
||||
@@ -118,6 +126,17 @@ class File
|
||||
#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
|
||||
|
||||
@@ -348,7 +348,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
|
||||
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
|
||||
return NULL;
|
||||
wcscpy(Name+Length,RndText);
|
||||
wcsncpyz(Name+Length,RndText,MaxSize-Length);
|
||||
if (!FileExist(Name))
|
||||
break;
|
||||
}
|
||||
@@ -360,7 +360,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||
#if !defined(SFX_MODULE)
|
||||
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
|
||||
{
|
||||
SaveFilePos SavePos(*SrcFile);
|
||||
int64 SavePos=SrcFile->Tell();
|
||||
#ifndef SILENT
|
||||
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
|
||||
#endif
|
||||
@@ -415,6 +415,8 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,
|
||||
if (Size!=INT64NDF)
|
||||
Size-=ReadSize;
|
||||
}
|
||||
SrcFile->Seek(SavePos,SEEK_SET);
|
||||
|
||||
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||
uiMsg(UIEVENT_FILESUMEND);
|
||||
|
||||
|
||||
@@ -46,26 +46,12 @@ bool ReadTextFile(
|
||||
// Set to really read size, so we can zero terminate it correctly.
|
||||
Data.Alloc(DataSize);
|
||||
|
||||
int LowEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0;
|
||||
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)
|
||||
{
|
||||
if (LowEndian || BigEndian)
|
||||
for (size_t I=2;I<DataSize;I++)
|
||||
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
|
||||
{
|
||||
SrcCharset=RCH_UNICODE; // High byte in UTF-16 char is found.
|
||||
break;
|
||||
}
|
||||
if (Utf8)
|
||||
{
|
||||
Data.Push(0); // Need a zero terminated string for UtfToWide.
|
||||
if (IsTextUtf8((const char *)(Data+3)))
|
||||
SrcCharset=RCH_UTF8;
|
||||
}
|
||||
}
|
||||
SrcCharset=DetectTextEncoding(&Data[0],DataSize);
|
||||
|
||||
Array<wchar> DataW;
|
||||
|
||||
@@ -83,16 +69,16 @@ bool ReadTextFile(
|
||||
if (SrcCharset==RCH_UNICODE)
|
||||
{
|
||||
size_t Start=2; // Skip byte order mark.
|
||||
if (!LowEndian && !BigEndian) // No byte order mask.
|
||||
if (!LittleEndian && !BigEndian) // No byte order mask.
|
||||
{
|
||||
Start=0;
|
||||
LowEndian=1;
|
||||
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+LowEndian]*256;
|
||||
DataW[(I-Start)/2]=Data[I+BigEndian]+Data[I+LittleEndian]*256;
|
||||
DataW[(End-Start)/2]=0;
|
||||
}
|
||||
|
||||
@@ -160,3 +146,21 @@ bool ReadTextFile(
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -12,4 +12,6 @@ bool ReadTextFile(
|
||||
bool ExpandEnvStr=false
|
||||
);
|
||||
|
||||
RAR_CHARSET DetectTextEncoding(const byte *Data,size_t DataSize);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@ FindFile::~FindFile()
|
||||
|
||||
void FindFile::SetMask(const wchar *Mask)
|
||||
{
|
||||
wcscpy(FindMask,Mask);
|
||||
wcsncpyz(FindMask,Mask,ASIZE(FindMask));
|
||||
FirstCall=true;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ bool FindFile::Next(FindData *fd,bool GetSymLink)
|
||||
wcsncpyz(DirName,FindMask,ASIZE(DirName));
|
||||
RemoveNameFromPath(DirName);
|
||||
if (*DirName==0)
|
||||
wcscpy(DirName,L".");
|
||||
wcsncpyz(DirName,L".",ASIZE(DirName));
|
||||
char DirNameA[NM];
|
||||
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
|
||||
if ((dirp=opendir(DirNameA))==NULL)
|
||||
@@ -63,32 +63,32 @@ bool FindFile::Next(FindData *fd,bool GetSymLink)
|
||||
}
|
||||
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;
|
||||
wchar Name[NM];
|
||||
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
|
||||
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
|
||||
|
||||
if (CmpName(FindMask,Name,MATCH_NAMES))
|
||||
{
|
||||
wchar FullName[NM];
|
||||
wcscpy(FullName,FindMask);
|
||||
wcsncpyz(FullName,FindMask,ASIZE(FullName));
|
||||
*PointToName(FullName)=0;
|
||||
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
|
||||
{
|
||||
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
|
||||
return false;
|
||||
}
|
||||
wcscat(FullName,Name);
|
||||
wcsncatz(FullName,Name,ASIZE(FullName));
|
||||
if (!FastFind(FullName,fd,GetSymLink))
|
||||
{
|
||||
ErrHandler.OpenErrorMsg(FullName);
|
||||
continue;
|
||||
}
|
||||
wcscpy(fd->Name,FullName);
|
||||
wcsncpyz(fd->Name,FullName,ASIZE(fd->Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,12 @@ 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
|
||||
|
||||
@@ -53,7 +53,7 @@ DataHash::DataHash()
|
||||
DataHash::~DataHash()
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(ThPool);
|
||||
delete ThPool;
|
||||
#endif
|
||||
cleandata(&CurCRC32, sizeof(CurCRC32));
|
||||
if (blake2ctx!=NULL)
|
||||
@@ -94,7 +94,7 @@ void DataHash::Update(const void *Data,size_t DataSize)
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
if (MaxThreads>1 && ThPool==NULL)
|
||||
ThPool=CreateThreadPool();
|
||||
ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER);
|
||||
blake2ctx->ThPool=ThPool;
|
||||
blake2ctx->MaxThreads=MaxThreads;
|
||||
#endif
|
||||
|
||||
@@ -11,18 +11,14 @@
|
||||
#define SIZEOF_SUBBLOCKHEAD 14
|
||||
#define SIZEOF_COMMHEAD 13
|
||||
#define SIZEOF_PROTECTHEAD 26
|
||||
#define SIZEOF_AVHEAD 14
|
||||
#define SIZEOF_SIGNHEAD 15
|
||||
#define SIZEOF_UOHEAD 18
|
||||
#define SIZEOF_MACHEAD 22
|
||||
#define SIZEOF_EAHEAD 24
|
||||
#define SIZEOF_BEEAHEAD 24
|
||||
#define SIZEOF_STREAMHEAD 26
|
||||
|
||||
#define VER_PACK 29
|
||||
#define VER_PACK5 50 // It is stored as 0, but we subtract 50 when saving an archive.
|
||||
#define VER_UNPACK 29
|
||||
#define VER_UNPACK5 50 // It is stored as 0, but we add 50 when reading an archive.
|
||||
#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
|
||||
|
||||
@@ -86,6 +82,8 @@ enum HEADER_TYPE {
|
||||
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 };
|
||||
|
||||
@@ -177,7 +175,7 @@ struct MainHeader:BaseBlock
|
||||
struct FileHeader:BlockHeader
|
||||
{
|
||||
byte HostOS;
|
||||
byte UnpVer;
|
||||
uint UnpVer; // It is 1 byte in RAR29 and bit field in RAR5.
|
||||
byte Method;
|
||||
union {
|
||||
uint FileAttr;
|
||||
@@ -193,7 +191,7 @@ struct FileHeader:BlockHeader
|
||||
|
||||
int64 PackSize;
|
||||
int64 UnpSize;
|
||||
int64 MaxSize; // Reserve size bytes for vint of this size.
|
||||
int64 MaxSize; // Reserve packed and unpacked size bytes for vint of this size.
|
||||
|
||||
HashValue FileHash;
|
||||
|
||||
@@ -323,23 +321,6 @@ struct ProtectHeader:BlockHeader
|
||||
};
|
||||
|
||||
|
||||
struct AVHeader:BaseBlock
|
||||
{
|
||||
byte UnpVer;
|
||||
byte Method;
|
||||
byte AVVer;
|
||||
uint AVInfoCRC;
|
||||
};
|
||||
|
||||
|
||||
struct SignHeader:BaseBlock
|
||||
{
|
||||
uint CreationTime;
|
||||
ushort ArcNameSize;
|
||||
ushort UserNameSize;
|
||||
};
|
||||
|
||||
|
||||
struct UnixOwnersHeader:SubBlockHeader
|
||||
{
|
||||
ushort OwnerNameSize;
|
||||
@@ -370,11 +351,4 @@ struct StreamHeader:SubBlockHeader
|
||||
};
|
||||
|
||||
|
||||
struct MacFInfoHeader:SubBlockHeader
|
||||
{
|
||||
uint fileType;
|
||||
uint fileCreator;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,6 +71,7 @@ void ListArchive(CommandData *Cmd)
|
||||
*VolNumText=0;
|
||||
while(Arc.ReadHeader()>0)
|
||||
{
|
||||
Wait(); // Allow quit listing with Ctrl+C.
|
||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||
if (HeaderType==HEAD_ENDARC)
|
||||
{
|
||||
@@ -91,7 +92,7 @@ void ListArchive(CommandData *Cmd)
|
||||
switch(HeaderType)
|
||||
{
|
||||
case HEAD_FILE:
|
||||
FileMatched=Cmd->IsProcessFile(Arc.FileHead)!=0;
|
||||
FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0;
|
||||
if (FileMatched)
|
||||
{
|
||||
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
|
||||
@@ -215,7 +216,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||
|
||||
wchar UnpSizeText[30],PackSizeText[30];
|
||||
if (hd.UnpSize==INT64NDF)
|
||||
wcscpy(UnpSizeText,L"?");
|
||||
wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText));
|
||||
else
|
||||
itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||
itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));
|
||||
@@ -229,13 +230,13 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||
wchar RatioStr[10];
|
||||
|
||||
if (hd.SplitBefore && hd.SplitAfter)
|
||||
wcscpy(RatioStr,L"<->");
|
||||
wcsncpyz(RatioStr,L"<->",ASIZE(RatioStr));
|
||||
else
|
||||
if (hd.SplitBefore)
|
||||
wcscpy(RatioStr,L"<--");
|
||||
wcsncpyz(RatioStr,L"<--",ASIZE(RatioStr));
|
||||
else
|
||||
if (hd.SplitAfter)
|
||||
wcscpy(RatioStr,L"-->");
|
||||
wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr));
|
||||
else
|
||||
swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));
|
||||
|
||||
@@ -344,7 +345,8 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||
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"3.0":L"5.0",hd.UnpVer,hd.Method,
|
||||
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");
|
||||
|
||||
@@ -466,7 +468,7 @@ void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSiz
|
||||
(A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-');
|
||||
break;
|
||||
case HSYS_UNKNOWN:
|
||||
wcscpy(AttrStr,L"?");
|
||||
wcsncpyz(AttrStr,L"?",AttrSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,10 +82,10 @@
|
||||
#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 (registered versions only)"
|
||||
#define MCHelpSwILOG L"\n ilog[name] Log errors to file"
|
||||
#define MCHelpSwINUL L"\n inul Disable all messages"
|
||||
#define MCHelpSwIOFF L"\n ioff Turn PC off after completing an operation"
|
||||
#define MCHelpSwISND L"\n isnd Enable sound"
|
||||
#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"
|
||||
@@ -127,11 +127,11 @@
|
||||
#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<time> Process files newer than <time>"
|
||||
#define MCHelpSwTO L"\n to<time> Process files older than <time>"
|
||||
#define MCHelpSwTA L"\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTB L"\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTS L"\n ts[m|c|a] Save or restore file time (modification, creation, access)"
|
||||
#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"
|
||||
@@ -203,7 +203,6 @@
|
||||
#define MErrOpenFile L"file"
|
||||
#define MAddNoFiles L"\nWARNING: No files"
|
||||
#define MMdfEncrSol L"\n%s: encrypted"
|
||||
#define MCannotMdfEncrSol L"\nCannot modify solid archive containing encrypted files"
|
||||
#define MAddAnalyze L"\nAnalyzing archived files: "
|
||||
#define MRepacking L"\nRepacking archived files: "
|
||||
#define MCRCFailed L"\n%-20s - checksum error"
|
||||
@@ -294,7 +293,8 @@
|
||||
#define MRprNoFiles L"\nNo files found"
|
||||
#define MLogUnexpEOF L"\nUnexpected end of archive"
|
||||
#define MRepAskReconst L"\nReconstruct archive structure ?"
|
||||
#define MRecScanning L"\nScanning..."
|
||||
#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"
|
||||
@@ -310,8 +310,6 @@
|
||||
#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 MListMACHead1 L"\n Mac OS file type: %c%c%c%c ; "
|
||||
#define MListMACHead2 L"file creator: %c%c%c%c\n"
|
||||
#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"
|
||||
@@ -343,7 +341,7 @@
|
||||
#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 MCannotEncName L"\nCannot encrypt archive already containing encrypted files"
|
||||
#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>"
|
||||
@@ -353,16 +351,17 @@
|
||||
#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"\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB."
|
||||
#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 MRepairing L"\nRepairing"
|
||||
#define MWrongFilePassword L"\nIncorrect password for %s"
|
||||
#define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x"
|
||||
#define MBlocksRecovered L"\n%d blocks recovered."
|
||||
#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"
|
||||
@@ -376,6 +375,8 @@
|
||||
#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."
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# Linux using GCC
|
||||
CXX=c++
|
||||
CXXFLAGS=-O2
|
||||
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
|
||||
@@ -138,7 +138,9 @@ install: install-unrar
|
||||
uninstall: uninstall-unrar
|
||||
|
||||
clean:
|
||||
@rm -f *.o *.bak *~
|
||||
@rm -f *.bak *~
|
||||
@rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ)
|
||||
@rm -f unrar libunrar.*
|
||||
|
||||
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
|
||||
@rm -f unrar
|
||||
@@ -154,8 +156,7 @@ sfx: clean $(OBJECTS)
|
||||
lib: WHAT=RARDLL
|
||||
lib: CXXFLAGS+=$(LIBFLAGS)
|
||||
lib: clean $(OBJECTS) $(LIB_OBJ)
|
||||
@rm -f libunrar.so
|
||||
@rm -f libunrar.a
|
||||
@rm -f libunrar.*
|
||||
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
|
||||
$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||
if (CmpMode!=MATCH_NAMES)
|
||||
{
|
||||
size_t WildLength=wcslen(Wildcard);
|
||||
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH &&
|
||||
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH && CmpMode!=MATCH_ALLWILD &&
|
||||
mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
|
||||
{
|
||||
// For all modes except MATCH_NAMES, MATCH_EXACT and MATCH_EXACTPATH
|
||||
// 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)
|
||||
@@ -46,6 +46,8 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||
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));
|
||||
@@ -64,8 +66,8 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||
|
||||
// Always return false for RAR temporary files to exclude them
|
||||
// from archiving operations.
|
||||
if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
|
||||
return(false);
|
||||
// if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
|
||||
// return(false);
|
||||
|
||||
if (CmpMode==MATCH_EXACT)
|
||||
return(mwcsicompc(Name1,Name2,ForceCase)==0);
|
||||
|
||||
@@ -14,6 +14,10 @@ enum {
|
||||
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.
|
||||
|
||||
|
||||
@@ -42,10 +42,14 @@ void ModelPPM::RestartModelRare()
|
||||
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;
|
||||
@@ -166,9 +170,6 @@ void RARPPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
|
||||
inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1)
|
||||
{
|
||||
#ifdef __ICL
|
||||
static
|
||||
#endif
|
||||
RARPPM_STATE UpState;
|
||||
RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
|
||||
RARPPM_STATE * p, * ps[MAX_O], ** pps=ps;
|
||||
@@ -202,7 +203,14 @@ LOOP_ENTRY:
|
||||
{
|
||||
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:
|
||||
@@ -492,6 +500,12 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||
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;
|
||||
@@ -503,7 +517,12 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||
{
|
||||
HiCnt=0;
|
||||
while ((HiCnt += p->Freq) <= count)
|
||||
p=*++pps;
|
||||
{
|
||||
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);
|
||||
@@ -516,12 +535,15 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||
pps--;
|
||||
do
|
||||
{
|
||||
Model->CharMask[(*++pps)->Symbol]=Model->EscCount;
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
2390
unrar/msc.dep
2390
unrar/msc.dep
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ void RAROptions::Init()
|
||||
Method=3;
|
||||
MsgStream=MSG_STDOUT;
|
||||
ConvertNames=NAMES_ORIGINALCASE;
|
||||
xmtime=EXTTIME_HIGH3;
|
||||
xmtime=EXTTIME_MAX;
|
||||
FileSizeLess=INT64NDF;
|
||||
FileSizeMore=INT64NDF;
|
||||
HashType=HASH_CRC32;
|
||||
|
||||
@@ -12,11 +12,7 @@ enum PATH_EXCL_MODE {
|
||||
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)
|
||||
|
||||
EXCL_SKIPABSPATH // Works as EXCL_BASEPATH for fully qualified paths
|
||||
// and as EXCL_UNCHANGED for relative paths.
|
||||
// Used by WinRAR GUI only.
|
||||
EXCL_ABSPATH // -ep3 (the full path with the disk letter)
|
||||
};
|
||||
|
||||
enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
|
||||
@@ -25,7 +21,7 @@ enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
|
||||
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
|
||||
|
||||
enum EXTTIME_MODE {
|
||||
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
|
||||
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_MAX
|
||||
};
|
||||
|
||||
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
|
||||
@@ -63,6 +59,20 @@ enum SAVECOPY_MODE {
|
||||
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;
|
||||
@@ -82,13 +92,21 @@ class RAROptions
|
||||
|
||||
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];
|
||||
#ifdef USE_QOPEN
|
||||
wchar SFXModule[NM];
|
||||
|
||||
#ifdef USE_QOPEN
|
||||
QOPEN_MODE QOpenMode;
|
||||
#endif
|
||||
|
||||
bool ConfigDisabled; // Switch -cfg-.
|
||||
wchar ExtrPath[NM];
|
||||
wchar CommentFile[NM];
|
||||
@@ -105,7 +123,7 @@ class RAROptions
|
||||
|
||||
wchar LogName[NM];
|
||||
MESSAGE_TYPE MsgStream;
|
||||
bool Sound;
|
||||
SOUND_NOTIFY_MODE Sound;
|
||||
OVERWRITE_MODE Overwrite;
|
||||
int Method;
|
||||
HASH_TYPE HashType;
|
||||
@@ -128,6 +146,7 @@ class RAROptions
|
||||
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;
|
||||
@@ -149,14 +168,17 @@ class RAROptions
|
||||
#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 FileTimeBefore;
|
||||
RarTime FileTimeAfter;
|
||||
RarTime FileMtimeBefore,FileCtimeBefore,FileAtimeBefore;
|
||||
bool FileMtimeBeforeOR,FileCtimeBeforeOR,FileAtimeBeforeOR;
|
||||
RarTime FileMtimeAfter,FileCtimeAfter,FileAtimeAfter;
|
||||
bool FileMtimeAfterOR,FileCtimeAfterOR,FileAtimeAfterOR;
|
||||
int64 FileSizeLess;
|
||||
int64 FileSizeMore;
|
||||
bool Lock;
|
||||
@@ -165,11 +187,12 @@ class RAROptions
|
||||
FilterMode FilterModes[MAX_FILTER_TYPES];
|
||||
wchar EmailTo[NM];
|
||||
uint VersionControl;
|
||||
bool AppendArcNameToPath;
|
||||
bool Shutdown;
|
||||
EXTTIME_MODE xmtime;
|
||||
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.
|
||||
|
||||
20
unrar/os.hpp
20
unrar/os.hpp
@@ -22,8 +22,22 @@
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
|
||||
#define STRICT
|
||||
|
||||
// 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
|
||||
@@ -39,6 +53,8 @@
|
||||
#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>
|
||||
@@ -117,7 +133,7 @@
|
||||
|
||||
#ifdef _UNIX
|
||||
|
||||
#define NM 2048
|
||||
#define NM 2048
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
112
unrar/pathfn.cpp
112
unrar/pathfn.cpp
@@ -16,7 +16,7 @@ wchar* PointToLastChar(const wchar *Path)
|
||||
}
|
||||
|
||||
|
||||
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
||||
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize)
|
||||
{
|
||||
const wchar *DestPtr=SrcPath;
|
||||
|
||||
@@ -25,7 +25,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
||||
if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
|
||||
DestPtr=s+4;
|
||||
|
||||
// Remove <d>:\ and any sequence of . and \ in the beginning of path string.
|
||||
// Remove any amount of <d>:\ and any sequence of . and \ in the beginning of path string.
|
||||
while (*DestPtr!=0)
|
||||
{
|
||||
const wchar *s=DestPtr;
|
||||
@@ -58,7 +58,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
||||
// so we use the temporary buffer for copying.
|
||||
wchar TmpStr[NM];
|
||||
wcsncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
|
||||
wcscpy(DestPath,TmpStr);
|
||||
wcsncpyz(DestPath,TmpStr,DestSize);
|
||||
}
|
||||
return (wchar *)DestPtr;
|
||||
}
|
||||
@@ -120,7 +120,14 @@ bool CmpExt(const wchar *Name,const wchar *Ext)
|
||||
|
||||
bool IsWildcard(const wchar *Str)
|
||||
{
|
||||
return Str==NULL ? false:wcspbrk(Str,L"*?")!=NULL;
|
||||
if (Str==NULL)
|
||||
return false;
|
||||
#ifdef _WIN_ALL
|
||||
// Not treat the special NTFS \\?\d: path prefix as a wildcard.
|
||||
if (Str[0]=='\\' && Str[1]=='\\' && Str[2]=='?' && Str[3]=='\\')
|
||||
Str+=4;
|
||||
#endif
|
||||
return wcspbrk(Str,L"*?")!=NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,13 +171,16 @@ void AddEndSlash(wchar *Path,size_t MaxLength)
|
||||
{
|
||||
size_t Length=wcslen(Path);
|
||||
if (Length>0 && Path[Length-1]!=CPATHDIVIDER && Length+1<MaxLength)
|
||||
wcscat(Path,SPATHDIVIDER);
|
||||
{
|
||||
Path[Length]=CPATHDIVIDER;
|
||||
Path[Length+1]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize)
|
||||
{
|
||||
// 'Name' and 'Pathname' can point to same memory area. This is why we use
|
||||
// 'Path', 'Name' and 'Pathname' can point to same memory area. So we use
|
||||
// the temporary buffer instead of constructing the name in 'Pathname'.
|
||||
wchar OutName[NM];
|
||||
wcsncpyz(OutName,Path,ASIZE(OutName));
|
||||
@@ -260,9 +270,9 @@ bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create)
|
||||
{
|
||||
char *EnvStr=getenv("HOME");
|
||||
if (EnvStr!=NULL)
|
||||
GetWideName(EnvStr,NULL,Path,MaxSize);
|
||||
CharToWide(EnvStr,Path,MaxSize);
|
||||
else
|
||||
wcsncpyz(Path, ConfPath[0], MaxSize);
|
||||
wcsncpyz(Path,ConfPath[0],MaxSize);
|
||||
return true;
|
||||
}
|
||||
Number--;
|
||||
@@ -303,9 +313,13 @@ void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckEx
|
||||
#endif
|
||||
|
||||
|
||||
// Returns a pointer to rightmost digit of volume number.
|
||||
// Returns a pointer to rightmost digit of volume number or to beginning
|
||||
// of file name if numeric part is missing.
|
||||
wchar* GetVolNumPart(const wchar *ArcName)
|
||||
{
|
||||
if (*ArcName==0)
|
||||
return (wchar *)ArcName;
|
||||
|
||||
// Pointing to last name character.
|
||||
const wchar *ChPtr=ArcName+wcslen(ArcName)-1;
|
||||
|
||||
@@ -346,18 +360,33 @@ void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering)
|
||||
ChPtr=GetExt(ArcName);
|
||||
}
|
||||
else
|
||||
if (ChPtr[1]==0 && wcslen(ArcName)<MaxLength-3 || wcsicomp(ChPtr+1,L"exe")==0 || wcsicomp(ChPtr+1,L"sfx")==0)
|
||||
wcscpy(ChPtr+1,L"rar");
|
||||
if (ChPtr[1]==0 || wcsicomp(ChPtr,L".exe")==0 || wcsicomp(ChPtr,L".sfx")==0)
|
||||
wcsncpyz(ChPtr,L".rar",MaxLength-(ChPtr-ArcName));
|
||||
|
||||
if (ChPtr==NULL || *ChPtr!='.' || ChPtr[1]==0)
|
||||
{
|
||||
// Normally we shall have some extension here. If we don't, it means
|
||||
// the name has no extension and buffer has no free space to append one.
|
||||
// Let's clear the name to prevent a new call with same name and return.
|
||||
*ArcName=0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!OldNumbering)
|
||||
{
|
||||
ChPtr=GetVolNumPart(ArcName);
|
||||
|
||||
// We should not check for IsDigit(*ChPtr) here and should increment
|
||||
// even non-digits. If we got a corrupt archive with volume flag,
|
||||
// but without numeric part, we still need to modify its name somehow,
|
||||
// so while (exist(name)) {NextVolumeName()} loops do not run infinitely.
|
||||
while ((++(*ChPtr))=='9'+1)
|
||||
{
|
||||
*ChPtr='0';
|
||||
ChPtr--;
|
||||
if (ChPtr<ArcName || !IsDigit(*ChPtr))
|
||||
{
|
||||
// Convert .part:.rar (.part9.rar after increment) to part10.rar.
|
||||
for (wchar *EndPtr=ArcName+wcslen(ArcName);EndPtr!=ChPtr;EndPtr--)
|
||||
*(EndPtr+1)=*EndPtr;
|
||||
*(ChPtr+1)='1';
|
||||
@@ -366,15 +395,15 @@ void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering)
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!IsDigit(*(ChPtr+2)) || !IsDigit(*(ChPtr+3)))
|
||||
wcscpy(ChPtr+2,L"00");
|
||||
if (!IsDigit(ChPtr[2]) || !IsDigit(ChPtr[3]))
|
||||
wcsncpyz(ChPtr+2,L"00",MaxLength-(ChPtr-ArcName)-2); // From .rar to .r00.
|
||||
else
|
||||
{
|
||||
ChPtr+=3;
|
||||
while ((++(*ChPtr))=='9'+1)
|
||||
if (*(ChPtr-1)=='.')
|
||||
ChPtr+=wcslen(ChPtr)-1; // Set to last character.
|
||||
while (++(*ChPtr)=='9'+1)
|
||||
if (ChPtr<=ArcName || *(ChPtr-1)=='.')
|
||||
{
|
||||
*ChPtr='A';
|
||||
*ChPtr='a'; // From .999 to .a00 if started from .001 or for too short names.
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -585,8 +614,7 @@ int ParseVersionFileName(wchar *Name,bool Truncate)
|
||||
wchar *VerText=wcsrchr(Name,';');
|
||||
if (VerText!=NULL)
|
||||
{
|
||||
if (Version==0)
|
||||
Version=atoiw(VerText+1);
|
||||
Version=atoiw(VerText+1);
|
||||
if (Truncate)
|
||||
*VerText=0;
|
||||
}
|
||||
@@ -652,7 +680,7 @@ wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,size_t MaxSize,b
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,bool &ArcNumPresent)
|
||||
static void GenArcName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,uint ArcNumber,bool &ArcNumPresent)
|
||||
{
|
||||
bool Prefix=false;
|
||||
if (*GenerateMask=='+')
|
||||
@@ -713,7 +741,7 @@ static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,b
|
||||
wchar Ext[NM],*Dot=GetExt(ArcName);
|
||||
*Ext=0;
|
||||
if (Dot==NULL)
|
||||
wcscpy(Ext,*PointToName(ArcName)==0 ? L".rar":L"");
|
||||
wcsncpyz(Ext,*PointToName(ArcName)==0 ? L".rar":L"",ASIZE(Ext));
|
||||
else
|
||||
{
|
||||
wcsncpyz(Ext,Dot,ASIZE(Ext));
|
||||
@@ -749,7 +777,7 @@ static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,b
|
||||
int CField[sizeof(Field)/sizeof(Field[0])];
|
||||
memset(CField,0,sizeof(CField));
|
||||
QuoteMode=false;
|
||||
for (int I=0;Mask[I]!=0;I++)
|
||||
for (uint I=0;Mask[I]!=0;I++)
|
||||
{
|
||||
if (Mask[I]=='{' || Mask[I]=='}')
|
||||
{
|
||||
@@ -810,21 +838,17 @@ static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,b
|
||||
AddEndSlash(NewName,ASIZE(NewName));
|
||||
wcsncatz(NewName,DateText,ASIZE(NewName));
|
||||
wcsncatz(NewName,PointToName(ArcName),ASIZE(NewName));
|
||||
wcscpy(ArcName,NewName);
|
||||
wcsncpyz(ArcName,NewName,MaxSize);
|
||||
}
|
||||
else
|
||||
wcscat(ArcName,DateText);
|
||||
wcscat(ArcName,Ext);
|
||||
wcsncatz(ArcName,DateText,MaxSize);
|
||||
wcsncatz(ArcName,Ext,MaxSize);
|
||||
}
|
||||
|
||||
|
||||
void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,bool Archiving)
|
||||
{
|
||||
// Must be enough space for archive name plus all stuff in mask plus
|
||||
// extra overhead produced by mask 'N' (archive number) characters.
|
||||
// One 'N' character can result in several numbers if we process more
|
||||
// than 9 archives.
|
||||
wchar NewName[NM+MAX_GENERATE_MASK+20];
|
||||
wchar NewName[NM];
|
||||
|
||||
uint ArcNumber=1;
|
||||
while (true) // Loop for 'N' (archive number) processing.
|
||||
@@ -833,7 +857,7 @@ void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask
|
||||
|
||||
bool ArcNumPresent=false;
|
||||
|
||||
GenArcName(NewName,GenerateMask,ArcNumber,ArcNumPresent);
|
||||
GenArcName(NewName,ASIZE(NewName),GenerateMask,ArcNumber,ArcNumPresent);
|
||||
|
||||
if (!ArcNumPresent)
|
||||
break;
|
||||
@@ -845,7 +869,7 @@ void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask
|
||||
// existing archive before the first unused name. So we generate
|
||||
// the name for (ArcNumber-1) below.
|
||||
wcsncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
|
||||
GenArcName(NewName,GenerateMask,ArcNumber-1,ArcNumPresent);
|
||||
GenArcName(NewName,ASIZE(NewName),GenerateMask,ArcNumber-1,ArcNumPresent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -895,8 +919,8 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||
{
|
||||
if (MaxSize<=PrefixLength+SrcLength)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcscpy(Dest+PrefixLength,Src);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
wcsncatz(Dest,Src,MaxSize); // "\\?\D:\very long path".
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -904,9 +928,9 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||
{
|
||||
if (MaxSize<=PrefixLength+SrcLength+2)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcscpy(Dest+PrefixLength,L"UNC");
|
||||
wcscpy(Dest+PrefixLength+3,Src+1);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
wcsncatz(Dest,L"UNC",MaxSize);
|
||||
wcsncatz(Dest,Src+1,MaxSize); // "\\?\UNC\server\share".
|
||||
return true;
|
||||
}
|
||||
// We may be here only if we modify IsFullPath in the future.
|
||||
@@ -923,9 +947,10 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||
{
|
||||
if (MaxSize<=PrefixLength+SrcLength+2)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcsncpy(Dest+PrefixLength,CurDir,2); // Copy drive letter 'd:'.
|
||||
wcscpy(Dest+PrefixLength+2,Src);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
CurDir[2]=0;
|
||||
wcsncatz(Dest,CurDir,MaxSize); // Copy drive letter 'd:'.
|
||||
wcsncatz(Dest,Src,MaxSize);
|
||||
return true;
|
||||
}
|
||||
else // Paths in path\name format.
|
||||
@@ -933,8 +958,8 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||
AddEndSlash(CurDir,ASIZE(CurDir));
|
||||
if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcscpy(Dest+PrefixLength,CurDir);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
wcsncatz(Dest,CurDir,MaxSize);
|
||||
|
||||
if (Src[0]=='.' && IsPathDiv(Src[1])) // Remove leading .\ in pathname.
|
||||
Src+=2;
|
||||
@@ -969,7 +994,8 @@ void MakeNameCompatible(wchar *Name)
|
||||
if (IsPathDiv(Name[Src]) || Name[Src]==0)
|
||||
for (int I=Dest-1;I>0 && (Name[I]==' ' || Name[I]=='.');I--)
|
||||
{
|
||||
if (IsPathDiv(Name[I-1])) // Permit path1/./path2 paths.
|
||||
// Permit path1/./path2 and ../path1 paths.
|
||||
if (Name[I]=='.' && (IsPathDiv(Name[I-1]) || Name[I-1]=='.' && I==1))
|
||||
break;
|
||||
Dest--;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
wchar* PointToName(const wchar *Path);
|
||||
wchar* PointToLastChar(const wchar *Path);
|
||||
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath);
|
||||
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);
|
||||
|
||||
@@ -61,19 +61,36 @@ void QuickOpen::Close()
|
||||
|
||||
void QuickOpen::Load(uint64 BlockPos)
|
||||
{
|
||||
if (!Loaded) // If loading the first time, perform additional intialization.
|
||||
if (!Loaded)
|
||||
{
|
||||
// If loading for the first time, perform additional intialization.
|
||||
SeekPos=Arc->Tell();
|
||||
UnsyncSeekPos=false;
|
||||
|
||||
SaveFilePos SavePos(*Arc);
|
||||
int64 SavePos=SeekPos;
|
||||
Arc->Seek(BlockPos,SEEK_SET);
|
||||
if (Arc->ReadHeader()==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||
|
||||
|
||||
// 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;
|
||||
QLHeaderPos=Arc->CurBlockPos;
|
||||
}
|
||||
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.
|
||||
}
|
||||
@@ -88,7 +105,10 @@ void QuickOpen::Load(uint64 BlockPos)
|
||||
Arc->SubHead.HashKey,Arc->SubHead.PswCheck);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Loaded=false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RawDataPos=0;
|
||||
@@ -156,7 +176,7 @@ bool QuickOpen::Seek(int64 Offset,int Method)
|
||||
// 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(QLHeaderPos);
|
||||
Load(QOHeaderPos);
|
||||
|
||||
if (Method==SEEK_SET)
|
||||
SeekPos=Offset;
|
||||
@@ -185,22 +205,28 @@ bool QuickOpen::Tell(int64 *Pos)
|
||||
|
||||
uint QuickOpen::ReadBuffer()
|
||||
{
|
||||
SaveFilePos SavePos(*Arc);
|
||||
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;
|
||||
if (SizeToRead==0)
|
||||
return 0;
|
||||
int ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
|
||||
if (ReadSize<=0)
|
||||
return 0;
|
||||
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);
|
||||
if (Arc->SubHead.Encrypted)
|
||||
Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
|
||||
#endif
|
||||
RawDataPos+=ReadSize;
|
||||
ReadBufSize+=ReadSize;
|
||||
RawDataPos+=ReadSize;
|
||||
ReadBufSize+=ReadSize;
|
||||
}
|
||||
}
|
||||
Arc->Seek(SavePos,SEEK_SET);
|
||||
return ReadSize;
|
||||
}
|
||||
|
||||
@@ -234,10 +260,10 @@ bool QuickOpen::ReadRaw(RawRead &Raw)
|
||||
return false;
|
||||
}
|
||||
|
||||
// If rest of block data crosses buffer boundary, read it in loop.
|
||||
size_t DataLeft=ReadBufSize-ReadBufPos;
|
||||
// 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;
|
||||
@@ -264,9 +290,11 @@ bool QuickOpen::ReadNext()
|
||||
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=QLHeaderPos-Offset;
|
||||
LastReadHeaderPos=QOHeaderPos-Offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,24 +29,24 @@ class QuickOpen
|
||||
QuickOpenItem *ListStart;
|
||||
QuickOpenItem *ListEnd;
|
||||
|
||||
byte *Buf;
|
||||
static const size_t MaxBufSize=0x10000; // Must be multiple of CRYPT_BLOCK_SIZE.
|
||||
size_t CurBufSize;
|
||||
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 QLHeaderPos;
|
||||
uint64 RawDataStart;
|
||||
uint64 RawDataSize;
|
||||
uint64 RawDataPos;
|
||||
size_t ReadBufSize;
|
||||
size_t ReadBufPos;
|
||||
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.
|
||||
bool UnsyncSeekPos; // QOpen SeekPos does not match an actual file pointer.
|
||||
public:
|
||||
QuickOpen();
|
||||
~QuickOpen();
|
||||
|
||||
@@ -29,7 +29,7 @@ int main(int argc, char *argv[])
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
// Must be initialized, normal initialization can be skipped in case of
|
||||
// exception.
|
||||
bool ShutdownOnClose=false;
|
||||
POWER_MODE ShutdownOnClose=POWERMODE_KEEP;
|
||||
#endif
|
||||
|
||||
try
|
||||
@@ -37,7 +37,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
CommandData *Cmd=new CommandData;
|
||||
#ifdef SFX_MODULE
|
||||
wcscpy(Cmd->Command,L"X");
|
||||
wcsncpyz(Cmd->Command,L"X",ASIZE(Cmd->Command));
|
||||
char *Switch=argc>1 ? argv[1]:NULL;
|
||||
if (Switch!=NULL && Cmd->IsSwitch(Switch[0]))
|
||||
{
|
||||
@@ -68,10 +68,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
ShutdownOnClose=Cmd->Shutdown;
|
||||
if (ShutdownOnClose)
|
||||
ShutdownCheckAnother(true);
|
||||
#endif
|
||||
|
||||
uiInit(Cmd->Sound);
|
||||
InitConsoleOptions(Cmd->MsgStream,Cmd->RedirectCharset);
|
||||
InitLogOptions(Cmd->LogName,Cmd->ErrlogCharset);
|
||||
ErrHandler.SetSilent(Cmd->AllYes || Cmd->MsgStream==MSG_NULL);
|
||||
|
||||
@@ -94,8 +95,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
if (ShutdownOnClose && ErrHandler.IsShutdownEnabled())
|
||||
Shutdown();
|
||||
if (ShutdownOnClose!=POWERMODE_KEEP && ErrHandler.IsShutdownEnabled() &&
|
||||
!ShutdownCheckAnother(false))
|
||||
Shutdown(ShutdownOnClose);
|
||||
#endif
|
||||
ErrHandler.MainExit=true;
|
||||
return ErrHandler.GetErrorCode();
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#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"
|
||||
@@ -36,7 +39,6 @@
|
||||
#include "filestr.hpp"
|
||||
#include "find.hpp"
|
||||
#include "scantree.hpp"
|
||||
#include "savepos.hpp"
|
||||
#include "getbits.hpp"
|
||||
#include "rdwrfn.hpp"
|
||||
#ifdef USE_QOPEN
|
||||
@@ -48,9 +50,6 @@
|
||||
#include "filcreat.hpp"
|
||||
#include "consio.hpp"
|
||||
#include "system.hpp"
|
||||
#ifdef _WIN_ALL
|
||||
#include "isnt.hpp"
|
||||
#endif
|
||||
#include "log.hpp"
|
||||
#include "rawint.hpp"
|
||||
#include "rawread.hpp"
|
||||
@@ -77,6 +76,9 @@
|
||||
|
||||
#include "rs.hpp"
|
||||
#include "rs16.hpp"
|
||||
|
||||
|
||||
|
||||
#include "recvol.hpp"
|
||||
#include "volume.hpp"
|
||||
#include "smallfn.hpp"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define Min(x,y) (((x)<(y)) ? (x):(y))
|
||||
#define Max(x,y) (((x)>(y)) ? (x):(y))
|
||||
|
||||
// Universal replacement of abs function for non-int arguments.
|
||||
// Universal replacement of abs function.
|
||||
#define Abs(x) (((x)<0) ? -(x):(x))
|
||||
|
||||
#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
@@ -18,15 +18,15 @@ typedef wchar_t wchar; // Unicode character
|
||||
// Make 64 bit integer from two 32 bit.
|
||||
#define INT32TO64(high,low) ((((uint64)(high))<<32)+((uint64)low))
|
||||
|
||||
// Special int64 value, large enough to never be found in real life.
|
||||
// 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.
|
||||
// compatible with 32 bit int64 if 64 bit type is not supported.
|
||||
#define INT64NDF INT32TO64(0x7fffffff,0x7fffffff)
|
||||
|
||||
// Maximum uint64 value.
|
||||
#define MAX_UINT64 INT32TO64(0xffffffff,0xffffffff)
|
||||
#define UINT64NDF MAX_UINT64
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@ void RarVM::Init()
|
||||
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);
|
||||
@@ -107,7 +108,14 @@ uint RarVM::ReadData(BitInput &Inp)
|
||||
void RarVM::SetMemory(size_t Pos,byte *Data,size_t DataSize)
|
||||
{
|
||||
if (Pos<VM_MEMSIZE && Data!=Mem+Pos)
|
||||
memmove(Mem+Pos,Data,Min(DataSize,VM_MEMSIZE-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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -279,7 +287,10 @@ bool RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
||||
PrevDelta=(signed char)(Predicted-PrevByte);
|
||||
PrevByte=Predicted;
|
||||
|
||||
int D=((signed char)CurByte)<<3;
|
||||
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);
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#define VMCF_OP0 0
|
||||
#define VMCF_OP1 1
|
||||
#define VMCF_OP2 2
|
||||
#define VMCF_OPMASK 3
|
||||
#define VMCF_BYTEMODE 4
|
||||
#define VMCF_JUMP 8
|
||||
#define VMCF_PROC 16
|
||||
#define VMCF_USEFLAGS 32
|
||||
#define VMCF_CHFLAGS 64
|
||||
|
||||
static byte VM_CmdFlags[]=
|
||||
{
|
||||
/* VM_MOV */ VMCF_OP2 | VMCF_BYTEMODE ,
|
||||
/* VM_CMP */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_ADD */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_SUB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_JZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_JNZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_INC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_DEC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_JMP */ VMCF_OP1 | VMCF_JUMP ,
|
||||
/* VM_XOR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_AND */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_OR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_TEST */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_JS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_JNS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_JB */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_JBE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_JA */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_JAE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
|
||||
/* VM_PUSH */ VMCF_OP1 ,
|
||||
/* VM_POP */ VMCF_OP1 ,
|
||||
/* VM_CALL */ VMCF_OP1 | VMCF_PROC ,
|
||||
/* VM_RET */ VMCF_OP0 | VMCF_PROC ,
|
||||
/* VM_NOT */ VMCF_OP1 | VMCF_BYTEMODE ,
|
||||
/* VM_SHL */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_SHR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_SAR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_NEG */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
|
||||
/* VM_PUSHA */ VMCF_OP0 ,
|
||||
/* VM_POPA */ VMCF_OP0 ,
|
||||
/* VM_PUSHF */ VMCF_OP0 | VMCF_USEFLAGS ,
|
||||
/* VM_POPF */ VMCF_OP0 | VMCF_CHFLAGS ,
|
||||
/* VM_MOVZX */ VMCF_OP2 ,
|
||||
/* VM_MOVSX */ VMCF_OP2 ,
|
||||
/* VM_XCHG */ VMCF_OP2 | VMCF_BYTEMODE ,
|
||||
/* VM_MUL */ VMCF_OP2 | VMCF_BYTEMODE ,
|
||||
/* VM_DIV */ VMCF_OP2 | VMCF_BYTEMODE ,
|
||||
/* VM_ADC */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS ,
|
||||
/* VM_SBB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS ,
|
||||
/* VM_PRINT */ VMCF_OP0
|
||||
};
|
||||
@@ -115,7 +115,9 @@ uint64 RawRead::Get8()
|
||||
uint64 RawRead::GetV()
|
||||
{
|
||||
uint64 Result=0;
|
||||
for (uint Shift=0;ReadPos<DataSize;Shift+=7)
|
||||
// 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;
|
||||
|
||||
@@ -19,11 +19,13 @@ void ComprDataIO::Init()
|
||||
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;
|
||||
@@ -95,7 +97,7 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||
return -1;
|
||||
ReadSize=SrcFile->Read(ReadAddr,SizeToRead);
|
||||
FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead;
|
||||
if (hd->SplitAfter)
|
||||
if (!NoFileHeader && hd->SplitAfter)
|
||||
PackedDataHash.Update(ReadAddr,ReadSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
class CmdAdd;
|
||||
class Unpack;
|
||||
class ArcFileSearch;
|
||||
|
||||
#if 0
|
||||
// We use external i/o calls for Benchmark command.
|
||||
@@ -32,6 +33,7 @@ class ComprDataIO
|
||||
bool ShowProgress;
|
||||
bool TestMode;
|
||||
bool SkipUnpCRC;
|
||||
bool NoFileHeader;
|
||||
|
||||
File *SrcFile;
|
||||
File *DestFile;
|
||||
@@ -62,6 +64,7 @@ class ComprDataIO
|
||||
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;}
|
||||
|
||||
@@ -31,12 +31,12 @@ bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
// handling exceptions. So it can close and delete files on Cancel.
|
||||
if (Fmt==RARFMT15)
|
||||
{
|
||||
RecVolumes3 RecVol(false);
|
||||
RecVolumes3 RecVol(Cmd,false);
|
||||
return RecVol.Restore(Cmd,Name,Silent);
|
||||
}
|
||||
else
|
||||
{
|
||||
RecVolumes5 RecVol(false);
|
||||
RecVolumes5 RecVol(Cmd,false);
|
||||
return RecVol.Restore(Cmd,Name,Silent);
|
||||
}
|
||||
}
|
||||
@@ -100,12 +100,12 @@ void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name)
|
||||
RevFile.Close();
|
||||
if (Rev5)
|
||||
{
|
||||
RecVolumes5 RecVol(true);
|
||||
RecVolumes5 RecVol(Cmd,true);
|
||||
RecVol.Test(Cmd,Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
RecVolumes3 RecVol(true);
|
||||
RecVolumes3 RecVol(Cmd,true);
|
||||
RecVol.Test(Cmd,Name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class RecVolumes3
|
||||
ThreadPool *RSThreadPool;
|
||||
#endif
|
||||
public:
|
||||
RecVolumes3(bool TestOnly);
|
||||
RecVolumes3(RAROptions *Cmd,bool TestOnly);
|
||||
~RecVolumes3();
|
||||
void Make(RAROptions *Cmd,wchar *ArcName);
|
||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||
@@ -71,11 +71,12 @@ class RecVolumes5
|
||||
#ifdef RAR_SMP
|
||||
ThreadPool *RecThreadPool;
|
||||
#endif
|
||||
RecRSThreadData ThreadData[MaxPoolThreads]; // Store thread parameters.
|
||||
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(bool TestOnly);
|
||||
RecVolumes5(RAROptions *Cmd,bool TestOnly);
|
||||
~RecVolumes5();
|
||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||
void Test(RAROptions *Cmd,const wchar *Name);
|
||||
|
||||
@@ -36,7 +36,7 @@ THREAD_PROC(RSDecodeThread)
|
||||
}
|
||||
#endif
|
||||
|
||||
RecVolumes3::RecVolumes3(bool TestOnly)
|
||||
RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly)
|
||||
{
|
||||
memset(SrcFile,0,sizeof(SrcFile));
|
||||
if (TestOnly)
|
||||
@@ -50,7 +50,7 @@ RecVolumes3::RecVolumes3(bool TestOnly)
|
||||
Buf.Alloc(TotalBufferSize);
|
||||
memset(SrcFile,0,sizeof(SrcFile));
|
||||
#ifdef RAR_SMP
|
||||
RSThreadPool=CreateThreadPool();
|
||||
RSThreadPool=new ThreadPool(Cmd->Threads);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ RecVolumes3::~RecVolumes3()
|
||||
for (size_t I=0;I<ASIZE(SrcFile);I++)
|
||||
delete SrcFile[I];
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(RSThreadPool);
|
||||
delete RSThreadPool;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
NewStyle=IsNewStyleRev(ArcName);
|
||||
while (Ext>ArcName+1 && (IsDigit(*(Ext-1)) || *(Ext-1)=='_'))
|
||||
Ext--;
|
||||
wcscpy(Ext,L"*.*");
|
||||
wcsncpyz(Ext,L"*.*",ASIZE(ArcName)-(Ext-ArcName));
|
||||
|
||||
FindFile Find;
|
||||
Find.SetMask(ArcName);
|
||||
@@ -235,7 +235,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
}
|
||||
RecVolNumber=P[1];
|
||||
FileNumber=P[2];
|
||||
wcscpy(PrevName,CurName);
|
||||
wcsncpyz(PrevName,CurName,ASIZE(PrevName));
|
||||
File *NewFile=new File;
|
||||
NewFile->TOpen(CurName);
|
||||
SrcFile[FileNumber+P[0]-1]=NewFile;
|
||||
@@ -247,7 +247,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
if (!Silent || FoundRecVolumes!=0)
|
||||
uiMsg(UIMSG_RECVOLFOUND,FoundRecVolumes);
|
||||
if (FoundRecVolumes==0)
|
||||
return(false);
|
||||
return false;
|
||||
|
||||
bool WriteFlags[256];
|
||||
memset(WriteFlags,0,sizeof(WriteFlags));
|
||||
@@ -290,8 +290,8 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
{
|
||||
NewFile->Close();
|
||||
wchar NewName[NM];
|
||||
wcscpy(NewName,ArcName);
|
||||
wcscat(NewName,L".bad");
|
||||
wcsncpyz(NewName,ArcName,ASIZE(NewName));
|
||||
wcsncatz(NewName,L".bad",ASIZE(NewName));
|
||||
|
||||
uiMsg(UIMSG_BADARCHIVE,ArcName);
|
||||
uiMsg(UIMSG_RENAMING,ArcName,NewName);
|
||||
@@ -322,7 +322,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
MissingVolumes++;
|
||||
|
||||
if (CurArcNum==FileNumber-1)
|
||||
wcscpy(LastVolName,ArcName);
|
||||
wcsncpyz(LastVolName,ArcName,ASIZE(LastVolName));
|
||||
|
||||
uiMsg(UIMSG_MISSINGVOL,ArcName);
|
||||
uiMsg(UIEVENT_NEWARCHIVE,ArcName);
|
||||
@@ -363,11 +363,10 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
|
||||
#ifdef RAR_SMP
|
||||
uint ThreadNumber=Cmd->Threads;
|
||||
RSEncode rse[MaxPoolThreads];
|
||||
#else
|
||||
uint ThreadNumber=1;
|
||||
RSEncode rse[1];
|
||||
#endif
|
||||
RSEncode *rse=new RSEncode[ThreadNumber];
|
||||
for (uint I=0;I<ThreadNumber;I++)
|
||||
rse[I].Init(RecVolNumber);
|
||||
|
||||
@@ -438,6 +437,8 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
if (WriteFlags[I])
|
||||
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
|
||||
}
|
||||
delete[] rse;
|
||||
|
||||
for (int I=0;I<RecVolNumber+FileNumber;I++)
|
||||
if (SrcFile[I]!=NULL)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
static const uint MaxVolumes=65535;
|
||||
|
||||
RecVolumes5::RecVolumes5(bool TestOnly)
|
||||
RecVolumes5::RecVolumes5(RAROptions *Cmd,bool TestOnly)
|
||||
{
|
||||
RealBuf=NULL;
|
||||
RealReadBuffer=NULL;
|
||||
@@ -10,7 +10,14 @@ RecVolumes5::RecVolumes5(bool TestOnly)
|
||||
TotalCount=0;
|
||||
RecBufferSize=0;
|
||||
|
||||
for (uint I=0;I<ASIZE(ThreadData);I++)
|
||||
#ifdef RAR_SMP
|
||||
MaxUserThreads=Cmd->Threads;
|
||||
#else
|
||||
MaxUserThreads=1;
|
||||
#endif
|
||||
|
||||
ThreadData=new RecRSThreadData[MaxUserThreads];
|
||||
for (uint I=0;I<MaxUserThreads;I++)
|
||||
{
|
||||
ThreadData[I].RecRSPtr=this;
|
||||
ThreadData[I].RS=NULL;
|
||||
@@ -25,7 +32,7 @@ RecVolumes5::RecVolumes5(bool TestOnly)
|
||||
else
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
RecThreadPool=CreateThreadPool();
|
||||
RecThreadPool=new ThreadPool(MaxUserThreads);
|
||||
#endif
|
||||
RealBuf=new byte[TotalBufferSize+SSE_ALIGNMENT];
|
||||
Buf=(byte *)ALIGN_VALUE(RealBuf,SSE_ALIGNMENT);
|
||||
@@ -39,10 +46,11 @@ RecVolumes5::~RecVolumes5()
|
||||
delete[] RealReadBuffer;
|
||||
for (uint I=0;I<RecItems.Size();I++)
|
||||
delete RecItems[I].f;
|
||||
for (uint I=0;I<ASIZE(ThreadData);I++)
|
||||
for (uint I=0;I<MaxUserThreads;I++)
|
||||
delete ThreadData[I].RS;
|
||||
delete[] ThreadData;
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(RecThreadPool);
|
||||
delete RecThreadPool;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -68,11 +76,7 @@ void RecVolumes5::ProcessRS(RAROptions *Cmd,uint DataNum,const byte *Data,uint M
|
||||
RS.UpdateECC(DataNum, I, Data, Buf+I*RecBufferSize, MaxRead);
|
||||
*/
|
||||
|
||||
#ifdef RAR_SMP
|
||||
uint ThreadNumber=Cmd->Threads;
|
||||
#else
|
||||
uint ThreadNumber=1;
|
||||
#endif
|
||||
uint ThreadNumber=MaxUserThreads;
|
||||
|
||||
const uint MinThreadBlock=0x1000;
|
||||
ThreadNumber=Min(ThreadNumber,MaxRead/MinThreadBlock);
|
||||
@@ -141,6 +145,8 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
wchar *Num=GetVolNumPart(ArcName);
|
||||
while (Num>ArcName && IsDigit(*(Num-1)))
|
||||
Num--;
|
||||
if (Num==ArcName)
|
||||
return false; // Numeric part is missing or entire volume name is numeric, not possible for RAR or REV volume.
|
||||
wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName));
|
||||
|
||||
wchar FirstVolName[NM];
|
||||
@@ -236,7 +242,7 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
uiMsg(UIMSG_STRING,Item->Name);
|
||||
|
||||
uint RevCRC;
|
||||
CalcFileSum(Item->f,&RevCRC,NULL,Cmd->Threads,INT64NDF,CALCFSUM_CURPOS);
|
||||
CalcFileSum(Item->f,&RevCRC,NULL,MaxUserThreads,INT64NDF,CALCFSUM_CURPOS);
|
||||
Item->Valid=RevCRC==Item->CRC;
|
||||
if (!Item->Valid)
|
||||
{
|
||||
@@ -285,8 +291,8 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
Item->f->Close();
|
||||
|
||||
wchar NewName[NM];
|
||||
wcscpy(NewName,Item->Name);
|
||||
wcscat(NewName,L".bad");
|
||||
wcsncpyz(NewName,Item->Name,ASIZE(NewName));
|
||||
wcsncatz(NewName,L".bad",ASIZE(NewName));
|
||||
|
||||
uiMsg(UIMSG_BADARCHIVE,Item->Name);
|
||||
uiMsg(UIMSG_RENAMING,Item->Name,NewName);
|
||||
|
||||
@@ -2,10 +2,21 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef RARDLL
|
||||
const wchar *St(MSGID StringId)
|
||||
const wchar* St(MSGID StringId)
|
||||
{
|
||||
return StringId;
|
||||
}
|
||||
|
||||
|
||||
// Needed for Unix swprintf to convert %s to %ls in legacy language resources.
|
||||
const wchar *StF(MSGID StringId)
|
||||
{
|
||||
static wchar FormattedStr[512];
|
||||
PrintfPrepareFmt(St(StringId),FormattedStr,ASIZE(FormattedStr));
|
||||
return FormattedStr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
#ifdef RARDLL
|
||||
#define St(x) (L"")
|
||||
#define StF(x) (L"")
|
||||
#else
|
||||
const wchar *St(MSGID StringId);
|
||||
const wchar *StF(MSGID StringId);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -75,11 +75,20 @@ void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVe
|
||||
// Check SSE here instead of constructor, so if object is a part of some
|
||||
// structure memset'ed before use, this variable is not lost.
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, 1);
|
||||
AES_NI=(CPUInfo[2] & 0x2000000)!=0;
|
||||
__cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function.
|
||||
if ((CPUInfo[0] & 0x7fffffff)>=1)
|
||||
{
|
||||
__cpuid(CPUInfo, 1);
|
||||
AES_NI=(CPUInfo[2] & 0x2000000)!=0;
|
||||
}
|
||||
else
|
||||
AES_NI=0;
|
||||
#endif
|
||||
|
||||
uint uKeyLenInBytes;
|
||||
// Other developers asked us to initialize it to suppress "may be used
|
||||
// uninitialized" warning in code below in some compilers.
|
||||
uint uKeyLenInBytes=0;
|
||||
|
||||
switch(keyLen)
|
||||
{
|
||||
case 128:
|
||||
|
||||
@@ -27,7 +27,7 @@ RSCoder16::~RSCoder16()
|
||||
delete[] MX;
|
||||
delete[] ValidFlags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Initialize logarithms and exponents Galois field tables.
|
||||
void RSCoder16::gfInit()
|
||||
@@ -41,7 +41,7 @@ void RSCoder16::gfInit()
|
||||
gfExp[L]=E;
|
||||
gfExp[L+gfSize]=E; // Duplicate the table to avoid gfExp overflow check.
|
||||
E<<=1;
|
||||
if (E>gfSize)
|
||||
if (E>gfSize)
|
||||
E^=0x1100B; // Irreducible field-generator polynomial.
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ uint RSCoder16::gfAdd(uint a,uint b) // Addition in Galois field.
|
||||
}
|
||||
|
||||
|
||||
uint RSCoder16::gfMul(uint a,uint b) // Multiplication in Galois field.
|
||||
uint RSCoder16::gfMul(uint a,uint b) // Multiplication in Galois field.
|
||||
{
|
||||
return gfExp[gfLog[a]+gfLog[b]];
|
||||
}
|
||||
@@ -156,7 +156,7 @@ void RSCoder16::InvertDecoderMatrix()
|
||||
for (uint Kr = 0, Kf = 0; Kr < NE; Kr++, Kf++)
|
||||
{
|
||||
while (ValidFlags[Kf]) // Skip trivial rows.
|
||||
Kf++;
|
||||
Kf++;
|
||||
MI[Kr * ND + Kf] = 1; // Set diagonal 1.
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ void RSCoder16::InvertDecoderMatrix()
|
||||
// after MI[..]^=, but we do not need it for matrix inversion.
|
||||
for (uint I = 0; I < NE; I++)
|
||||
MI[I * ND + Kf] ^= MX[I * ND + Kf];
|
||||
Kf++;
|
||||
Kf++;
|
||||
}
|
||||
|
||||
if (Kf == ND)
|
||||
@@ -186,14 +186,14 @@ void RSCoder16::InvertDecoderMatrix()
|
||||
uint PInv = gfInv( MXk[Kf] ); // Pivot inverse.
|
||||
// Divide the pivot row by pivot, so pivot cell contains 1.
|
||||
for (uint I = 0; I < ND; I++)
|
||||
{
|
||||
{
|
||||
MXk[I] = gfMul( MXk[I], PInv );
|
||||
MIk[I] = gfMul( MIk[I], PInv );
|
||||
}
|
||||
|
||||
for (uint I = 0; I < NE; I++)
|
||||
if (I != Kr) // For all rows except containing the pivot cell.
|
||||
{
|
||||
{
|
||||
// Apply Gaussian elimination Mij -= Mkj * Mik / pivot.
|
||||
// Since pivot is already 1, it is reduced to Mij -= Mkj * Mik.
|
||||
uint *MXi = MX + I * ND; // i-th row of main matrix.
|
||||
@@ -361,7 +361,7 @@ bool RSCoder16::SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte
|
||||
__m128i LowBytes1=_mm_and_si128(D[1],LowByteMask);
|
||||
__m128i HighBytes=_mm_packus_epi16(HighBytes0,HighBytes1);
|
||||
__m128i LowBytes=_mm_packus_epi16(LowBytes0,LowBytes1);
|
||||
|
||||
|
||||
// Multiply bits 0..3 of low bytes. Store low and high product bytes
|
||||
// separately in cumulative sum variables.
|
||||
__m128i LowBytesLow4=_mm_and_si128(LowBytes,Low4Mask);
|
||||
@@ -377,7 +377,7 @@ bool RSCoder16::SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte
|
||||
// Add new product to existing sum, low and high bytes separately.
|
||||
LowBytesMultSum=_mm_xor_si128(LowBytesMultSum,LowBytesHigh4MultLow);
|
||||
HighBytesMultSum=_mm_xor_si128(HighBytesMultSum,LowBytesHigh4MultHigh);
|
||||
|
||||
|
||||
// Multiply bits 0..3 of high bytes. Store low and high product bytes separately.
|
||||
__m128i HighBytesLow4=_mm_and_si128(HighBytes,Low4Mask);
|
||||
__m128i HighBytesLow4MultLow=_mm_shuffle_epi8(T2L,HighBytesLow4);
|
||||
@@ -413,7 +413,7 @@ bool RSCoder16::SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte
|
||||
// because Data and ECC can have different alignment offsets.
|
||||
for (; Pos<BlockSize; Pos+=2)
|
||||
*(ushort*)(ECC+Pos) ^= gfMul( M, *(ushort*)(Data+Pos) );
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,26 @@ class SaveFilePos
|
||||
}
|
||||
~SaveFilePos()
|
||||
{
|
||||
SaveFile->Seek(SavePos,SEEK_SET);
|
||||
// Unless the file is already closed either by current exception
|
||||
// processing or intentionally by external code.
|
||||
if (SaveFile->IsOpened())
|
||||
{
|
||||
try
|
||||
{
|
||||
SaveFile->Seek(SavePos,SEEK_SET);
|
||||
}
|
||||
catch(RAR_EXIT)
|
||||
{
|
||||
// Seek() can throw an exception and it terminates process
|
||||
// if we are already processing another exception. Also in C++ 11
|
||||
// an exception in destructor always terminates process unless
|
||||
// we mark destructor with noexcept(false). So we do not want to
|
||||
// throw here. To prevent data loss we do not want to continue
|
||||
// execution after seek error, so we close the file.
|
||||
// Any next access to this file will return an error.
|
||||
SaveFile->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -142,7 +142,12 @@ bool ScanTree::GetFilteredMask()
|
||||
bool WildcardFound=false;
|
||||
uint FolderWildcardCount=0;
|
||||
uint SlashPos=0;
|
||||
for (int I=0;CurMask[I]!=0;I++)
|
||||
uint StartPos=0;
|
||||
#ifdef _WIN_ALL // Not treat the special NTFS \\?\d: path prefix as a wildcard.
|
||||
if (CurMask[0]=='\\' && CurMask[1]=='\\' && CurMask[2]=='?' && CurMask[3]=='\\')
|
||||
StartPos=4;
|
||||
#endif
|
||||
for (uint I=StartPos;CurMask[I]!=0;I++)
|
||||
{
|
||||
if (CurMask[I]=='?' || CurMask[I]=='*')
|
||||
WildcardFound=true;
|
||||
@@ -171,7 +176,7 @@ bool ScanTree::GetFilteredMask()
|
||||
|
||||
wchar Filter[NM];
|
||||
// Convert path\dir*\ to *\dir filter to search for 'dir' in all 'path' subfolders.
|
||||
wcscpy(Filter,L"*");
|
||||
wcsncpyz(Filter,L"*",ASIZE(Filter));
|
||||
AddEndSlash(Filter,ASIZE(Filter));
|
||||
// SlashPos might point or not point to path separator for masks like 'dir*', '\dir*' or 'd:dir*'
|
||||
wchar *WildName=IsPathDiv(CurMask[SlashPos]) || IsDriveDiv(CurMask[SlashPos]) ? CurMask+SlashPos+1 : CurMask+SlashPos;
|
||||
@@ -226,7 +231,7 @@ bool ScanTree::GetNextMask()
|
||||
SpecPathLength=Name-CurMask;
|
||||
Depth=0;
|
||||
|
||||
wcscpy(OrigCurMask,CurMask);
|
||||
wcsncpyz(OrigCurMask,CurMask,ASIZE(OrigCurMask));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -350,16 +355,19 @@ SCAN_CODE ScanTree::FindProc(FindData *FD)
|
||||
if (Slash!=NULL)
|
||||
{
|
||||
wchar Mask[NM];
|
||||
wcscpy(Mask,Slash);
|
||||
wcsncpyz(Mask,Slash,ASIZE(Mask));
|
||||
if (Depth<SetAllMaskDepth)
|
||||
wcscpy(Mask+1,PointToName(OrigCurMask));
|
||||
wcsncpyz(Mask+1,PointToName(OrigCurMask),ASIZE(Mask)-1);
|
||||
*Slash=0;
|
||||
wcscpy(DirName,CurMask);
|
||||
wcsncpyz(DirName,CurMask,ASIZE(DirName));
|
||||
wchar *PrevSlash=wcsrchr(CurMask,CPATHDIVIDER);
|
||||
if (PrevSlash==NULL)
|
||||
wcscpy(CurMask,Mask+1);
|
||||
wcsncpyz(CurMask,Mask+1,ASIZE(CurMask));
|
||||
else
|
||||
wcscpy(PrevSlash,Mask);
|
||||
{
|
||||
*PrevSlash=0;
|
||||
wcsncatz(CurMask,Mask,ASIZE(CurMask));
|
||||
}
|
||||
}
|
||||
if (GetDirs==SCAN_GETDIRSTWICE &&
|
||||
FindFile::FastFind(DirName,FD,GetLinks) && FD->IsDir)
|
||||
@@ -397,8 +405,8 @@ SCAN_CODE ScanTree::FindProc(FindData *FD)
|
||||
|
||||
wchar Mask[NM];
|
||||
|
||||
wcscpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask));
|
||||
wcscpy(CurMask,FD->Name);
|
||||
wcsncpyz(Mask,FastFindFile ? MASKALL:PointToName(CurMask),ASIZE(Mask));
|
||||
wcsncpyz(CurMask,FD->Name,ASIZE(CurMask));
|
||||
|
||||
if (wcslen(CurMask)+wcslen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ class ScanTree
|
||||
ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs);
|
||||
~ScanTree();
|
||||
SCAN_CODE GetNext(FindData *FindData);
|
||||
size_t GetSpecPathLength() {return SpecPathLength;};
|
||||
size_t GetSpecPathLength() {return SpecPathLength;}
|
||||
int GetErrors() {return Errors;};
|
||||
void SetErrArcName(const wchar *Name) {wcsncpyz(ErrArcName,Name,ASIZE(ErrArcName));}
|
||||
void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;}
|
||||
|
||||
@@ -28,7 +28,8 @@ void IntToExt(const char *Src,char *Dest,size_t DestSize)
|
||||
}
|
||||
|
||||
|
||||
// Convert archived names to Unicode. Allow user to select a code page in GUI.
|
||||
// Convert archived names and comments to Unicode.
|
||||
// Allows user to select a code page in GUI.
|
||||
void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding)
|
||||
{
|
||||
#if defined(_WIN_ALL) // Console Windows RAR.
|
||||
@@ -36,11 +37,12 @@ void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Enc
|
||||
UtfToWide(Src,Dest,DestSize);
|
||||
else
|
||||
{
|
||||
char NameA[NM];
|
||||
Array<char> NameA;
|
||||
if (Encoding==ACTW_OEM)
|
||||
{
|
||||
IntToExt(Src,NameA,ASIZE(NameA));
|
||||
Src=NameA;
|
||||
NameA.Alloc(DestSize+1);
|
||||
IntToExt(Src,&NameA[0],NameA.Size());
|
||||
Src=&NameA[0];
|
||||
}
|
||||
CharToWide(Src,Dest,DestSize);
|
||||
}
|
||||
@@ -58,6 +60,8 @@ void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Enc
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int stricomp(const char *s1,const char *s2)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
@@ -121,7 +125,8 @@ unsigned char loctolower(unsigned char ch)
|
||||
{
|
||||
#if defined(_WIN_ALL)
|
||||
// Convert to LPARAM first to avoid a warning in 64 bit mode.
|
||||
return (int)(LPARAM)CharLowerA((LPSTR)ch);
|
||||
// Convert to uintptr_t to avoid Clang/win error: cast to 'char *' from smaller integer type 'unsigned char' [-Werror,-Wint-to-pointer-cast]
|
||||
return (int)(LPARAM)CharLowerA((LPSTR)(uintptr_t)ch);
|
||||
#else
|
||||
return tolower(ch);
|
||||
#endif
|
||||
@@ -132,7 +137,8 @@ unsigned char loctoupper(unsigned char ch)
|
||||
{
|
||||
#if defined(_WIN_ALL)
|
||||
// Convert to LPARAM first to avoid a warning in 64 bit mode.
|
||||
return (int)(LPARAM)CharUpperA((LPSTR)ch);
|
||||
// Convert to uintptr_t to avoid Clang/win error: cast to 'char *' from smaller integer type 'unsigned char' [-Werror,-Wint-to-pointer-cast]
|
||||
return (int)(LPARAM)CharUpperA((LPSTR)(uintptr_t)ch);
|
||||
#else
|
||||
return toupper(ch);
|
||||
#endif
|
||||
@@ -235,8 +241,8 @@ uint GetDigits(uint Number)
|
||||
|
||||
bool LowAscii(const char *Str)
|
||||
{
|
||||
for (int I=0;Str[I]!=0;I++)
|
||||
if ((byte)Str[I]<32 || (byte)Str[I]>127)
|
||||
for (size_t I=0;Str[I]!=0;I++)
|
||||
if (/*(byte)Str[I]<32 || */(byte)Str[I]>127)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -244,11 +250,11 @@ bool LowAscii(const char *Str)
|
||||
|
||||
bool LowAscii(const wchar *Str)
|
||||
{
|
||||
for (int I=0;Str[I]!=0;I++)
|
||||
for (size_t I=0;Str[I]!=0;I++)
|
||||
{
|
||||
// We convert wchar_t to uint just in case if some compiler
|
||||
// uses signed wchar_t.
|
||||
if ((uint)Str[I]<32 || (uint)Str[I]>127)
|
||||
if (/*(uint)Str[I]<32 || */(uint)Str[I]>127)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -275,53 +281,49 @@ int wcsnicompc(const wchar *s1,const wchar *s2,size_t n)
|
||||
}
|
||||
|
||||
|
||||
// Safe strncpy: copies maxlen-1 max and always returns zero terminated dest.
|
||||
char* strncpyz(char *dest, const char *src, size_t maxlen)
|
||||
// Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
|
||||
void strncpyz(char *dest, const char *src, size_t maxlen)
|
||||
{
|
||||
if (maxlen>0)
|
||||
{
|
||||
strncpy(dest,src,maxlen-1);
|
||||
dest[maxlen-1]=0;
|
||||
while (--maxlen>0 && *src!=0)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe wcsncpy: copies maxlen-1 max and always returns zero terminated dest.
|
||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
||||
// Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
|
||||
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
||||
{
|
||||
if (maxlen>0)
|
||||
{
|
||||
wcsncpy(dest,src,maxlen-1);
|
||||
dest[maxlen-1]=0;
|
||||
while (--maxlen>0 && *src!=0)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe strncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard strncat.
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen)
|
||||
// Safe append: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with wcsncat.
|
||||
void strncatz(char* dest, const char* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = strlen(dest);
|
||||
int avail=int(maxlen - Length - 1);
|
||||
if (avail > 0)
|
||||
strncat(dest, src, avail);
|
||||
return dest;
|
||||
size_t length = strlen(dest);
|
||||
if (maxlen > length)
|
||||
strncpyz(dest + length, src, maxlen - length);
|
||||
}
|
||||
|
||||
|
||||
// Safe wcsncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard wcsncat.
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
||||
// Safe append: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with wcsncat.
|
||||
void wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = wcslen(dest);
|
||||
int avail=int(maxlen - Length - 1);
|
||||
if (avail > 0)
|
||||
wcsncat(dest, src, avail);
|
||||
return dest;
|
||||
size_t length = wcslen(dest);
|
||||
if (maxlen > length)
|
||||
wcsncpyz(dest + length, src, maxlen - length);
|
||||
}
|
||||
|
||||
|
||||
@@ -428,7 +430,7 @@ const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize)
|
||||
}
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
#ifndef RARDLL
|
||||
// For compatibility with existing translations we use %s to print Unicode
|
||||
// strings in format strings and convert them to %ls here. %s could work
|
||||
// without such conversion in Windows, but not in Unix wprintf.
|
||||
|
||||
@@ -8,6 +8,7 @@ void IntToExt(const char *Src,char *Dest,size_t DestSize);
|
||||
enum ACTW_ENCODING { ACTW_DEFAULT, ACTW_OEM, ACTW_UTF8};
|
||||
void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding);
|
||||
|
||||
|
||||
int stricomp(const char *s1,const char *s2);
|
||||
int strnicomp(const char *s1,const char *s2,size_t n);
|
||||
wchar* RemoveEOL(wchar *Str);
|
||||
@@ -15,10 +16,10 @@ wchar* RemoveLF(wchar *Str);
|
||||
unsigned char loctolower(unsigned char ch);
|
||||
unsigned char loctoupper(unsigned char ch);
|
||||
|
||||
char* strncpyz(char *dest, const char *src, size_t maxlen);
|
||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen);
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||
void strncpyz(char *dest, const char *src, size_t maxlen);
|
||||
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||
void strncatz(char* dest, const char* src, size_t maxlen);
|
||||
void wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||
|
||||
unsigned char etoupper(unsigned char ch);
|
||||
wchar etoupperw(wchar ch);
|
||||
@@ -43,7 +44,7 @@ void itoa(int64 n,char *Str,size_t MaxSize);
|
||||
void itoa(int64 n,wchar *Str,size_t MaxSize);
|
||||
const wchar* GetWide(const char *Src);
|
||||
const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize);
|
||||
#ifndef SILENT
|
||||
#ifndef RARDLL
|
||||
void PrintfPrepareFmt(const wchar *Org,wchar *Cvt,size_t MaxSize);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class StringList
|
||||
Array<wchar> StringData;
|
||||
size_t CurPos;
|
||||
|
||||
uint StringsCount;
|
||||
size_t StringsCount;
|
||||
|
||||
size_t SaveCurPos[16],SavePosNumber;
|
||||
public:
|
||||
@@ -21,7 +21,7 @@ class StringList
|
||||
wchar* GetString();
|
||||
bool GetString(wchar **Str);
|
||||
void Rewind();
|
||||
uint ItemsCount() {return StringsCount;};
|
||||
size_t ItemsCount() {return StringsCount;};
|
||||
size_t GetCharCount() {return StringData.Size();}
|
||||
bool Search(const wchar *Str,bool CaseSensitive);
|
||||
void SavePosition();
|
||||
|
||||
@@ -80,7 +80,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
||||
{
|
||||
uint t=SASize << 20;
|
||||
if (SubAllocatorSize == t)
|
||||
return TRUE;
|
||||
return true;
|
||||
StopSubAllocator();
|
||||
|
||||
// Original algorithm expects FIXED_UNIT_SIZE, but actual structure size
|
||||
@@ -91,7 +91,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
||||
if ((HeapStart=(byte *)malloc(AllocSize)) == NULL)
|
||||
{
|
||||
ErrHandler.MemoryError();
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// HeapEnd did not present in original algorithm. We added it to control
|
||||
@@ -99,7 +99,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
||||
HeapEnd=HeapStart+AllocSize-UNIT_SIZE;
|
||||
|
||||
SubAllocatorSize=t;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -215,13 +215,13 @@ void* SubAllocator::AllocUnitsRare(int indx)
|
||||
GlueCount--;
|
||||
i=U2B(Indx2Units[indx]);
|
||||
int j=FIXED_UNIT_SIZE*Indx2Units[indx];
|
||||
if (FakeUnitsStart-pText > j)
|
||||
if (FakeUnitsStart - pText > j)
|
||||
{
|
||||
FakeUnitsStart-=j;
|
||||
FakeUnitsStart -= j;
|
||||
UnitsStart -= i;
|
||||
return(UnitsStart);
|
||||
return UnitsStart;
|
||||
}
|
||||
return(NULL);
|
||||
return NULL;
|
||||
}
|
||||
} while ( !FreeList[i].next );
|
||||
void* RetVal=RemoveNode(i);
|
||||
|
||||
@@ -77,7 +77,7 @@ class SubAllocator
|
||||
inline void* ExpandUnits(void* ptr,int OldNU);
|
||||
inline void* ShrinkUnits(void* ptr,int OldNU,int NewNU);
|
||||
inline void FreeUnits(void* ptr,int OldNU);
|
||||
long GetAllocatedMemory() {return(SubAllocatorSize);};
|
||||
long GetAllocatedMemory() {return(SubAllocatorSize);}
|
||||
|
||||
byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
|
||||
};
|
||||
|
||||
@@ -102,7 +102,7 @@ void Wait()
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
void Shutdown()
|
||||
void Shutdown(POWER_MODE Mode)
|
||||
{
|
||||
HANDLE hToken;
|
||||
TOKEN_PRIVILEGES tkp;
|
||||
@@ -114,7 +114,36 @@ void Shutdown()
|
||||
|
||||
AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
|
||||
}
|
||||
ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE|EWX_POWEROFF,SHTDN_REASON_FLAG_PLANNED);
|
||||
if (Mode==POWERMODE_OFF)
|
||||
ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE,SHTDN_REASON_FLAG_PLANNED);
|
||||
if (Mode==POWERMODE_SLEEP)
|
||||
SetSuspendState(FALSE,FALSE,FALSE);
|
||||
if (Mode==POWERMODE_HIBERNATE)
|
||||
SetSuspendState(TRUE,FALSE,FALSE);
|
||||
if (Mode==POWERMODE_RESTART)
|
||||
ExitWindowsEx(EWX_REBOOT|EWX_FORCE,SHTDN_REASON_FLAG_PLANNED);
|
||||
}
|
||||
|
||||
|
||||
bool ShutdownCheckAnother(bool Open)
|
||||
{
|
||||
const wchar *EventName=L"rar -ioff";
|
||||
static HANDLE hEvent=NULL;
|
||||
bool Result=false; // Return false if no other RAR -ioff are running.
|
||||
if (Open) // Create or open the event.
|
||||
hEvent=CreateEvent(NULL,FALSE,FALSE,EventName);
|
||||
else
|
||||
{
|
||||
if (hEvent!=NULL)
|
||||
CloseHandle(hEvent); // Close our event.
|
||||
// Check if other copies still own the event. While race conditions
|
||||
// are possible, they are improbable and their harm is minimal.
|
||||
hEvent=CreateEvent(NULL,FALSE,FALSE,EventName);
|
||||
Result=GetLastError()==ERROR_ALREADY_EXISTS;
|
||||
if (hEvent!=NULL)
|
||||
CloseHandle(hEvent);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -158,18 +187,29 @@ SSE_VERSION _SSE_Version=GetSSEVersion();
|
||||
SSE_VERSION GetSSEVersion()
|
||||
{
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, 7);
|
||||
if ((CPUInfo[1] & 0x20)!=0)
|
||||
return SSE_AVX2;
|
||||
__cpuid(CPUInfo, 1);
|
||||
if ((CPUInfo[2] & 0x80000)!=0)
|
||||
return SSE_SSE41;
|
||||
if ((CPUInfo[2] & 0x200)!=0)
|
||||
return SSE_SSSE3;
|
||||
if ((CPUInfo[3] & 0x4000000)!=0)
|
||||
return SSE_SSE2;
|
||||
if ((CPUInfo[3] & 0x2000000)!=0)
|
||||
return SSE_SSE;
|
||||
__cpuid(CPUInfo, 0x80000000);
|
||||
|
||||
// Maximum supported cpuid function. For example, Pentium M 755 returns 4 here.
|
||||
uint MaxSupported=CPUInfo[0] & 0x7fffffff;
|
||||
|
||||
if (MaxSupported>=7)
|
||||
{
|
||||
__cpuid(CPUInfo, 7);
|
||||
if ((CPUInfo[1] & 0x20)!=0)
|
||||
return SSE_AVX2;
|
||||
}
|
||||
if (MaxSupported>=1)
|
||||
{
|
||||
__cpuid(CPUInfo, 1);
|
||||
if ((CPUInfo[2] & 0x80000)!=0)
|
||||
return SSE_SSE41;
|
||||
if ((CPUInfo[2] & 0x200)!=0)
|
||||
return SSE_SSSE3;
|
||||
if ((CPUInfo[3] & 0x4000000)!=0)
|
||||
return SSE_SSE2;
|
||||
if ((CPUInfo[3] & 0x2000000)!=0)
|
||||
return SSE_SSE;
|
||||
}
|
||||
return SSE_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,8 @@ void SetPriority(int Priority);
|
||||
clock_t MonoClock();
|
||||
void Wait();
|
||||
bool EmailFile(const wchar *FileName,const wchar *MailToW);
|
||||
void Shutdown();
|
||||
void Shutdown(POWER_MODE Mode);
|
||||
bool ShutdownCheckAnother(bool Open);
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
HMODULE WINAPI LoadSysLibrary(const wchar *Name);
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
// Typically we use the same global thread pool for all RAR modules.
|
||||
static ThreadPool *GlobalPool=NULL;
|
||||
static uint GlobalPoolUseCount=0;
|
||||
|
||||
static inline bool CriticalSectionCreate(CRITSECT_HANDLE *CritSection)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
@@ -43,57 +39,6 @@ static inline void CriticalSectionEnd(CRITSECT_HANDLE *CritSection)
|
||||
}
|
||||
|
||||
|
||||
static struct GlobalPoolCreateSync
|
||||
{
|
||||
CRITSECT_HANDLE CritSection;
|
||||
GlobalPoolCreateSync() { CriticalSectionCreate(&CritSection); }
|
||||
~GlobalPoolCreateSync() { CriticalSectionDelete(&CritSection); }
|
||||
} PoolCreateSync;
|
||||
|
||||
|
||||
ThreadPool* CreateThreadPool()
|
||||
{
|
||||
CriticalSectionStart(&PoolCreateSync.CritSection);
|
||||
|
||||
if (GlobalPoolUseCount++ == 0)
|
||||
GlobalPool=new ThreadPool(MaxPoolThreads);
|
||||
|
||||
// We use a simple thread pool, which does not allow to add tasks from
|
||||
// different functions and threads in the same time. It is ok for RAR,
|
||||
// but UnRAR.dll can be used in multithreaded environment. So if one of
|
||||
// threads requests a copy of global pool and another copy is already
|
||||
// in use, we create and return a new pool instead of existing global.
|
||||
if (GlobalPoolUseCount > 1)
|
||||
{
|
||||
ThreadPool *Pool = new ThreadPool(MaxPoolThreads);
|
||||
CriticalSectionEnd(&PoolCreateSync.CritSection);
|
||||
return Pool;
|
||||
}
|
||||
|
||||
CriticalSectionEnd(&PoolCreateSync.CritSection);
|
||||
return GlobalPool;
|
||||
}
|
||||
|
||||
|
||||
void DestroyThreadPool(ThreadPool *Pool)
|
||||
{
|
||||
if (Pool!=NULL)
|
||||
{
|
||||
CriticalSectionStart(&PoolCreateSync.CritSection);
|
||||
|
||||
if (Pool==GlobalPool && GlobalPoolUseCount > 0 && --GlobalPoolUseCount == 0)
|
||||
delete GlobalPool;
|
||||
|
||||
// To correctly work in multithreaded environment UnRAR.dll creates
|
||||
// new pools if global pool is already in use. We delete such pools here.
|
||||
if (Pool!=GlobalPool)
|
||||
delete Pool;
|
||||
|
||||
CriticalSectionEnd(&PoolCreateSync.CritSection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static THREAD_HANDLE ThreadCreate(NATIVE_THREAD_PTR Proc,void *Data)
|
||||
{
|
||||
#ifdef _UNIX
|
||||
|
||||
@@ -170,12 +170,13 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data)
|
||||
CreateThreads();
|
||||
|
||||
// If queue is full, wait until it is empty.
|
||||
if ((QueueTop + 1) % ASIZE(TaskQueue) == QueueBottom)
|
||||
if (ActiveThreads>=ASIZE(TaskQueue))
|
||||
WaitDone();
|
||||
|
||||
TaskQueue[QueueTop].Proc = Proc;
|
||||
TaskQueue[QueueTop].Param = Data;
|
||||
QueueTop = (QueueTop + 1) % ASIZE(TaskQueue);
|
||||
ActiveThreads++;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,9 +185,6 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data)
|
||||
// are sleeping yet.
|
||||
void ThreadPool::WaitDone()
|
||||
{
|
||||
// We add ASIZE(TaskQueue) for case if TaskQueue array size is not
|
||||
// a power of two. Negative numbers would not suit our purpose here.
|
||||
ActiveThreads=(QueueTop+ASIZE(TaskQueue)-QueueBottom) % ASIZE(TaskQueue);
|
||||
if (ActiveThreads==0)
|
||||
return;
|
||||
#ifdef _WIN_ALL
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
#ifndef RAR_SMP
|
||||
const uint MaxPoolThreads=1; // For single threaded version.
|
||||
#else
|
||||
const uint MaxPoolThreads=32;
|
||||
// We need to use the processor groups API to increase it beyond 64.
|
||||
// Also be sure to check and adjust if needed per thread and total block size
|
||||
// when compressing if going above 64.
|
||||
const uint MaxPoolThreads=64;
|
||||
|
||||
|
||||
#ifdef _UNIX
|
||||
@@ -98,9 +101,6 @@ class ThreadPool
|
||||
#endif
|
||||
};
|
||||
|
||||
ThreadPool* CreateThreadPool();
|
||||
void DestroyThreadPool(ThreadPool *Pool);
|
||||
|
||||
#endif // RAR_SMP
|
||||
|
||||
#endif // _RAR_THREADPOOL_
|
||||
|
||||
@@ -25,9 +25,9 @@ void RarTime::GetLocal(RarLocalTime *lt)
|
||||
// Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime.
|
||||
FILETIME rft;
|
||||
SystemTimeToFileTime(&st1,&rft);
|
||||
int64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)-
|
||||
INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
|
||||
INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime);
|
||||
uint64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)-
|
||||
INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
|
||||
INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime);
|
||||
lft.dwLowDateTime=(DWORD)Corrected;
|
||||
lft.dwHighDateTime=(DWORD)(Corrected>>32);
|
||||
}
|
||||
@@ -100,9 +100,9 @@ void RarTime::SetLocal(RarLocalTime *lt)
|
||||
// Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime.
|
||||
FILETIME rft;
|
||||
SystemTimeToFileTime(&st2,&rft);
|
||||
int64 Corrected=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)-
|
||||
INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
|
||||
INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime);
|
||||
uint64 Corrected=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)-
|
||||
INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
|
||||
INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime);
|
||||
ft.dwLowDateTime=(DWORD)Corrected;
|
||||
ft.dwHighDateTime=(DWORD)(Corrected>>32);
|
||||
}
|
||||
@@ -236,7 +236,7 @@ void RarTime::GetText(wchar *DateStr,size_t MaxSize,bool FullMS)
|
||||
else
|
||||
{
|
||||
// We use escape before '?' to avoid weird C trigraph characters.
|
||||
wcscpy(DateStr,L"\?\?\?\?-\?\?-\?\? \?\?:\?\?");
|
||||
wcsncpyz(DateStr,L"\?\?\?\?-\?\?-\?\? \?\?:\?\?",MaxSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ void RarTime::SetIsoText(const wchar *TimeText)
|
||||
void RarTime::SetAgeText(const wchar *TimeText)
|
||||
{
|
||||
uint Seconds=0,Value=0;
|
||||
for (int I=0;TimeText[I]!=0;I++)
|
||||
for (uint I=0;TimeText[I]!=0;I++)
|
||||
{
|
||||
int Ch=TimeText[I];
|
||||
if (IsDigit(Ch))
|
||||
|
||||
42
unrar/ui.hpp
42
unrar/ui.hpp
@@ -10,16 +10,17 @@ enum UIMESSAGE_CODE {
|
||||
UIERROR_SYSERRMSG, UIERROR_GENERALERRMSG, UIERROR_INCERRCOUNT,
|
||||
UIERROR_CHECKSUM, UIERROR_CHECKSUMENC, UIERROR_CHECKSUMPACKED,
|
||||
UIERROR_BADPSW, UIERROR_MEMORY, UIERROR_FILEOPEN, UIERROR_FILECREATE,
|
||||
UIERROR_FILECLOSE, UIERROR_FILESEEK, UIERROR_FILEREAD,
|
||||
UIERROR_FILEWRITE, UIERROR_FILEDELETE, UIERROR_FILERENAME,
|
||||
UIERROR_FILECLOSE, UIERROR_FILESEEK, UIERROR_FILEREAD, UIERROR_FILEWRITE,
|
||||
UIERROR_FILEDELETE, UIERROR_RECYCLEFAILED, UIERROR_FILERENAME,
|
||||
UIERROR_FILEATTR, UIERROR_FILECOPY, UIERROR_FILECOPYHINT,
|
||||
UIERROR_DIRCREATE, UIERROR_SLINKCREATE, UIERROR_HLINKCREATE,
|
||||
UIERROR_NEEDADMIN, UIERROR_ARCBROKEN, UIERROR_HEADERBROKEN,
|
||||
UIERROR_MHEADERBROKEN, UIERROR_FHEADERBROKEN, UIERROR_SUBHEADERBROKEN,
|
||||
UIERROR_SUBHEADERUNKNOWN, UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED,
|
||||
UIERROR_UNKNOWNMETHOD, UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING,
|
||||
UIERROR_NEWERRAR, UIERROR_NOTSFX, UIERROR_OLDTOSFX,
|
||||
UIERROR_WRONGSFXVER, UIERROR_ALREADYENC, UIERROR_DICTOUTMEM,
|
||||
UIERROR_NOLINKTARGET, UIERROR_NEEDADMIN, UIERROR_ARCBROKEN,
|
||||
UIERROR_HEADERBROKEN, UIERROR_MHEADERBROKEN, UIERROR_FHEADERBROKEN,
|
||||
UIERROR_SUBHEADERBROKEN, UIERROR_SUBHEADERUNKNOWN,
|
||||
UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED, UIERROR_UNKNOWNMETHOD,
|
||||
UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING, UIERROR_NEWERRAR,
|
||||
UIERROR_NOTSFX, UIERROR_OLDTOSFX,
|
||||
UIERROR_WRONGSFXVER, UIERROR_HEADENCMISMATCH, UIERROR_DICTOUTMEM,
|
||||
UIERROR_USESMALLERDICT, UIERROR_MODIFYUNKNOWN, UIERROR_MODIFYOLD,
|
||||
UIERROR_MODIFYLOCKED, UIERROR_MODIFYVOLUME, UIERROR_NOTVOLUME,
|
||||
UIERROR_NOTFIRSTVOLUME, UIERROR_RECVOLLIMIT, UIERROR_RECVOLDIFFSETS,
|
||||
@@ -31,16 +32,17 @@ enum UIMESSAGE_CODE {
|
||||
UIERROR_NOFILESTOADD, UIERROR_NOFILESTODELETE, UIERROR_NOFILESTOEXTRACT,
|
||||
UIERROR_MISSINGVOL, UIERROR_NEEDPREVVOL, UIERROR_UNKNOWNEXTRA,
|
||||
UIERROR_CORRUPTEXTRA, UIERROR_NTFSREQUIRED, UIERROR_ZIPVOLSFX,
|
||||
UIERROR_FILERO, UIERROR_TOOLARGESFX, UIERROR_EMAIL, UIERROR_ACLGET,
|
||||
UIERROR_ACLBROKEN, UIERROR_ACLUNKNOWN, UIERROR_ACLSET, UIERROR_STREAMBROKEN,
|
||||
UIERROR_STREAMUNKNOWN, UIERROR_INCOMPATSWITCH, UIERROR_PATHTOOLONG,
|
||||
UIERROR_DIRSCAN, UIERROR_UOWNERGET, UIERROR_UOWNERBROKEN,
|
||||
UIERROR_UOWNERGETOWNERID, UIERROR_UOWNERGETGROUPID, UIERROR_UOWNERSET,
|
||||
UIERROR_ULINKREAD, UIERROR_ULINKEXIST,
|
||||
UIERROR_FILERO, UIERROR_TOOLARGESFX, UIERROR_NOZIPSFX, UIERROR_EMAIL,
|
||||
UIERROR_ACLGET, UIERROR_ACLBROKEN, UIERROR_ACLUNKNOWN, UIERROR_ACLSET,
|
||||
UIERROR_STREAMBROKEN, UIERROR_STREAMUNKNOWN, UIERROR_INCOMPATSWITCH,
|
||||
UIERROR_PATHTOOLONG, UIERROR_DIRSCAN, UIERROR_UOWNERGET,
|
||||
UIERROR_UOWNERBROKEN, UIERROR_UOWNERGETOWNERID, UIERROR_UOWNERGETGROUPID,
|
||||
UIERROR_UOWNERSET, UIERROR_ULINKREAD, UIERROR_ULINKEXIST,
|
||||
UIERROR_OPENPRESERVEATIME,
|
||||
|
||||
UIMSG_FIRST,
|
||||
UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_RRFOUND,
|
||||
UIMSG_RRNOTFOUND, UIMSG_RRDAMAGED, UIMSG_BLOCKSRECOVERED,
|
||||
UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_ANALYZEFILEDATA,
|
||||
UIMSG_RRFOUND, UIMSG_RRNOTFOUND, UIMSG_RRDAMAGED, UIMSG_BLOCKSRECOVERED,
|
||||
UIMSG_COPYINGDATA, UIMSG_AREADAMAGED, UIMSG_SECTORDAMAGED,
|
||||
UIMSG_SECTORRECOVERED, UIMSG_SECTORNOTRECOVERED, UIMSG_FOUND,
|
||||
UIMSG_CORRECTINGNAME, UIMSG_BADARCHIVE, UIMSG_CREATING, UIMSG_RENAMING,
|
||||
@@ -75,7 +77,7 @@ enum UIASKREP_RESULT {
|
||||
UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags);
|
||||
UIASKREP_RESULT uiAskReplaceEx(RAROptions *Cmd,wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags);
|
||||
|
||||
void uiInit(bool Sound);
|
||||
void uiInit(SOUND_NOTIFY_MODE Sound);
|
||||
|
||||
|
||||
void uiStartArchiveExtract(bool Extract,const wchar *ArcName);
|
||||
@@ -85,6 +87,7 @@ void uiProcessProgress(const char *Command,int64 CurSize,int64 TotalSize);
|
||||
|
||||
enum UIPASSWORD_TYPE {UIPASSWORD_GLOBAL,UIPASSWORD_FILE,UIPASSWORD_ARCHIVE};
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password);
|
||||
bool uiIsGlobalPasswordSet();
|
||||
|
||||
enum UIALARM_TYPE {UIALARM_ERROR, UIALARM_INFO, UIALARM_QUESTION};
|
||||
void uiAlarm(UIALARM_TYPE Type);
|
||||
@@ -110,6 +113,11 @@ class uiMsgStore
|
||||
public:
|
||||
uiMsgStore(UIMESSAGE_CODE Code)
|
||||
{
|
||||
// Init arrays in case a caller passes fewer parameters than expected.
|
||||
for (uint I=0;I<ASIZE(Str);I++)
|
||||
Str[I]=L"";
|
||||
memset(Num,0,sizeof(Num));
|
||||
|
||||
NumSize=StrSize=0;
|
||||
this->Code=Code;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
static bool uiSoundEnabled;
|
||||
static SOUND_NOTIFY_MODE uiSoundNotify;
|
||||
|
||||
void uiInit(bool Sound)
|
||||
void uiInit(SOUND_NOTIFY_MODE Sound)
|
||||
{
|
||||
uiSoundEnabled = Sound;
|
||||
uiSoundNotify = Sound;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,10 @@ UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTi
|
||||
{
|
||||
itoa(FileSize,SizeText2,ASIZE(SizeText2));
|
||||
FileTime->GetText(DateStr2,ASIZE(DateStr2),false);
|
||||
eprintf(St(MAskReplace),Name,SizeText1,DateStr1,SizeText2,DateStr2);
|
||||
if ((Flags & UIASKREP_F_EXCHSRCDEST)==0)
|
||||
eprintf(St(MAskReplace),Name,SizeText1,DateStr1,SizeText2,DateStr2);
|
||||
else
|
||||
eprintf(St(MAskReplace),Name,SizeText2,DateStr2,SizeText1,DateStr1);
|
||||
}
|
||||
|
||||
bool AllowRename=(Flags & UIASKREP_F_NORENAME)==0;
|
||||
@@ -96,10 +99,13 @@ void uiMsgStore::Msg()
|
||||
Log(Str[0],St(MDataBadCRC),Str[1],Str[0]);
|
||||
break;
|
||||
case UIERROR_BADPSW:
|
||||
Log(Str[0],St(MWrongFilePassword),Str[1]);
|
||||
break;
|
||||
case UIWAIT_BADPSW:
|
||||
Log(Str[0],St(MWrongPassword));
|
||||
break;
|
||||
case UIERROR_MEMORY:
|
||||
mprintf(L"\n");
|
||||
Log(NULL,St(MErrOutMem));
|
||||
break;
|
||||
case UIERROR_FILEOPEN:
|
||||
@@ -124,6 +130,9 @@ void uiMsgStore::Msg()
|
||||
case UIERROR_FILEDELETE:
|
||||
Log(Str[0],St(MCannotDelete),Str[1]);
|
||||
break;
|
||||
case UIERROR_RECYCLEFAILED:
|
||||
Log(Str[0],St(MRecycleFailed));
|
||||
break;
|
||||
case UIERROR_FILERENAME:
|
||||
Log(Str[0],St(MErrRename),Str[1],Str[2]);
|
||||
break;
|
||||
@@ -147,6 +156,10 @@ void uiMsgStore::Msg()
|
||||
case UIERROR_HLINKCREATE:
|
||||
Log(NULL,St(MErrCreateLnkH),Str[0]);
|
||||
break;
|
||||
case UIERROR_NOLINKTARGET:
|
||||
Log(NULL,St(MErrLnkTarget));
|
||||
mprintf(L" "); // For progress percent.
|
||||
break;
|
||||
case UIERROR_NEEDADMIN:
|
||||
Log(NULL,St(MNeedAdmin));
|
||||
break;
|
||||
@@ -178,7 +191,11 @@ void uiMsgStore::Msg()
|
||||
Log(Str[0],St(MUnknownMeth),Str[1]);
|
||||
break;
|
||||
case UIERROR_UNKNOWNENCMETHOD:
|
||||
Log(Str[0],St(MUnkEncMethod),Str[1]);
|
||||
{
|
||||
wchar Msg[256];
|
||||
swprintf(Msg,ASIZE(Msg),St(MUnkEncMethod),Str[1]);
|
||||
Log(Str[0],L"%s: %s",Msg,Str[2]);
|
||||
}
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case UIERROR_RENAMING:
|
||||
@@ -211,6 +228,7 @@ void uiMsgStore::Msg()
|
||||
break;
|
||||
case UIERROR_INVALIDNAME:
|
||||
Log(Str[0],St(MInvalidName),Str[1]);
|
||||
mprintf(L"\n"); // Needed when called from CmdExtract::ExtractCurrentFile.
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case UIERROR_NEWRARFORMAT:
|
||||
@@ -339,13 +357,22 @@ void uiMsgStore::Msg()
|
||||
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
|
||||
{
|
||||
return GetConsolePassword(Type,FileName,Password);
|
||||
// Unlike GUI we cannot provide Cancel button here, so we use the empty
|
||||
// password to abort. Otherwise user not knowing a password would need to
|
||||
// press Ctrl+C multiple times to quit from infinite password request loop.
|
||||
return GetConsolePassword(Type,FileName,Password) && Password->IsSet();
|
||||
}
|
||||
|
||||
|
||||
bool uiIsGlobalPasswordSet()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void uiAlarm(UIALARM_TYPE Type)
|
||||
{
|
||||
if (uiSoundEnabled)
|
||||
if (uiSoundNotify==SOUND_NOTIFY_ON)
|
||||
{
|
||||
static clock_t LastTime=-10; // Negative to always beep first time.
|
||||
if ((MonoClock()-LastTime)/CLOCKS_PER_SEC>5)
|
||||
|
||||
@@ -39,6 +39,12 @@ bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Passw
|
||||
}
|
||||
|
||||
|
||||
bool uiIsGlobalPasswordSet()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void uiAlarm(UIALARM_TYPE Type)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,8 +50,11 @@ bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const w
|
||||
char Target[NM];
|
||||
if (IsLink(Arc.FileHead.FileAttr))
|
||||
{
|
||||
size_t DataSize=Min(Arc.FileHead.PackSize,ASIZE(Target)-1);
|
||||
DataIO.UnpRead((byte *)Target,DataSize);
|
||||
size_t DataSize=(size_t)Arc.FileHead.PackSize;
|
||||
if (DataSize>ASIZE(Target)-1)
|
||||
return false;
|
||||
if ((size_t)DataIO.UnpRead((byte *)Target,DataSize)!=DataSize)
|
||||
return false;
|
||||
Target[DataSize]=0;
|
||||
|
||||
DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,1);
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#ifndef _RAR_ULINKS_
|
||||
#define _RAR_ULINKS_
|
||||
|
||||
void SaveLinkData(ComprDataIO &DataIO,Archive &TempArc,FileHeader &hd,
|
||||
const char *Name);
|
||||
bool ExtractLink(ComprDataIO &DataIO,Archive &Arc,const char *LinkName,
|
||||
uint &LinkCRC,bool Create);
|
||||
|
||||
#endif
|
||||
@@ -36,7 +36,25 @@ bool WideToChar(const wchar *Src,char *Dest,size_t DestSize)
|
||||
mbstate_t ps; // Use thread safe external state based functions.
|
||||
memset (&ps, 0, sizeof(ps));
|
||||
const wchar *SrcParam=Src; // wcsrtombs can change the pointer.
|
||||
|
||||
// Some implementations of wcsrtombs can cause memory analyzing tools
|
||||
// like valgrind to report uninitialized data access. It happens because
|
||||
// internally these implementations call SSE4 based wcslen function,
|
||||
// which reads 16 bytes at once including those beyond of trailing 0.
|
||||
size_t ResultingSize=wcsrtombs(Dest,&SrcParam,DestSize,&ps);
|
||||
|
||||
if (ResultingSize==(size_t)-1 && errno==EILSEQ)
|
||||
{
|
||||
// Aborted on inconvertible character not zero terminating the result.
|
||||
// EILSEQ helps to distinguish it from small output buffer abort.
|
||||
// We want to convert as much as we can, so we clean the output buffer
|
||||
// and repeat conversion.
|
||||
memset (&ps, 0, sizeof(ps));
|
||||
SrcParam=Src; // wcsrtombs can change the pointer.
|
||||
memset(Dest,0,DestSize);
|
||||
ResultingSize=wcsrtombs(Dest,&SrcParam,DestSize,&ps);
|
||||
}
|
||||
|
||||
if (ResultingSize==(size_t)-1)
|
||||
RetCode=false;
|
||||
if (ResultingSize==0 && *Src!=0)
|
||||
@@ -52,7 +70,7 @@ bool WideToChar(const wchar *Src,char *Dest,size_t DestSize)
|
||||
#endif
|
||||
if (DestSize>0)
|
||||
Dest[DestSize-1]=0;
|
||||
|
||||
|
||||
// We tried to return the empty string if conversion is failed,
|
||||
// but it does not work well. WideCharToMultiByte returns 'failed' code
|
||||
// and partially converted string even if we wanted to convert only a part
|
||||
@@ -120,21 +138,21 @@ bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success)
|
||||
if (wcschr(Src,(wchar)MappedStringMark)==NULL)
|
||||
return false;
|
||||
|
||||
// Seems to be that wcrtomb in some memory analyzing libraries
|
||||
// can produce uninitilized output while reporting success on garbage input.
|
||||
// So we clean the destination to calm analyzers.
|
||||
memset(Dest,0,DestSize);
|
||||
|
||||
Success=true;
|
||||
uint SrcPos=0,DestPos=0;
|
||||
while (DestPos<DestSize-MB_CUR_MAX)
|
||||
while (Src[SrcPos]!=0 && DestPos<DestSize-MB_CUR_MAX)
|
||||
{
|
||||
if (Src[SrcPos]==0)
|
||||
{
|
||||
Dest[DestPos]=0;
|
||||
break;
|
||||
}
|
||||
if (uint(Src[SrcPos])==MappedStringMark)
|
||||
{
|
||||
SrcPos++;
|
||||
continue;
|
||||
}
|
||||
// For security reasons do not retore low ASCII codes, so mapping cannot
|
||||
// For security reasons do not restore low ASCII codes, so mapping cannot
|
||||
// be used to hide control codes like path separators.
|
||||
if (uint(Src[SrcPos])>=MapAreaStart+0x80 && uint(Src[SrcPos])<MapAreaStart+0x100)
|
||||
Dest[DestPos++]=char(uint(Src[SrcPos++])-MapAreaStart);
|
||||
@@ -142,21 +160,25 @@ bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success)
|
||||
{
|
||||
mbstate_t ps;
|
||||
memset(&ps,0,sizeof(ps));
|
||||
if (wcrtomb(Dest+DestPos,Src[SrcPos],&ps)==-1)
|
||||
if (wcrtomb(Dest+DestPos,Src[SrcPos],&ps)==(size_t)-1)
|
||||
{
|
||||
Dest[DestPos]='_';
|
||||
Success=false;
|
||||
}
|
||||
SrcPos++;
|
||||
memset(&ps,0,sizeof(ps));
|
||||
int Length=mbrlen(Dest+DestPos,MB_CUR_MAX,&ps);
|
||||
DestPos+=Max(Length,1);
|
||||
}
|
||||
}
|
||||
Dest[Min(DestPos,DestSize-1)]=0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_UNIX) && defined(MBFUNCTIONS)
|
||||
// Convert and map inconvertible Unicode characters.
|
||||
// Convert and map inconvertible Unicode characters.
|
||||
// We use it for extended ASCII names in Unix.
|
||||
void CharToWideMap(const char *Src,wchar *Dest,size_t DestSize,bool &Success)
|
||||
{
|
||||
@@ -170,13 +192,13 @@ void CharToWideMap(const char *Src,wchar *Dest,size_t DestSize,bool &Success)
|
||||
{
|
||||
if (Src[SrcPos]==0)
|
||||
{
|
||||
Dest[DestPos]=0;
|
||||
Success=true;
|
||||
break;
|
||||
}
|
||||
mbstate_t ps;
|
||||
memset(&ps,0,sizeof(ps));
|
||||
if (mbrtowc(Dest+DestPos,Src+SrcPos,MB_CUR_MAX,&ps)==-1)
|
||||
size_t res=mbrtowc(Dest+DestPos,Src+SrcPos,MB_CUR_MAX,&ps);
|
||||
if (res==(size_t)-1 || res==(size_t)-2)
|
||||
{
|
||||
// For security reasons we do not want to map low ASCII characters,
|
||||
// so we do not have additional .. and path separator codes.
|
||||
@@ -202,6 +224,7 @@ void CharToWideMap(const char *Src,wchar *Dest,size_t DestSize,bool &Success)
|
||||
DestPos++;
|
||||
}
|
||||
}
|
||||
Dest[Min(DestPos,DestSize-1)]=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -281,7 +304,7 @@ size_t WideToUtfSize(const wchar *Src)
|
||||
if (*Src<0x800)
|
||||
Size+=2;
|
||||
else
|
||||
if (*Src<0x10000)
|
||||
if ((uint)*Src<0x10000) //(uint) to avoid Clang/win "always true" warning for 16-bit wchar_t.
|
||||
{
|
||||
if (Src[0]>=0xd800 && Src[0]<=0xdbff && Src[1]>=0xdc00 && Src[1]<=0xdfff)
|
||||
{
|
||||
@@ -292,13 +315,12 @@ size_t WideToUtfSize(const wchar *Src)
|
||||
Size+=3;
|
||||
}
|
||||
else
|
||||
if (*Src<0x200000)
|
||||
if ((uint)*Src<0x200000) //(uint) to avoid Clang/win "always true" warning for 16-bit wchar_t.
|
||||
Size+=4;
|
||||
return Size+1; // Include terminating zero.
|
||||
}
|
||||
|
||||
|
||||
// Dest can be NULL if we only need to check validity of Src.
|
||||
bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
{
|
||||
bool Success=true;
|
||||
@@ -347,40 +369,56 @@ bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
Success=false;
|
||||
break;
|
||||
}
|
||||
if (Dest!=NULL && --dsize<0)
|
||||
if (--dsize<0)
|
||||
break;
|
||||
if (d>0xffff)
|
||||
{
|
||||
if (Dest!=NULL && --dsize<0)
|
||||
if (--dsize<0)
|
||||
break;
|
||||
if (d>0x10ffff) // UTF-8 must end at 0x10ffff according to RFC 3629.
|
||||
{
|
||||
Success=false;
|
||||
continue;
|
||||
}
|
||||
if (Dest!=NULL)
|
||||
if (sizeof(*Dest)==2) // Use the surrogate pair.
|
||||
{
|
||||
*(Dest++)=((d-0x10000)>>10)+0xd800;
|
||||
*(Dest++)=(d&0x3ff)+0xdc00;
|
||||
}
|
||||
else
|
||||
*(Dest++)=d;
|
||||
if (sizeof(*Dest)==2) // Use the surrogate pair.
|
||||
{
|
||||
*(Dest++)=((d-0x10000)>>10)+0xd800;
|
||||
*(Dest++)=(d&0x3ff)+0xdc00;
|
||||
}
|
||||
else
|
||||
*(Dest++)=d;
|
||||
}
|
||||
else
|
||||
if (Dest!=NULL)
|
||||
*(Dest++)=d;
|
||||
*(Dest++)=d;
|
||||
}
|
||||
if (Dest!=NULL)
|
||||
*Dest=0;
|
||||
*Dest=0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
// Source data can be both with and without UTF-8 BOM.
|
||||
bool IsTextUtf8(const char *Src)
|
||||
// For zero terminated strings.
|
||||
bool IsTextUtf8(const byte *Src)
|
||||
{
|
||||
return UtfToWide(Src,NULL,0);
|
||||
return IsTextUtf8(Src,strlen((const char *)Src));
|
||||
}
|
||||
|
||||
|
||||
// Source data can be both with and without UTF-8 BOM.
|
||||
bool IsTextUtf8(const byte *Src,size_t SrcSize)
|
||||
{
|
||||
while (SrcSize-- > 0)
|
||||
{
|
||||
byte C=*(Src++);
|
||||
int HighOne=0; // Number of leftmost '1' bits.
|
||||
for (byte Mask=0x80;Mask!=0 && (C & Mask)!=0;Mask>>=1)
|
||||
HighOne++;
|
||||
if (HighOne==1 || HighOne>6)
|
||||
return false;
|
||||
while (--HighOne > 0)
|
||||
if (SrcSize-- <= 0 || (*(Src++) & 0xc0)!=0x80)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -451,6 +489,8 @@ const wchar_t* wcscasestr(const wchar_t *str, const wchar_t *search)
|
||||
wchar* wcslower(wchar *s)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// _wcslwr requires setlocale and we do not want to depend on setlocale
|
||||
// in Windows. Also CharLower involves less overhead.
|
||||
CharLower(s);
|
||||
#else
|
||||
for (wchar *c=s;*c!=0;c++)
|
||||
@@ -465,6 +505,8 @@ wchar* wcslower(wchar *s)
|
||||
wchar* wcsupper(wchar *s)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// _wcsupr requires setlocale and we do not want to depend on setlocale
|
||||
// in Windows. Also CharUpper involves less overhead.
|
||||
CharUpper(s);
|
||||
#else
|
||||
for (wchar *c=s;*c!=0;c++)
|
||||
@@ -482,8 +524,9 @@ int toupperw(int ch)
|
||||
#if defined(_WIN_ALL)
|
||||
// CharUpper is more reliable than towupper in Windows, which seems to be
|
||||
// C locale dependent even in Unicode version. For example, towupper failed
|
||||
// to convert lowercase Russian characters.
|
||||
return (int)(INT_PTR)CharUpper((wchar *)(INT_PTR)ch);
|
||||
// to convert lowercase Russian characters. Use 0xffff mask to prevent crash
|
||||
// if value larger than 0xffff is passed to this function.
|
||||
return (int)(INT_PTR)CharUpper((wchar *)(INT_PTR)(ch&0xffff));
|
||||
#else
|
||||
return towupper(ch);
|
||||
#endif
|
||||
@@ -494,8 +537,9 @@ int tolowerw(int ch)
|
||||
{
|
||||
#if defined(_WIN_ALL)
|
||||
// CharLower is more reliable than towlower in Windows.
|
||||
// See comment for towupper above.
|
||||
return (int)(INT_PTR)CharLower((wchar *)(INT_PTR)ch);
|
||||
// See comment for towupper above. Use 0xffff mask to prevent crash
|
||||
// if value larger than 0xffff is passed to this function.
|
||||
return (int)(INT_PTR)CharLower((wchar *)(INT_PTR)(ch&0xffff));
|
||||
#else
|
||||
return towlower(ch);
|
||||
#endif
|
||||
@@ -510,19 +554,23 @@ int atoiw(const wchar *s)
|
||||
|
||||
int64 atoilw(const wchar *s)
|
||||
{
|
||||
int sign=1;
|
||||
if (*s=='-')
|
||||
bool sign=false;
|
||||
if (*s=='-') // We do use signed integers here, for example, in GUI SFX.
|
||||
{
|
||||
s++;
|
||||
sign=-1;
|
||||
sign=true;
|
||||
}
|
||||
int64 n=0;
|
||||
// Use unsigned type here, since long string can overflow the variable
|
||||
// and signed integer overflow is undefined behavior in C++.
|
||||
uint64 n=0;
|
||||
while (*s>='0' && *s<='9')
|
||||
{
|
||||
n=n*10+(*s-'0');
|
||||
s++;
|
||||
}
|
||||
return sign*n;
|
||||
// Check int64(n)>=0 to avoid the signed overflow with undefined behavior
|
||||
// when negating 0x8000000000000000.
|
||||
return sign && int64(n)>=0 ? -int64(n) : int64(n);
|
||||
}
|
||||
|
||||
|
||||
@@ -606,3 +654,5 @@ char* SupportDBCS::strrchrd(const char *s, int c)
|
||||
return((char *)found);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize);
|
||||
void WideToUtf(const wchar *Src,char *Dest,size_t DestSize);
|
||||
size_t WideToUtfSize(const wchar *Src);
|
||||
bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize);
|
||||
bool IsTextUtf8(const char *Src);
|
||||
bool IsTextUtf8(const byte *Src);
|
||||
bool IsTextUtf8(const byte *Src,size_t SrcSize);
|
||||
|
||||
int wcsicomp(const wchar *s1,const wchar *s2);
|
||||
int wcsnicomp(const wchar *s1,const wchar *s2,size_t n);
|
||||
@@ -62,4 +63,5 @@ inline void InitDBCS() {gdbcs.Init();}
|
||||
inline void copychrd(char *dest,const char *src) {*dest=*src;}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@ Unpack::Unpack(ComprDataIO *DataIO)
|
||||
UnpSomeRead=false;
|
||||
#ifdef RAR_SMP
|
||||
MaxUserThreads=1;
|
||||
UnpThreadPool=CreateThreadPool();
|
||||
UnpThreadPool=NULL;
|
||||
ReadBufMT=NULL;
|
||||
UnpThreadData=NULL;
|
||||
#endif
|
||||
@@ -52,13 +52,24 @@ Unpack::~Unpack()
|
||||
if (Window!=NULL)
|
||||
free(Window);
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(UnpThreadPool);
|
||||
delete UnpThreadPool;
|
||||
delete[] ReadBufMT;
|
||||
delete[] UnpThreadData;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef RAR_SMP
|
||||
void Unpack::SetThreads(uint Threads)
|
||||
{
|
||||
// More than 8 threads are unlikely to provide noticeable gain
|
||||
// for unpacking, but would use the additional memory.
|
||||
MaxUserThreads=Min(Threads,8);
|
||||
UnpThreadPool=new ThreadPool(MaxUserThreads);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Unpack::Init(size_t WinSize,bool Solid)
|
||||
{
|
||||
// If 32-bit RAR unpacks an archive with 4 GB dictionary, the window size
|
||||
@@ -135,7 +146,7 @@ void Unpack::Init(size_t WinSize,bool Solid)
|
||||
}
|
||||
|
||||
|
||||
void Unpack::DoUnpack(int Method,bool Solid)
|
||||
void Unpack::DoUnpack(uint Method,bool Solid)
|
||||
{
|
||||
// Methods <50 will crash in Fragmented mode when accessing NULL Window.
|
||||
// They cannot be called in such mode now, but we check it below anyway
|
||||
@@ -206,6 +217,7 @@ void Unpack::UnpInitData(bool Solid)
|
||||
UnpInitData20(Solid);
|
||||
#endif
|
||||
UnpInitData30(Solid);
|
||||
UnpInitData50(Solid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define MAX_FILTER_BLOCK_SIZE 0x400000
|
||||
|
||||
// Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_WRITE,
|
||||
// so we keep number of buffered filter in unpacker reasonable.
|
||||
// so we keep a number of buffered filters in unpacker reasonable.
|
||||
#define UNPACK_MAX_WRITE 0x400000
|
||||
|
||||
// Decode compressed bit fields to alphabet numbers.
|
||||
@@ -211,6 +211,7 @@ class Unpack:PackDef
|
||||
void UnpWriteArea(size_t StartPtr,size_t EndPtr);
|
||||
void UnpWriteData(byte *Data,size_t Size);
|
||||
_forceinline uint SlotToLength(BitInput &Inp,uint Slot);
|
||||
void UnpInitData50(bool Solid);
|
||||
bool ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header);
|
||||
bool ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables);
|
||||
void MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size);
|
||||
@@ -307,7 +308,9 @@ class Unpack:PackDef
|
||||
DecodeTable MD[4]; // Decode multimedia data, up to 4 channels.
|
||||
|
||||
unsigned char UnpOldTable20[MC20*4];
|
||||
int UnpAudioBlock,UnpChannels,UnpCurChannel,UnpChannelDelta;
|
||||
bool UnpAudioBlock;
|
||||
uint UnpChannels,UnpCurChannel;
|
||||
int UnpChannelDelta;
|
||||
void CopyString20(uint Length,uint Distance);
|
||||
bool ReadTables20();
|
||||
void UnpWriteBuf20();
|
||||
@@ -326,7 +329,7 @@ class Unpack:PackDef
|
||||
bool ReadEndOfBlock();
|
||||
bool ReadVMCode();
|
||||
bool ReadVMCodePPM();
|
||||
bool AddVMCode(uint FirstByte,byte *Code,int CodeSize);
|
||||
bool AddVMCode(uint FirstByte,byte *Code,uint CodeSize);
|
||||
int SafePPMDecodeChar();
|
||||
bool ReadTables30();
|
||||
bool UnpReadBuf30();
|
||||
@@ -341,7 +344,12 @@ class Unpack:PackDef
|
||||
byte UnpOldTable[HUFF_TABLE_SIZE30];
|
||||
int UnpBlockType;
|
||||
|
||||
bool TablesRead;
|
||||
// If we already read decoding tables for Unpack v2,v3,v5.
|
||||
// We should not use a single variable for all algorithm versions,
|
||||
// because we can have a corrupt archive with one algorithm file
|
||||
// followed by another algorithm file with "solid" flag and we do not
|
||||
// want to reuse tables from one algorithm in another.
|
||||
bool TablesRead2,TablesRead3,TablesRead5;
|
||||
|
||||
// Virtual machine to execute filters code.
|
||||
RarVM VM;
|
||||
@@ -368,16 +376,13 @@ class Unpack:PackDef
|
||||
Unpack(ComprDataIO *DataIO);
|
||||
~Unpack();
|
||||
void Init(size_t WinSize,bool Solid);
|
||||
void DoUnpack(int Method,bool Solid);
|
||||
void DoUnpack(uint Method,bool Solid);
|
||||
bool IsFileExtracted() {return(FileExtracted);}
|
||||
void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
|
||||
void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;}
|
||||
|
||||
#ifdef RAR_SMP
|
||||
// More than 8 threads are unlikely to provide a noticeable gain
|
||||
// for unpacking, but would use the additional memory.
|
||||
void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);}
|
||||
|
||||
void SetThreads(uint Threads);
|
||||
void UnpackDecode(UnpackThreadData &D);
|
||||
#endif
|
||||
|
||||
@@ -387,8 +392,12 @@ class Unpack:PackDef
|
||||
uint GetChar()
|
||||
{
|
||||
if (Inp.InAddr>BitInput::MAX_SIZE-30)
|
||||
{
|
||||
UnpReadBuf();
|
||||
return(Inp.InBuf[Inp.InAddr++]);
|
||||
if (Inp.InAddr>=BitInput::MAX_SIZE) // If nothing was read.
|
||||
return 0;
|
||||
}
|
||||
return Inp.InBuf[Inp.InAddr++];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ void Unpack::LongLZ()
|
||||
break;
|
||||
}
|
||||
|
||||
ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
|
||||
ChSetB[DistancePlace & 0xff]=ChSetB[NewDistancePlace];
|
||||
ChSetB[NewDistancePlace]=Distance;
|
||||
|
||||
Distance=((Distance & 0xff00) | (Inp.fgetbits() >> 8)) >> 1;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
void Unpack::CopyString20(uint Length,uint Distance)
|
||||
{
|
||||
LastDist=OldDist[OldDistPtr++ & 3]=Distance;
|
||||
LastDist=OldDist[OldDistPtr++]=Distance;
|
||||
OldDistPtr = OldDistPtr & 3; // Needed if RAR 1.5 file is called after RAR 2.0.
|
||||
LastLength=Length;
|
||||
DestUnpSize-=Length;
|
||||
CopyString(Length,Distance);
|
||||
@@ -13,11 +14,11 @@ void Unpack::Unpack20(bool Solid)
|
||||
{
|
||||
static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
|
||||
static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
|
||||
static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
|
||||
static uint DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
|
||||
static unsigned char DBits[]= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
|
||||
static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
|
||||
static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
|
||||
unsigned int Bits;
|
||||
uint Bits;
|
||||
|
||||
if (Suspended)
|
||||
UnpPtr=WrPtr;
|
||||
@@ -26,9 +27,8 @@ void Unpack::Unpack20(bool Solid)
|
||||
UnpInitData(Solid);
|
||||
if (!UnpReadBuf())
|
||||
return;
|
||||
if (!Solid)
|
||||
if (!ReadTables20())
|
||||
return;
|
||||
if ((!Solid || !TablesRead2) && !ReadTables20())
|
||||
return;
|
||||
--DestUnpSize;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ void Unpack::Unpack20(bool Solid)
|
||||
}
|
||||
if (UnpAudioBlock)
|
||||
{
|
||||
int AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]);
|
||||
uint AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]);
|
||||
|
||||
if (AudioNumber==256)
|
||||
{
|
||||
@@ -55,14 +55,14 @@ void Unpack::Unpack20(bool Solid)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
Window[UnpPtr++]=DecodeAudio(AudioNumber);
|
||||
Window[UnpPtr++]=DecodeAudio((int)AudioNumber);
|
||||
if (++UnpCurChannel==UnpChannels)
|
||||
UnpCurChannel=0;
|
||||
--DestUnpSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
int Number=DecodeNumber(Inp,&BlockTables.LD);
|
||||
uint Number=DecodeNumber(Inp,&BlockTables.LD);
|
||||
if (Number<256)
|
||||
{
|
||||
Window[UnpPtr++]=(byte)Number;
|
||||
@@ -71,15 +71,15 @@ void Unpack::Unpack20(bool Solid)
|
||||
}
|
||||
if (Number>269)
|
||||
{
|
||||
int Length=LDecode[Number-=270]+3;
|
||||
uint Length=LDecode[Number-=270]+3;
|
||||
if ((Bits=LBits[Number])>0)
|
||||
{
|
||||
Length+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
|
||||
int DistNumber=DecodeNumber(Inp,&BlockTables.DD);
|
||||
unsigned int Distance=DDecode[DistNumber]+1;
|
||||
uint DistNumber=DecodeNumber(Inp,&BlockTables.DD);
|
||||
uint Distance=DDecode[DistNumber]+1;
|
||||
if ((Bits=DBits[DistNumber])>0)
|
||||
{
|
||||
Distance+=Inp.getbits()>>(16-Bits);
|
||||
@@ -109,9 +109,9 @@ void Unpack::Unpack20(bool Solid)
|
||||
}
|
||||
if (Number<261)
|
||||
{
|
||||
unsigned int Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
|
||||
int LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
|
||||
int Length=LDecode[LengthNumber]+2;
|
||||
uint Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
|
||||
uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
|
||||
uint Length=LDecode[LengthNumber]+2;
|
||||
if ((Bits=LBits[LengthNumber])>0)
|
||||
{
|
||||
Length+=Inp.getbits()>>(16-Bits);
|
||||
@@ -132,7 +132,7 @@ void Unpack::Unpack20(bool Solid)
|
||||
}
|
||||
if (Number<270)
|
||||
{
|
||||
unsigned int Distance=SDDecode[Number-=261]+1;
|
||||
uint Distance=SDDecode[Number-=261]+1;
|
||||
if ((Bits=SDBits[Number])>0)
|
||||
{
|
||||
Distance+=Inp.getbits()>>(16-Bits);
|
||||
@@ -167,17 +167,17 @@ bool Unpack::ReadTables20()
|
||||
{
|
||||
byte BitLength[BC20];
|
||||
byte Table[MC20*4];
|
||||
int TableSize,N,I;
|
||||
if (Inp.InAddr>ReadTop-25)
|
||||
if (!UnpReadBuf())
|
||||
return(false);
|
||||
return false;
|
||||
uint BitField=Inp.getbits();
|
||||
UnpAudioBlock=(BitField & 0x8000);
|
||||
UnpAudioBlock=(BitField & 0x8000)!=0;
|
||||
|
||||
if (!(BitField & 0x4000))
|
||||
memset(UnpOldTable20,0,sizeof(UnpOldTable20));
|
||||
Inp.addbits(2);
|
||||
|
||||
uint TableSize;
|
||||
if (UnpAudioBlock)
|
||||
{
|
||||
UnpChannels=((BitField>>12) & 3)+1;
|
||||
@@ -189,19 +189,18 @@ bool Unpack::ReadTables20()
|
||||
else
|
||||
TableSize=NC20+DC20+RC20;
|
||||
|
||||
for (I=0;I<BC20;I++)
|
||||
for (uint I=0;I<BC20;I++)
|
||||
{
|
||||
BitLength[I]=(byte)(Inp.getbits() >> 12);
|
||||
Inp.addbits(4);
|
||||
}
|
||||
MakeDecodeTables(BitLength,&BlockTables.BD,BC20);
|
||||
I=0;
|
||||
while (I<TableSize)
|
||||
for (uint I=0;I<TableSize;)
|
||||
{
|
||||
if (Inp.InAddr>ReadTop-5)
|
||||
if (!UnpReadBuf())
|
||||
return false;
|
||||
int Number=DecodeNumber(Inp,&BlockTables.BD);
|
||||
uint Number=DecodeNumber(Inp,&BlockTables.BD);
|
||||
if (Number<16)
|
||||
{
|
||||
Table[I]=(Number+UnpOldTable20[I]) & 0xf;
|
||||
@@ -210,9 +209,11 @@ bool Unpack::ReadTables20()
|
||||
else
|
||||
if (Number==16)
|
||||
{
|
||||
N=(Inp.getbits() >> 14)+3;
|
||||
uint N=(Inp.getbits() >> 14)+3;
|
||||
Inp.addbits(2);
|
||||
if (I>0)
|
||||
if (I==0)
|
||||
return false; // We cannot have "repeat previous" code at the first position.
|
||||
else
|
||||
while (N-- > 0 && I<TableSize)
|
||||
{
|
||||
Table[I]=Table[I-1];
|
||||
@@ -221,6 +222,7 @@ bool Unpack::ReadTables20()
|
||||
}
|
||||
else
|
||||
{
|
||||
uint N;
|
||||
if (Number==17)
|
||||
{
|
||||
N=(Inp.getbits() >> 13)+3;
|
||||
@@ -235,10 +237,11 @@ bool Unpack::ReadTables20()
|
||||
Table[I++]=0;
|
||||
}
|
||||
}
|
||||
TablesRead2=true;
|
||||
if (Inp.InAddr>ReadTop)
|
||||
return(true);
|
||||
return true;
|
||||
if (UnpAudioBlock)
|
||||
for (I=0;I<UnpChannels;I++)
|
||||
for (uint I=0;I<UnpChannels;I++)
|
||||
MakeDecodeTables(&Table[I*MC20],&MD[I],MC20);
|
||||
else
|
||||
{
|
||||
@@ -246,8 +249,8 @@ bool Unpack::ReadTables20()
|
||||
MakeDecodeTables(&Table[NC20],&BlockTables.DD,DC20);
|
||||
MakeDecodeTables(&Table[NC20+DC20],&BlockTables.RD,RC20);
|
||||
}
|
||||
memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20));
|
||||
return(true);
|
||||
memcpy(UnpOldTable20,Table,TableSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +272,10 @@ void Unpack::UnpInitData20(int Solid)
|
||||
{
|
||||
if (!Solid)
|
||||
{
|
||||
UnpAudioBlock=UnpChannelDelta=UnpCurChannel=0;
|
||||
TablesRead2=false;
|
||||
UnpAudioBlock=false;
|
||||
UnpChannelDelta=0;
|
||||
UnpCurChannel=0;
|
||||
UnpChannels=1;
|
||||
|
||||
memset(AudV,0,sizeof(AudV));
|
||||
@@ -290,9 +296,12 @@ byte Unpack::DecodeAudio(int Delta)
|
||||
int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta;
|
||||
PCh=(PCh>>3) & 0xFF;
|
||||
|
||||
unsigned int Ch=PCh-Delta;
|
||||
uint Ch=PCh-Delta;
|
||||
|
||||
int D=((signed char)Delta)<<3;
|
||||
int D=(signed char)Delta;
|
||||
// Left shift of negative value is undefined behavior in C++,
|
||||
// so we cast it to unsigned to follow the standard.
|
||||
D=(uint)D<<3;
|
||||
|
||||
V->Dif[0]+=abs(D);
|
||||
V->Dif[1]+=abs(D-V->D1);
|
||||
@@ -311,9 +320,9 @@ byte Unpack::DecodeAudio(int Delta)
|
||||
|
||||
if ((V->ByteCount & 0x1F)==0)
|
||||
{
|
||||
unsigned int MinDif=V->Dif[0],NumMinDif=0;
|
||||
uint MinDif=V->Dif[0],NumMinDif=0;
|
||||
V->Dif[0]=0;
|
||||
for (int I=1;I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
|
||||
for (uint I=1;I<ASIZE(V->Dif);I++)
|
||||
{
|
||||
if (V->Dif[I]<MinDif)
|
||||
{
|
||||
@@ -366,5 +375,5 @@ byte Unpack::DecodeAudio(int Delta)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return((byte)Ch);
|
||||
return (byte)Ch;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ void Unpack::Unpack29(bool Solid)
|
||||
UnpInitData(Solid);
|
||||
if (!UnpReadBuf30())
|
||||
return;
|
||||
if ((!Solid || !TablesRead) && !ReadTables30())
|
||||
if ((!Solid || !TablesRead3) && !ReadTables30())
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ void Unpack::Unpack29(bool Solid)
|
||||
continue;
|
||||
}
|
||||
|
||||
int Number=DecodeNumber(Inp,&BlockTables.LD);
|
||||
uint Number=DecodeNumber(Inp,&BlockTables.LD);
|
||||
if (Number<256)
|
||||
{
|
||||
Window[UnpPtr++]=(byte)Number;
|
||||
@@ -141,15 +141,15 @@ void Unpack::Unpack29(bool Solid)
|
||||
}
|
||||
if (Number>=271)
|
||||
{
|
||||
int Length=LDecode[Number-=271]+3;
|
||||
uint Length=LDecode[Number-=271]+3;
|
||||
if ((Bits=LBits[Number])>0)
|
||||
{
|
||||
Length+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
|
||||
int DistNumber=DecodeNumber(Inp,&BlockTables.DD);
|
||||
unsigned int Distance=DDecode[DistNumber]+1;
|
||||
uint DistNumber=DecodeNumber(Inp,&BlockTables.DD);
|
||||
uint Distance=DDecode[DistNumber]+1;
|
||||
if ((Bits=DBits[DistNumber])>0)
|
||||
{
|
||||
if (DistNumber>9)
|
||||
@@ -166,7 +166,7 @@ void Unpack::Unpack29(bool Solid)
|
||||
}
|
||||
else
|
||||
{
|
||||
int LowDist=DecodeNumber(Inp,&BlockTables.LDD);
|
||||
uint LowDist=DecodeNumber(Inp,&BlockTables.LDD);
|
||||
if (LowDist==16)
|
||||
{
|
||||
LowDistRepCount=LOW_DIST_REP_COUNT-1;
|
||||
@@ -189,7 +189,7 @@ void Unpack::Unpack29(bool Solid)
|
||||
if (Distance>=0x2000)
|
||||
{
|
||||
Length++;
|
||||
if (Distance>=0x40000L)
|
||||
if (Distance>=0x40000)
|
||||
Length++;
|
||||
}
|
||||
|
||||
@@ -218,13 +218,13 @@ void Unpack::Unpack29(bool Solid)
|
||||
}
|
||||
if (Number<263)
|
||||
{
|
||||
int DistNum=Number-259;
|
||||
unsigned int Distance=OldDist[DistNum];
|
||||
for (int I=DistNum;I>0;I--)
|
||||
uint DistNum=Number-259;
|
||||
uint Distance=OldDist[DistNum];
|
||||
for (uint I=DistNum;I>0;I--)
|
||||
OldDist[I]=OldDist[I-1];
|
||||
OldDist[0]=Distance;
|
||||
|
||||
int LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
|
||||
uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
|
||||
int Length=LDecode[LengthNumber]+2;
|
||||
if ((Bits=LBits[LengthNumber])>0)
|
||||
{
|
||||
@@ -237,7 +237,7 @@ void Unpack::Unpack29(bool Solid)
|
||||
}
|
||||
if (Number<272)
|
||||
{
|
||||
unsigned int Distance=SDDecode[Number-=263]+1;
|
||||
uint Distance=SDDecode[Number-=263]+1;
|
||||
if ((Bits=SDBits[Number])>0)
|
||||
{
|
||||
Distance+=Inp.getbits()>>(16-Bits);
|
||||
@@ -274,11 +274,11 @@ bool Unpack::ReadEndOfBlock()
|
||||
NewTable=(BitField & 0x4000)!=0;
|
||||
Inp.addbits(2);
|
||||
}
|
||||
TablesRead=!NewTable;
|
||||
TablesRead3=!NewTable;
|
||||
|
||||
// Quit immediately if "new file" flag is set. If "new table" flag
|
||||
// is present, we'll read the table in beginning of next file
|
||||
// based on 'TablesRead' 'false' value.
|
||||
// based on 'TablesRead3' 'false' value.
|
||||
if (NewFile)
|
||||
return false;
|
||||
return ReadTables30(); // Quit only if we failed to read tables.
|
||||
@@ -290,9 +290,9 @@ bool Unpack::ReadVMCode()
|
||||
// Entire VM code is guaranteed to fully present in block defined
|
||||
// by current Huffman table. Compressor checks that VM code does not cross
|
||||
// Huffman block boundaries.
|
||||
unsigned int FirstByte=Inp.getbits()>>8;
|
||||
uint FirstByte=Inp.getbits()>>8;
|
||||
Inp.addbits(8);
|
||||
int Length=(FirstByte & 7)+1;
|
||||
uint Length=(FirstByte & 7)+1;
|
||||
if (Length==7)
|
||||
{
|
||||
Length=(Inp.getbits()>>8)+7;
|
||||
@@ -304,8 +304,10 @@ bool Unpack::ReadVMCode()
|
||||
Length=Inp.getbits();
|
||||
Inp.addbits(16);
|
||||
}
|
||||
if (Length==0)
|
||||
return false;
|
||||
Array<byte> VMCode(Length);
|
||||
for (int I=0;I<Length;I++)
|
||||
for (uint I=0;I<Length;I++)
|
||||
{
|
||||
// Try to read the new buffer if only one byte is left.
|
||||
// But if we read all bytes except the last, one byte is enough.
|
||||
@@ -320,15 +322,15 @@ bool Unpack::ReadVMCode()
|
||||
|
||||
bool Unpack::ReadVMCodePPM()
|
||||
{
|
||||
unsigned int FirstByte=SafePPMDecodeChar();
|
||||
uint FirstByte=SafePPMDecodeChar();
|
||||
if ((int)FirstByte==-1)
|
||||
return false;
|
||||
int Length=(FirstByte & 7)+1;
|
||||
uint Length=(FirstByte & 7)+1;
|
||||
if (Length==7)
|
||||
{
|
||||
int B1=SafePPMDecodeChar();
|
||||
if (B1==-1)
|
||||
return(false);
|
||||
return false;
|
||||
Length=B1+7;
|
||||
}
|
||||
else
|
||||
@@ -342,19 +344,21 @@ bool Unpack::ReadVMCodePPM()
|
||||
return false;
|
||||
Length=B1*256+B2;
|
||||
}
|
||||
if (Length==0)
|
||||
return false;
|
||||
Array<byte> VMCode(Length);
|
||||
for (int I=0;I<Length;I++)
|
||||
for (uint I=0;I<Length;I++)
|
||||
{
|
||||
int Ch=SafePPMDecodeChar();
|
||||
if (Ch==-1)
|
||||
return(false);
|
||||
return false;
|
||||
VMCode[I]=Ch;
|
||||
}
|
||||
return AddVMCode(FirstByte,&VMCode[0],Length);
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::AddVMCode(uint FirstByte,byte *Code,int CodeSize)
|
||||
bool Unpack::AddVMCode(uint FirstByte,byte *Code,uint CodeSize)
|
||||
{
|
||||
VMCodeInp.InitBitInput();
|
||||
memcpy(VMCodeInp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
|
||||
@@ -405,7 +409,7 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,int CodeSize)
|
||||
StackFilter->ParentFilter=FiltPos;
|
||||
}
|
||||
|
||||
int EmptyCount=0;
|
||||
uint EmptyCount=0;
|
||||
for (uint I=0;I<PrgStack.Size();I++)
|
||||
{
|
||||
PrgStack[I-EmptyCount]=PrgStack[I];
|
||||
@@ -424,7 +428,7 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,int CodeSize)
|
||||
PrgStack.Add(1);
|
||||
EmptyCount=1;
|
||||
}
|
||||
int StackPos=(int)(PrgStack.Size()-EmptyCount);
|
||||
size_t StackPos=PrgStack.Size()-EmptyCount;
|
||||
PrgStack[StackPos]=StackFilter;
|
||||
|
||||
uint BlockStart=RarVM::ReadData(VMCodeInp);
|
||||
@@ -458,7 +462,7 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,int CodeSize)
|
||||
{
|
||||
uint InitMask=VMCodeInp.fgetbits()>>9;
|
||||
VMCodeInp.faddbits(7);
|
||||
for (int I=0;I<7;I++)
|
||||
for (uint I=0;I<7;I++)
|
||||
if (InitMask & (1<<I))
|
||||
StackFilter->Prg.InitR[I]=RarVM::ReadData(VMCodeInp);
|
||||
}
|
||||
@@ -466,7 +470,7 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,int CodeSize)
|
||||
if (NewFilter)
|
||||
{
|
||||
uint VMCodeSize=RarVM::ReadData(VMCodeInp);
|
||||
if (VMCodeSize>=0x10000 || VMCodeSize==0)
|
||||
if (VMCodeSize>=0x10000 || VMCodeSize==0 || VMCodeInp.InAddr+VMCodeSize>CodeSize)
|
||||
return false;
|
||||
Array<byte> VMCode(VMCodeSize);
|
||||
for (uint I=0;I<VMCodeSize;I++)
|
||||
@@ -644,13 +648,13 @@ bool Unpack::ReadTables30()
|
||||
memset(UnpOldTable,0,sizeof(UnpOldTable));
|
||||
Inp.faddbits(2);
|
||||
|
||||
for (int I=0;I<BC;I++)
|
||||
for (uint I=0;I<BC;I++)
|
||||
{
|
||||
int Length=(byte)(Inp.fgetbits() >> 12);
|
||||
uint Length=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (Length==15)
|
||||
{
|
||||
int ZeroCount=(byte)(Inp.fgetbits() >> 12);
|
||||
uint ZeroCount=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (ZeroCount==0)
|
||||
BitLength[I]=15;
|
||||
@@ -667,13 +671,13 @@ bool Unpack::ReadTables30()
|
||||
}
|
||||
MakeDecodeTables(BitLength,&BlockTables.BD,BC30);
|
||||
|
||||
const int TableSize=HUFF_TABLE_SIZE30;
|
||||
for (int I=0;I<TableSize;)
|
||||
const uint TableSize=HUFF_TABLE_SIZE30;
|
||||
for (uint I=0;I<TableSize;)
|
||||
{
|
||||
if (Inp.InAddr>ReadTop-5)
|
||||
if (!UnpReadBuf30())
|
||||
return(false);
|
||||
int Number=DecodeNumber(Inp,&BlockTables.BD);
|
||||
uint Number=DecodeNumber(Inp,&BlockTables.BD);
|
||||
if (Number<16)
|
||||
{
|
||||
Table[I]=(Number+UnpOldTable[I]) & 0xf;
|
||||
@@ -682,7 +686,7 @@ bool Unpack::ReadTables30()
|
||||
else
|
||||
if (Number<18)
|
||||
{
|
||||
int N;
|
||||
uint N;
|
||||
if (Number==16)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
@@ -693,7 +697,9 @@ bool Unpack::ReadTables30()
|
||||
N=(Inp.fgetbits() >> 9)+11;
|
||||
Inp.faddbits(7);
|
||||
}
|
||||
if (I>0)
|
||||
if (I==0)
|
||||
return false; // We cannot have "repeat previous" code at the first position.
|
||||
else
|
||||
while (N-- > 0 && I<TableSize)
|
||||
{
|
||||
Table[I]=Table[I-1];
|
||||
@@ -702,7 +708,7 @@ bool Unpack::ReadTables30()
|
||||
}
|
||||
else
|
||||
{
|
||||
int N;
|
||||
uint N;
|
||||
if (Number==18)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
@@ -717,7 +723,7 @@ bool Unpack::ReadTables30()
|
||||
Table[I++]=0;
|
||||
}
|
||||
}
|
||||
TablesRead=true;
|
||||
TablesRead3=true;
|
||||
if (Inp.InAddr>ReadTop)
|
||||
return false;
|
||||
MakeDecodeTables(&Table[0],&BlockTables.LD,NC30);
|
||||
@@ -733,7 +739,7 @@ void Unpack::UnpInitData30(bool Solid)
|
||||
{
|
||||
if (!Solid)
|
||||
{
|
||||
TablesRead=false;
|
||||
TablesRead3=false;
|
||||
memset(UnpOldTable,0,sizeof(UnpOldTable));
|
||||
PPMEscChar=2;
|
||||
UnpBlockType=BLOCK_LZ;
|
||||
|
||||
@@ -7,7 +7,12 @@ void Unpack::Unpack5(bool Solid)
|
||||
UnpInitData(Solid);
|
||||
if (!UnpReadBuf())
|
||||
return;
|
||||
if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
|
||||
|
||||
// Check TablesRead5 to be sure that we read tables at least once
|
||||
// regardless of current block header TablePresent flag.
|
||||
// So we can safefly use these tables below.
|
||||
if (!ReadBlockHeader(Inp,BlockHeader) ||
|
||||
!ReadTables(Inp,BlockHeader,BlockTables) || !TablesRead5)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -37,7 +42,7 @@ void Unpack::Unpack5(bool Solid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
@@ -431,6 +436,10 @@ byte* Unpack::ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt)
|
||||
}
|
||||
return SrcData;
|
||||
case FILTER_ARM:
|
||||
// 2019-11-15: we turned off ARM filter by default when compressing,
|
||||
// mostly because it is inefficient for modern 64 bit ARM binaries.
|
||||
// It was turned on by default in 5.0 - 5.80b3 , so we still need it
|
||||
// here for compatibility with some of previously created archives.
|
||||
{
|
||||
uint FileOffset=(uint)WrittenFileSize;
|
||||
// DataSize is unsigned, so we use "CurPos+3" and not "DataSize-3"
|
||||
@@ -516,6 +525,13 @@ void Unpack::UnpWriteData(byte *Data,size_t Size)
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpInitData50(bool Solid)
|
||||
{
|
||||
if (!Solid)
|
||||
TablesRead5=false;
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header)
|
||||
{
|
||||
Header.HeaderSize=0;
|
||||
@@ -524,11 +540,11 @@ bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header)
|
||||
if (!UnpReadBuf())
|
||||
return false;
|
||||
Inp.faddbits((8-Inp.InBit)&7);
|
||||
|
||||
|
||||
byte BlockFlags=Inp.fgetbits()>>8;
|
||||
Inp.faddbits(8);
|
||||
uint ByteCount=((BlockFlags>>3)&3)+1; // Block size byte count.
|
||||
|
||||
|
||||
if (ByteCount==4)
|
||||
return false;
|
||||
|
||||
@@ -570,13 +586,13 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable
|
||||
return false;
|
||||
|
||||
byte BitLength[BC];
|
||||
for (int I=0;I<BC;I++)
|
||||
for (uint I=0;I<BC;I++)
|
||||
{
|
||||
int Length=(byte)(Inp.fgetbits() >> 12);
|
||||
uint Length=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (Length==15)
|
||||
{
|
||||
int ZeroCount=(byte)(Inp.fgetbits() >> 12);
|
||||
uint ZeroCount=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (ZeroCount==0)
|
||||
BitLength[I]=15;
|
||||
@@ -595,13 +611,13 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable
|
||||
MakeDecodeTables(BitLength,&Tables.BD,BC);
|
||||
|
||||
byte Table[HUFF_TABLE_SIZE];
|
||||
const int TableSize=HUFF_TABLE_SIZE;
|
||||
for (int I=0;I<TableSize;)
|
||||
const uint TableSize=HUFF_TABLE_SIZE;
|
||||
for (uint I=0;I<TableSize;)
|
||||
{
|
||||
if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5)
|
||||
if (!UnpReadBuf())
|
||||
return false;
|
||||
int Number=DecodeNumber(Inp,&Tables.BD);
|
||||
uint Number=DecodeNumber(Inp,&Tables.BD);
|
||||
if (Number<16)
|
||||
{
|
||||
Table[I]=Number;
|
||||
@@ -610,7 +626,7 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable
|
||||
else
|
||||
if (Number<18)
|
||||
{
|
||||
int N;
|
||||
uint N;
|
||||
if (Number==16)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
@@ -621,7 +637,16 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable
|
||||
N=(Inp.fgetbits() >> 9)+11;
|
||||
Inp.faddbits(7);
|
||||
}
|
||||
if (I>0)
|
||||
if (I==0)
|
||||
{
|
||||
// We cannot have "repeat previous" code at the first position.
|
||||
// Multiple such codes would shift Inp position without changing I,
|
||||
// which can lead to reading beyond of Inp boundary in mutithreading
|
||||
// mode, where Inp.ExternalBuffer disables bounds check and we just
|
||||
// reserve a lot of buffer space to not need such check normally.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
while (N-- > 0 && I<TableSize)
|
||||
{
|
||||
Table[I]=Table[I-1];
|
||||
@@ -630,7 +655,7 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable
|
||||
}
|
||||
else
|
||||
{
|
||||
int N;
|
||||
uint N;
|
||||
if (Number==18)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
@@ -645,6 +670,7 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable
|
||||
Table[I++]=0;
|
||||
}
|
||||
}
|
||||
TablesRead5=true;
|
||||
if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop)
|
||||
return false;
|
||||
MakeDecodeTables(&Table[0],&Tables.LD,NC);
|
||||
|
||||
@@ -48,7 +48,7 @@ void FragmentedWindow::Init(size_t WinSize)
|
||||
}
|
||||
if (NewMem==NULL)
|
||||
throw std::bad_alloc();
|
||||
|
||||
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access to unused areas of sliding dictionary.
|
||||
memset(NewMem,0,Size);
|
||||
|
||||
@@ -133,11 +133,13 @@ void Unpack::Unpack5MT(bool Solid)
|
||||
if (!CurData->HeaderRead)
|
||||
{
|
||||
CurData->HeaderRead=true;
|
||||
if (!ReadBlockHeader(CurData->Inp,CurData->BlockHeader))
|
||||
if (!ReadBlockHeader(CurData->Inp,CurData->BlockHeader) ||
|
||||
!CurData->BlockHeader.TablePresent && !TablesRead5)
|
||||
{
|
||||
Done=true;
|
||||
break;
|
||||
}
|
||||
TablesRead5=true;
|
||||
}
|
||||
|
||||
// To prevent too high memory use we switch to single threaded mode
|
||||
@@ -163,7 +165,7 @@ void Unpack::Unpack5MT(bool Solid)
|
||||
if (DataLeft<TooSmallToProcess)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//#undef USE_THREADS
|
||||
UnpackThreadDataList UTDArray[MaxPoolThreads];
|
||||
uint UTDArrayPos=0;
|
||||
@@ -178,7 +180,7 @@ void Unpack::Unpack5MT(bool Solid)
|
||||
UnpackThreadDataList *UTD=UTDArray+UTDArrayPos++;
|
||||
UTD->D=UnpThreadData+CurBlock;
|
||||
UTD->BlockCount=Min(MaxBlockPerThread,BlockNumberMT-CurBlock);
|
||||
|
||||
|
||||
#ifdef USE_THREADS
|
||||
if (BlockNumber==1)
|
||||
UnpackDecode(*UTD->D);
|
||||
@@ -198,7 +200,7 @@ void Unpack::Unpack5MT(bool Solid)
|
||||
#endif
|
||||
|
||||
bool IncompleteThread=false;
|
||||
|
||||
|
||||
for (uint Block=0;Block<BlockNumber;Block++)
|
||||
{
|
||||
UnpackThreadData *CurData=UnpThreadData+Block;
|
||||
@@ -249,7 +251,7 @@ void Unpack::Unpack5MT(bool Solid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (IncompleteThread || Done)
|
||||
break; // Current buffer is done, read more data or quit.
|
||||
else
|
||||
@@ -301,7 +303,7 @@ void Unpack::UnpackDecode(UnpackThreadData &D)
|
||||
D.DamagedData=true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
D.DecodedSize=0;
|
||||
int BlockBorder=D.BlockHeader.BlockStart+D.BlockHeader.BlockSize-1;
|
||||
|
||||
@@ -411,7 +413,7 @@ void Unpack::UnpackDecode(UnpackThreadData &D)
|
||||
{
|
||||
UnpackFilter Filter;
|
||||
ReadFilter(D.Inp,Filter);
|
||||
|
||||
|
||||
CurItem->Type=UNPDT_FILTER;
|
||||
CurItem->Length=Filter.Type;
|
||||
CurItem->Distance=Filter.BlockStart;
|
||||
@@ -449,7 +451,7 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D)
|
||||
while (Item<Border)
|
||||
{
|
||||
UnpPtr&=MaxWinMask;
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
@@ -496,7 +498,7 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D)
|
||||
if (Item->Type==UNPDT_FILTER)
|
||||
{
|
||||
UnpackFilter Filter;
|
||||
|
||||
|
||||
Filter.Type=(byte)Item->Length;
|
||||
Filter.BlockStart=Item->Distance;
|
||||
|
||||
@@ -532,7 +534,7 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D)
|
||||
D.DamagedData=true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int BlockBorder=D.BlockHeader.BlockStart+D.BlockHeader.BlockSize-1;
|
||||
|
||||
// Reserve enough space even for filter entry.
|
||||
@@ -557,7 +559,7 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
|
||||
@@ -13,7 +13,7 @@ _forceinline void Unpack::InsertOldDist(uint Distance)
|
||||
_forceinline void Unpack::CopyString(uint Length,uint Distance)
|
||||
{
|
||||
size_t SrcPtr=UnpPtr-Distance;
|
||||
if (SrcPtr<MaxWinSize-MAX_LZ_MATCH && UnpPtr<MaxWinSize-MAX_LZ_MATCH)
|
||||
if (SrcPtr<MaxWinSize-MAX_INC_LZ_MATCH && UnpPtr<MaxWinSize-MAX_INC_LZ_MATCH)
|
||||
{
|
||||
// If we are not close to end of window, we do not need to waste time
|
||||
// to "& MaxWinMask" pointer protection.
|
||||
@@ -46,7 +46,7 @@ _forceinline void Unpack::CopyString(uint Length,uint Distance)
|
||||
{
|
||||
// In theory we still could overlap here.
|
||||
// Supposing Distance == MaxWinSize - 1 we have memcpy(Src, Src + 1, 8).
|
||||
// But for real RAR archives Distance <= MaxWinSize - MAX_LZ_MATCH
|
||||
// But for real RAR archives Distance <= MaxWinSize - MAX_INC_LZ_MATCH
|
||||
// always, so overlap here is impossible.
|
||||
|
||||
// This memcpy expanded inline by MSVC. We could also use uint64
|
||||
@@ -120,7 +120,7 @@ _forceinline uint Unpack::DecodeNumber(BitInput &Inp,DecodeTable *Dec)
|
||||
|
||||
// Convert the position in the code list to position in alphabet
|
||||
// and return it.
|
||||
return(Dec->DecodeNum[Pos]);
|
||||
return Dec->DecodeNum[Pos];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define RARVER_MAJOR 5
|
||||
#define RARVER_MINOR 50
|
||||
#define RARVER_BETA 5
|
||||
#define RARVER_DAY 2
|
||||
#define RARVER_MONTH 7
|
||||
#define RARVER_YEAR 2017
|
||||
#define RARVER_MINOR 91
|
||||
#define RARVER_BETA 0
|
||||
#define RARVER_DAY 25
|
||||
#define RARVER_MONTH 6
|
||||
#define RARVER_YEAR 2020
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user