Initial import of unrar source code

This commit is contained in:
Kovid Goyal 2012-11-24 20:46:13 +05:30
parent 1902c7e8ef
commit 67f689c7fb
128 changed files with 27586 additions and 0 deletions

623
src/unrar/UnRAR.vcproj Normal file
View File

@ -0,0 +1,623 @@
<?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="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="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="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="savepos.cpp"
>
</File>
<File
RelativePath="scantree.cpp"
>
</File>
<File
RelativePath="secpassword.cpp"
>
</File>
<File
RelativePath="sha1.cpp"
>
</File>
<File
RelativePath="smallfn.cpp"
>
</File>
<File
RelativePath="strfn.cpp"
>
</File>
<File
RelativePath="strlist.cpp"
>
</File>
<File
RelativePath="system.cpp"
>
</File>
<File
RelativePath="timefn.cpp"
>
</File>
<File
RelativePath="ulinks.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}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

848
src/unrar/UnRARDll.vcproj Normal file
View File

@ -0,0 +1,848 @@
<?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"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
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"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
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"
RuntimeLibrary="0"
StructMemberAlignment="0"
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"
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"
RuntimeLibrary="0"
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;NOCRYPT"
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="0"
DisableSpecificWarnings="4007;4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
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;NOCRYPT"
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"
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="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="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="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="recvol.cpp"
>
</File>
<File
RelativePath="rijndael.cpp"
>
</File>
<File
RelativePath="rs.cpp"
>
</File>
<File
RelativePath="savepos.cpp"
>
</File>
<File
RelativePath="scantree.cpp"
>
</File>
<File
RelativePath="secpassword.cpp"
>
</File>
<File
RelativePath="sha1.cpp"
>
</File>
<File
RelativePath=".\smallfn.cpp"
>
</File>
<File
RelativePath="strfn.cpp"
>
</File>
<File
RelativePath="strlist.cpp"
>
</File>
<File
RelativePath="system.cpp"
>
</File>
<File
RelativePath="timefn.cpp"
>
</File>
<File
RelativePath="ulinks.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>

81
src/unrar/acknow.txt Normal file
View File

@ -0,0 +1,81 @@
ACKNOWLEDGMENTS
* RAR text compression algorithm is based on Dmitry Shkarin PPMII
and Dmitry Subbotin carryless rangecoder public domain source code.
You may find it in ftp.elf.stuba.sk/pub/pc/pack.
* RAR encryption includes parts of code from Szymon Stefanek
and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Source code of this package also as other cryptographic technology
and computing project related links are available on Brian Gladman's
web site: http://www.gladman.me.uk
* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
Original Intel Slicing-by-8 code is available here:
http://sourceforge.net/projects/slicing-by-8/
Original Intel Slicing-by-8 code is licensed under BSD License
available at http://www.opensource.org/licenses/bsd-license.html
Copyright (c) 2004-2006 Intel Corporation.
All Rights Reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with
the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
to significantly improve RAR compression and speed.

235
src/unrar/arccmt.cpp Normal file
View File

@ -0,0 +1,235 @@
bool IsAnsiComment(const char *Data,int Size);
bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
{
if (!MainComment)
return(false);
SaveFilePos SavePos(*this);
#ifndef SFX_MODULE
ushort CmtLength;
if (OldFormat)
{
Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET);
CmtLength=GetByte();
CmtLength+=(GetByte()<<8);
}
else
#endif
{
if ((NewMhd.Flags & MHD_COMMENT)!=0)
{
// Old style (RAR 2.9) archive comment embedded into the main
// archive header.
Seek(SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD,SEEK_SET);
ReadHeader();
}
else
{
// Current (RAR 3.0+) version of archive comment.
Seek(SFXSize+SIZEOF_MARKHEAD+NewMhd.HeadSize,SEEK_SET);
return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData,CmtDataW)!=0);
}
#ifndef SFX_MODULE
// Old style (RAR 2.9) comment header embedded into the main
// archive header.
if (CommHead.HeadCRC!=HeaderCRC)
{
Log(FileName,St(MLogCommHead));
Alarm();
return(false);
}
CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
#endif
}
#ifndef SFX_MODULE
if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT)!=0 || !OldFormat && CommHead.Method!=0x30)
{
if (!OldFormat && (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER || CommHead.Method > 0x35))
return(false);
ComprDataIO DataIO;
DataIO.SetTestMode(true);
uint UnpCmtLength;
if (OldFormat)
{
#ifdef RAR_NOCRYPT
return(false);
#else
UnpCmtLength=GetByte();
UnpCmtLength+=(GetByte()<<8);
CmtLength-=2;
DataIO.SetCmt13Encryption();
#endif
}
else
UnpCmtLength=CommHead.UnpSize;
DataIO.SetFiles(this,NULL);
DataIO.EnableShowProgress(false);
DataIO.SetPackedSizeToRead(CmtLength);
Unpack Unpack(&DataIO);
Unpack.Init();
Unpack.SetDestSize(UnpCmtLength);
Unpack.DoUnpack(CommHead.UnpVer,false);
if (!OldFormat && ((~DataIO.UnpFileCRC)&0xffff)!=CommHead.CommCRC)
{
Log(FileName,St(MLogCommBrk));
Alarm();
return(false);
}
else
{
byte *UnpData;
size_t UnpDataSize;
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
CmtData->Alloc(UnpDataSize);
memcpy(&((*CmtData)[0]),UnpData,UnpDataSize);
}
}
else
{
CmtData->Alloc(CmtLength);
Read(&((*CmtData)[0]),CmtLength);
if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&((*CmtData)[0]),CmtLength)&0xffff))
{
Log(FileName,St(MLogCommBrk));
Alarm();
CmtData->Reset();
return(false);
}
}
#endif
#if defined(_WIN_ALL) && !defined(_WIN_CE)
if (CmtData->Size()>0)
{
size_t CmtSize=CmtData->Size();
char *DataA=(char *)CmtData->Addr();
OemToCharBuffA(DataA,DataA,(DWORD)CmtSize);
if (CmtDataW!=NULL)
{
CmtDataW->Alloc(CmtSize+1);
// It can cause reallocation, so we should not use 'DataA' variable
// with previosuly saved CmtData->Addr() after Push() call.
CmtData->Push(0);
CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
CmtData->Alloc(CmtSize);
CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
}
}
#endif
return(CmtData->Size()>0);
}
size_t Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
{
bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
if (!ReadSubData(CmtData,NULL))
return(0);
size_t CmtSize=CmtData->Size();
if (Unicode)
{
CmtSize/=2;
Array<wchar> DataW(CmtSize+1);
RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
DataW[CmtSize]=0;
size_t DestSize=CmtSize*4;
CmtData->Alloc(DestSize+1);
WideToChar(DataW.Addr(),(char *)CmtData->Addr(),DestSize);
(*CmtData)[DestSize]=0;
CmtSize=strlen((char *)CmtData->Addr());
CmtData->Alloc(CmtSize);
if (CmtDataW!=NULL)
{
*CmtDataW=DataW;
CmtDataW->Alloc(CmtSize);
}
}
else
if (CmtDataW!=NULL)
{
CmtData->Push(0);
CmtDataW->Alloc(CmtSize+1);
CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
CmtData->Alloc(CmtSize);
CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
}
return(CmtSize);
}
void Archive::ViewComment()
{
#ifndef GUI
if (Cmd->DisableComment)
return;
Array<byte> CmtBuf;
if (GetComment(&CmtBuf,NULL))
{
size_t CmtSize=CmtBuf.Size();
char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize);
if (ChPtr!=NULL)
CmtSize=ChPtr-(char *)&CmtBuf[0];
mprintf("\n");
OutComment((char *)&CmtBuf[0],CmtSize);
}
#endif
}
#ifndef SFX_MODULE
// Used for archives created by old RAR versions up to and including RAR 2.9.
// New RAR versions store file comments in separate headers and such comments
// are displayed in ListNewSubHeader function.
void Archive::ViewFileComment()
{
if (!(NewLhd.Flags & LHD_COMMENT) || Cmd->DisableComment || OldFormat)
return;
#ifndef GUI
mprintf(St(MFileComment));
#endif
const int MaxSize=0x8000;
Array<char> CmtBuf(MaxSize);
SaveFilePos SavePos(*this);
Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
int64 SaveCurBlockPos=CurBlockPos;
int64 SaveNextBlockPos=NextBlockPos;
size_t Size=ReadHeader();
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
if (Size<7 || CommHead.HeadType!=COMM_HEAD)
return;
if (CommHead.HeadCRC!=HeaderCRC)
{
#ifndef GUI
Log(FileName,St(MLogCommHead));
#endif
return;
}
if (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER ||
CommHead.Method > 0x30 || CommHead.UnpSize > MaxSize)
return;
Read(&CmtBuf[0],CommHead.UnpSize);
if (CommHead.CommCRC!=((~CRC(0xffffffff,&CmtBuf[0],CommHead.UnpSize)&0xffff)))
{
Log(FileName,St(MLogBrokFCmt));
}
else
{
OutComment(&CmtBuf[0],CommHead.UnpSize);
#ifndef GUI
mprintf("\n");
#endif
}
}
#endif

284
src/unrar/archive.cpp Normal file
View File

@ -0,0 +1,284 @@
#include "rar.hpp"
#ifndef SHELL_EXT
#include "arccmt.cpp"
#endif
Archive::Archive(RAROptions *InitCmd)
{
Cmd=InitCmd==NULL ? &DummyCmd:InitCmd;
OpenShared=Cmd->OpenShared;
OldFormat=false;
Solid=false;
Volume=false;
MainComment=false;
Locked=false;
Signed=false;
NotFirstVolume=false;
SFXSize=0;
LatestTime.Reset();
Protected=false;
Encrypted=false;
FailedHeaderDecryption=false;
BrokenFileHeader=false;
LastReadBlock=0;
CurBlockPos=0;
NextBlockPos=0;
RecoveryPos=SIZEOF_MARKHEAD;
RecoverySectors=-1;
memset(&NewMhd,0,sizeof(NewMhd));
NewMhd.HeadType=MAIN_HEAD;
NewMhd.HeadSize=SIZEOF_NEWMHD;
HeaderCRC=0;
VolWrite=0;
AddingFilesSize=0;
AddingHeadersSize=0;
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
*HeadersSalt=0;
*SubDataSalt=0;
#endif
*FirstVolumeName=0;
*FirstVolumeNameW=0;
Splitting=false;
NewArchive=false;
SilentOpen=false;
}
#ifndef SHELL_EXT
void Archive::CheckArc(bool EnableBroken)
{
if (!IsArchive(EnableBroken))
{
Log(FileName,St(MBadArc),FileName);
ErrHandler.Exit(RARX_FATAL);
}
}
#endif
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
void Archive::CheckOpen(const char *Name,const wchar *NameW)
{
TOpen(Name,NameW);
CheckArc(false);
}
#endif
bool Archive::WCheckOpen(const char *Name,const wchar *NameW)
{
if (!WOpen(Name,NameW))
return(false);
if (!IsArchive(false))
{
#ifndef SHELL_EXT
Log(FileName,St(MNotRAR),FileName);
#endif
Close();
return(false);
}
return(true);
}
ARCSIGN_TYPE Archive::IsSignature(const byte *D,size_t Size)
{
ARCSIGN_TYPE Type=ARCSIGN_NONE;
if (Size>=1 && D[0]==0x52)
#ifndef SFX_MODULE
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
Type=ARCSIGN_OLD;
else
#endif
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
{
// We check for non-zero last signature byte, so we can return
// a sensible warning in case we'll want to change the archive
// format sometimes in the future.
Type=D[6]==0 ? ARCSIGN_CURRENT:ARCSIGN_FUTURE;
}
return Type;
}
bool Archive::IsArchive(bool EnableBroken)
{
Encrypted=false;
#ifndef SFX_MODULE
if (IsDevice())
{
#ifndef SHELL_EXT
Log(FileName,St(MInvalidName),FileName);
#endif
return(false);
}
#endif
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
return(false);
SFXSize=0;
ARCSIGN_TYPE Type;
if ((Type=IsSignature(MarkHead.Mark,sizeof(MarkHead.Mark)))!=ARCSIGN_NONE)
{
OldFormat=(Type==ARCSIGN_OLD);
if (OldFormat)
Seek(0,SEEK_SET);
}
else
{
Array<char> Buffer(MAXSFXSIZE);
long CurPos=(long)Tell();
int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
for (int I=0;I<ReadSize;I++)
if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=ARCSIGN_NONE)
{
OldFormat=(Type==ARCSIGN_OLD);
if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
{
char *D=&Buffer[28-CurPos];
if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
continue;
}
SFXSize=CurPos+I;
Seek(SFXSize,SEEK_SET);
if (!OldFormat)
Read(MarkHead.Mark,SIZEOF_MARKHEAD);
break;
}
if (SFXSize==0)
return false;
}
if (Type==ARCSIGN_FUTURE)
{
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
Log(FileName,St(MNewRarFormat));
#endif
return false;
}
ReadHeader();
SeekToNext();
#ifndef SFX_MODULE
if (OldFormat)
{
NewMhd.Flags=OldMhd.Flags & 0x3f;
NewMhd.HeadSize=OldMhd.HeadSize;
}
else
#endif
{
if (HeaderCRC!=NewMhd.HeadCRC)
{
#ifndef SHELL_EXT
Log(FileName,St(MLogMainHead));
#endif
Alarm();
if (!EnableBroken)
return(false);
}
}
Volume=(NewMhd.Flags & MHD_VOLUME);
Solid=(NewMhd.Flags & MHD_SOLID)!=0;
MainComment=(NewMhd.Flags & MHD_COMMENT)!=0;
Locked=(NewMhd.Flags & MHD_LOCK)!=0;
Signed=(NewMhd.PosAV!=0);
Protected=(NewMhd.Flags & MHD_PROTECT)!=0;
Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
if (NewMhd.EncryptVer>UNP_VER)
{
#ifdef RARDLL
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
#else
ErrHandler.SetErrorCode(RARX_WARNING);
#if !defined(SILENT) && !defined(SFX_MODULE)
Log(FileName,St(MUnknownMeth),FileName);
Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
#endif
#endif
return(false);
}
#ifdef RARDLL
// If callback function is not set, we cannot get the password,
// so we skip the initial header processing for encrypted header archive.
// It leads to skipped archive comment, but the rest of archive data
// is processed correctly.
if (Cmd->Callback==NULL)
SilentOpen=true;
#endif
// If not encrypted, we'll check it below.
NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0;
if (!SilentOpen || !Encrypted)
{
SaveFilePos SavePos(*this);
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
NotFirstVolume=false;
while (ReadHeader()!=0)
{
int HeaderType=GetHeaderType();
if (HeaderType==NEWSUB_HEAD)
{
if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
MainComment=true;
if ((SubHead.Flags & LHD_SPLIT_BEFORE) ||
Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)
NotFirstVolume=true;
}
else
{
if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 ||
Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
NotFirstVolume=true;
break;
}
SeekToNext();
}
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
}
if (!Volume || !NotFirstVolume)
{
strcpy(FirstVolumeName,FileName);
wcscpy(FirstVolumeNameW,FileNameW);
}
return(true);
}
void Archive::SeekToNext()
{
Seek(NextBlockPos,SEEK_SET);
}
#ifndef SFX_MODULE
int Archive::GetRecoverySize(bool Required)
{
if (!Protected)
return(0);
if (RecoverySectors!=-1 || !Required)
return(RecoverySectors);
SaveFilePos SavePos(*this);
Seek(SFXSize,SEEK_SET);
SearchSubBlock(SUBHEAD_TYPE_RR);
return(RecoverySectors);
}
#endif

121
src/unrar/archive.hpp Normal file
View File

@ -0,0 +1,121 @@
#ifndef _RAR_ARCHIVE_
#define _RAR_ARCHIVE_
class Pack;
enum {EN_LOCK=1,EN_VOL=2,EN_FIRSTVOL=4};
enum ARCSIGN_TYPE {ARCSIGN_NONE,ARCSIGN_OLD,ARCSIGN_CURRENT,ARCSIGN_FUTURE};
class Archive:public File
{
private:
ARCSIGN_TYPE IsSignature(const byte *D,size_t Size);
void UpdateLatestTime(FileHeader *CurBlock);
void ConvertNameCase(char *Name);
void ConvertNameCase(wchar *Name);
void ConvertUnknownHeader();
size_t ReadOldHeader();
void UnexpEndArcMsg();
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
CryptData HeadersCrypt;
byte HeadersSalt[SALT_SIZE];
#endif
#ifndef SHELL_EXT
ComprDataIO SubDataIO;
byte SubDataSalt[SALT_SIZE];
#endif
RAROptions *Cmd,DummyCmd;
MarkHeader MarkHead;
OldMainHeader OldMhd;
int RecoverySectors;
int64 RecoveryPos;
bool FailedHeaderDecryption;
RarTime LatestTime;
int LastReadBlock;
int CurHeaderType;
bool SilentOpen;
public:
Archive(RAROptions *InitCmd=NULL);
bool IsArchive(bool EnableBroken);
size_t SearchBlock(int BlockType);
size_t SearchSubBlock(const char *Type);
int ReadBlock(int BlockType);
void WriteBlock(int BlockType,BaseBlock *wb=NULL);
int PrepareNamesToWrite(char *Name,wchar *NameW,char *DestName,byte *DestNameW);
void SetLhdSize();
size_t ReadHeader();
void CheckArc(bool EnableBroken);
void CheckOpen(const char *Name,const wchar *NameW=NULL);
bool WCheckOpen(const char *Name,const wchar *NameW=NULL);
bool GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW);
void ViewComment();
void ViewFileComment();
void SetLatestTime(RarTime *NewTime);
void SeekToNext();
bool CheckAccess();
bool IsArcDir();
bool IsArcLabel();
void ConvertAttributes();
int GetRecoverySize(bool Required);
void VolSubtractHeaderSize(size_t SubSize);
void AddSubData(byte *SrcData,size_t DataSize,File *SrcFile,const char *Name,bool AllowSplit);
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
int GetHeaderType() {return(CurHeaderType);};
size_t ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW);
void WriteCommentData(byte *Data,size_t DataSize,bool FileComment);
RAROptions* GetRAROptions() {return(Cmd);}
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
BaseBlock ShortBlock;
MainHeader NewMhd;
FileHeader NewLhd;
EndArcHeader EndArcHead;
SubBlockHeader SubBlockHead;
FileHeader SubHead;
CommentHeader CommHead;
ProtectHeader ProtectHead;
AVHeader AVHead;
SignHeader SignHead;
UnixOwnersHeader UOHead;
MacFInfoHeader MACHead;
EAHeader EAHead;
StreamHeader StreamHead;
int64 CurBlockPos;
int64 NextBlockPos;
bool OldFormat;
bool Solid;
bool Volume;
bool MainComment;
bool Locked;
bool Signed;
bool NotFirstVolume;
bool Protected;
bool Encrypted;
size_t SFXSize;
bool BrokenFileHeader;
bool Splitting;
ushort HeaderCRC;
int64 VolWrite;
int64 AddingFilesSize;
size_t AddingHeadersSize;
bool NewArchive;
char FirstVolumeName[NM];
wchar FirstVolumeNameW[NM];
};
#endif

765
src/unrar/arcread.cpp Normal file
View File

@ -0,0 +1,765 @@
#include "rar.hpp"
size_t Archive::SearchBlock(int BlockType)
{
size_t Size,Count=0;
while ((Size=ReadHeader())!=0 &&
(BlockType==ENDARC_HEAD || GetHeaderType()!=ENDARC_HEAD))
{
if ((++Count & 127)==0)
Wait();
if (GetHeaderType()==BlockType)
return(Size);
SeekToNext();
}
return(0);
}
size_t Archive::SearchSubBlock(const char *Type)
{
size_t Size;
while ((Size=ReadHeader())!=0 && GetHeaderType()!=ENDARC_HEAD)
{
if (GetHeaderType()==NEWSUB_HEAD && SubHead.CmpName(Type))
return(Size);
SeekToNext();
}
return(0);
}
void Archive::UnexpEndArcMsg()
{
int64 ArcSize=FileLength();
if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
{
#ifndef SHELL_EXT
Log(FileName,St(MLogUnexpEOF));
#endif
ErrHandler.SetErrorCode(RARX_WARNING);
}
}
size_t Archive::ReadHeader()
{
// Once we failed to decrypt an encrypted block, there is no reason to
// attempt to do it further. We'll never be successful and only generate
// endless errors.
if (FailedHeaderDecryption)
return 0;
CurBlockPos=Tell();
#ifndef SFX_MODULE
if (OldFormat)
return(ReadOldHeader());
#endif
RawRead Raw(this);
bool Decrypt=Encrypted && CurBlockPos>=(int64)SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;
if (Decrypt)
{
#if defined(SHELL_EXT) || defined(RAR_NOCRYPT)
return(0);
#else
if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
{
UnexpEndArcMsg();
return(0);
}
if (!Cmd->Password.IsSet())
{
#ifdef RARDLL
if (Cmd->Callback!=NULL)
{
wchar PasswordW[MAXPASSWORD];
*PasswordW=0;
if (Cmd->Callback(UCM_NEEDPASSWORDW,Cmd->UserData,(LPARAM)PasswordW,ASIZE(PasswordW))==-1)
*PasswordW=0;
if (*PasswordW==0)
{
char PasswordA[MAXPASSWORD];
*PasswordA=0;
if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
*PasswordA=0;
GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW));
cleandata(PasswordA,sizeof(PasswordA));
}
Cmd->Password.Set(PasswordW);
cleandata(PasswordW,sizeof(PasswordW));
}
if (!Cmd->Password.IsSet())
{
Close();
Cmd->DllError=ERAR_MISSING_PASSWORD;
ErrHandler.Exit(RARX_USERBREAK);
}
#else
if (!GetPassword(PASSWORD_ARCHIVE,FileName,FileNameW,&Cmd->Password))
{
Close();
ErrHandler.Exit(RARX_USERBREAK);
}
#endif
}
HeadersCrypt.SetCryptKeys(&Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
Raw.SetCrypt(&HeadersCrypt);
#endif
}
Raw.Read(SIZEOF_SHORTBLOCKHEAD);
if (Raw.Size()==0)
{
UnexpEndArcMsg();
return(0);
}
Raw.Get(ShortBlock.HeadCRC);
byte HeadType;
Raw.Get(HeadType);
ShortBlock.HeadType=(HEADER_TYPE)HeadType;
Raw.Get(ShortBlock.Flags);
Raw.Get(ShortBlock.HeadSize);
if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
{
#ifndef SHELL_EXT
Log(FileName,St(MLogFileHead),"???");
#endif
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RARX_CRC);
return(0);
}
if (ShortBlock.HeadType==COMM_HEAD)
{
// Old style (up to RAR 2.9) comment header embedded into main
// or file header. We must not read the entire ShortBlock.HeadSize here
// to not break the comment processing logic later.
Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
}
else
if (ShortBlock.HeadType==MAIN_HEAD && (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
// 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.
Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
}
else
Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);
NextBlockPos=CurBlockPos+ShortBlock.HeadSize;
switch(ShortBlock.HeadType)
{
case MAIN_HEAD:
*(BaseBlock *)&NewMhd=ShortBlock;
Raw.Get(NewMhd.HighPosAV);
Raw.Get(NewMhd.PosAV);
if (NewMhd.Flags & MHD_ENCRYPTVER)
Raw.Get(NewMhd.EncryptVer);
break;
case ENDARC_HEAD:
*(BaseBlock *)&EndArcHead=ShortBlock;
if (EndArcHead.Flags & EARC_DATACRC)
Raw.Get(EndArcHead.ArcDataCRC);
if (EndArcHead.Flags & EARC_VOLNUMBER)
Raw.Get(EndArcHead.VolNumber);
break;
case FILE_HEAD:
case NEWSUB_HEAD:
{
FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
*(BaseBlock *)hd=ShortBlock;
Raw.Get(hd->PackSize);
Raw.Get(hd->UnpSize);
Raw.Get(hd->HostOS);
Raw.Get(hd->FileCRC);
Raw.Get(hd->FileTime);
Raw.Get(hd->UnpVer);
Raw.Get(hd->Method);
Raw.Get(hd->NameSize);
Raw.Get(hd->FileAttr);
if (hd->Flags & LHD_LARGE)
{
Raw.Get(hd->HighPackSize);
Raw.Get(hd->HighUnpSize);
}
else
{
hd->HighPackSize=hd->HighUnpSize=0;
if (hd->UnpSize==0xffffffff)
{
// UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
// that we do not know the unpacked file size and must unpack it
// until we find the end of file marker in compressed data.
hd->UnpSize=(uint)(INT64NDF);
hd->HighUnpSize=(uint)(INT64NDF>>32);
}
}
hd->FullPackSize=INT32TO64(hd->HighPackSize,hd->PackSize);
hd->FullUnpSize=INT32TO64(hd->HighUnpSize,hd->UnpSize);
char FileName[NM*4];
size_t NameSize=Min(hd->NameSize,sizeof(FileName)-1);
Raw.Get((byte *)FileName,NameSize);
FileName[NameSize]=0;
strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));
if (hd->HeadType==NEWSUB_HEAD)
{
// Let's calculate the size of optional data.
int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
if (hd->Flags & LHD_SALT)
DataSize-=SALT_SIZE;
if (DataSize>0)
{
// Here we read optional additional fields for subheaders.
// They are stored after the file name and before salt.
hd->SubData.Alloc(DataSize);
Raw.Get(&hd->SubData[0],DataSize);
if (hd->CmpName(SUBHEAD_TYPE_RR))
{
byte *D=&hd->SubData[8];
RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
}
}
}
else
if (hd->HeadType==FILE_HEAD)
{
if (hd->Flags & LHD_UNICODE)
{
EncodeFileName NameCoder;
size_t Length=strlen(FileName);
if (Length==hd->NameSize)
{
UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1);
ExtToInt(hd->FileName,hd->FileName);
}
else
{
Length++;
NameCoder.Decode(FileName,(byte *)FileName+Length,
hd->NameSize-Length,hd->FileNameW,
sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
}
if (*hd->FileNameW==0)
hd->Flags &= ~LHD_UNICODE;
}
else
*hd->FileNameW=0;
#ifndef SFX_MODULE
ConvertNameCase(hd->FileName);
ConvertNameCase(hd->FileNameW);
#endif
ConvertUnknownHeader();
}
if (hd->Flags & LHD_SALT)
Raw.Get(hd->Salt,SALT_SIZE);
hd->mtime.SetDos(hd->FileTime);
hd->ctime.Reset();
hd->atime.Reset();
hd->arctime.Reset();
if (hd->Flags & LHD_EXTTIME)
{
ushort Flags;
Raw.Get(Flags);
RarTime *tbl[4];
tbl[0]=&NewLhd.mtime;
tbl[1]=&NewLhd.ctime;
tbl[2]=&NewLhd.atime;
tbl[3]=&NewLhd.arctime;
for (int I=0;I<4;I++)
{
RarTime *CurTime=tbl[I];
uint rmode=Flags>>(3-I)*4;
if ((rmode & 8)==0)
continue;
if (I!=0)
{
uint DosTime;
Raw.Get(DosTime);
CurTime->SetDos(DosTime);
}
RarLocalTime rlt;
CurTime->GetLocal(&rlt);
if (rmode & 4)
rlt.Second++;
rlt.Reminder=0;
int count=rmode&3;
for (int J=0;J<count;J++)
{
byte CurByte;
Raw.Get(CurByte);
rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
}
CurTime->SetLocal(&rlt);
}
}
NextBlockPos+=hd->FullPackSize;
bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff;
if (hd->HeadCRC!=HeaderCRC)
{
if (hd->HeadType==NEWSUB_HEAD && strlen(hd->FileName)<ASIZE(hd->FileName)-5)
strcat(hd->FileName,"- ???");
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RARX_WARNING);
// If we have a broken encrypted header, we do not need to display
// the error message here, because it will be displayed for such
// headers later in this function. Also such headers are unlikely
// to have anything sensible in file name field, so it is useless
// to display the file name.
bool EncBroken=Decrypt && ShortBlock.HeadCRC!=(~Raw.GetCRC(false)&0xffff);
if (!EncBroken)
{
#ifndef SHELL_EXT
Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
Alarm();
#endif
}
}
}
break;
#ifndef SFX_MODULE
case COMM_HEAD:
*(BaseBlock *)&CommHead=ShortBlock;
Raw.Get(CommHead.UnpSize);
Raw.Get(CommHead.UnpVer);
Raw.Get(CommHead.Method);
Raw.Get(CommHead.CommCRC);
break;
case SIGN_HEAD:
*(BaseBlock *)&SignHead=ShortBlock;
Raw.Get(SignHead.CreationTime);
Raw.Get(SignHead.ArcNameSize);
Raw.Get(SignHead.UserNameSize);
break;
case AV_HEAD:
*(BaseBlock *)&AVHead=ShortBlock;
Raw.Get(AVHead.UnpVer);
Raw.Get(AVHead.Method);
Raw.Get(AVHead.AVVer);
Raw.Get(AVHead.AVInfoCRC);
break;
case PROTECT_HEAD:
*(BaseBlock *)&ProtectHead=ShortBlock;
Raw.Get(ProtectHead.DataSize);
Raw.Get(ProtectHead.Version);
Raw.Get(ProtectHead.RecSectors);
Raw.Get(ProtectHead.TotalBlocks);
Raw.Get(ProtectHead.Mark,8);
NextBlockPos+=ProtectHead.DataSize;
RecoverySectors=ProtectHead.RecSectors;
break;
case SUB_HEAD:
*(BaseBlock *)&SubBlockHead=ShortBlock;
Raw.Get(SubBlockHead.DataSize);
NextBlockPos+=SubBlockHead.DataSize;
Raw.Get(SubBlockHead.SubType);
Raw.Get(SubBlockHead.Level);
switch(SubBlockHead.SubType)
{
case UO_HEAD:
*(SubBlockHeader *)&UOHead=SubBlockHead;
Raw.Get(UOHead.OwnerNameSize);
Raw.Get(UOHead.GroupNameSize);
if (UOHead.OwnerNameSize>NM-1)
UOHead.OwnerNameSize=NM-1;
if (UOHead.GroupNameSize>NM-1)
UOHead.GroupNameSize=NM-1;
Raw.Get((byte *)UOHead.OwnerName,UOHead.OwnerNameSize);
Raw.Get((byte *)UOHead.GroupName,UOHead.GroupNameSize);
UOHead.OwnerName[UOHead.OwnerNameSize]=0;
UOHead.GroupName[UOHead.GroupNameSize]=0;
break;
case MAC_HEAD:
*(SubBlockHeader *)&MACHead=SubBlockHead;
Raw.Get(MACHead.fileType);
Raw.Get(MACHead.fileCreator);
break;
case EA_HEAD:
case BEEA_HEAD:
case NTACL_HEAD:
*(SubBlockHeader *)&EAHead=SubBlockHead;
Raw.Get(EAHead.UnpSize);
Raw.Get(EAHead.UnpVer);
Raw.Get(EAHead.Method);
Raw.Get(EAHead.EACRC);
break;
case STREAM_HEAD:
*(SubBlockHeader *)&StreamHead=SubBlockHead;
Raw.Get(StreamHead.UnpSize);
Raw.Get(StreamHead.UnpVer);
Raw.Get(StreamHead.Method);
Raw.Get(StreamHead.StreamCRC);
Raw.Get(StreamHead.StreamNameSize);
if (StreamHead.StreamNameSize>NM-1)
StreamHead.StreamNameSize=NM-1;
Raw.Get((byte *)StreamHead.StreamName,StreamHead.StreamNameSize);
StreamHead.StreamName[StreamHead.StreamNameSize]=0;
break;
}
break;
#endif
default:
if (ShortBlock.Flags & LONG_BLOCK)
{
uint DataSize;
Raw.Get(DataSize);
NextBlockPos+=DataSize;
}
break;
}
HeaderCRC=~Raw.GetCRC(false)&0xffff;
CurHeaderType=ShortBlock.HeadType;
if (Decrypt)
{
NextBlockPos+=Raw.PaddedSize()+SALT_SIZE;
if (ShortBlock.HeadCRC!=HeaderCRC)
{
bool Recovered=false;
if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0)
{
// 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;
for (int J=0;J<7;J++)
if (GetByte()!=0)
Recovered=false;
}
if (!Recovered)
{
#ifndef SILENT
Log(FileName,St(MEncrBadCRC),FileName);
#endif
// Close();
FailedHeaderDecryption=true;
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RARX_CRC);
return(0);
}
}
}
if (NextBlockPos<=CurBlockPos)
{
#ifndef SHELL_EXT
Log(FileName,St(MLogFileHead),"???");
#endif
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RARX_CRC);
return(0);
}
return(Raw.Size());
}
#ifndef SFX_MODULE
size_t Archive::ReadOldHeader()
{
RawRead Raw(this);
if (CurBlockPos<=(int64)SFXSize)
{
Raw.Read(SIZEOF_OLDMHD);
Raw.Get(OldMhd.Mark,4);
Raw.Get(OldMhd.HeadSize);
Raw.Get(OldMhd.Flags);
NextBlockPos=CurBlockPos+OldMhd.HeadSize;
CurHeaderType=MAIN_HEAD;
}
else
{
OldFileHeader OldLhd;
Raw.Read(SIZEOF_OLDLHD);
NewLhd.HeadType=FILE_HEAD;
Raw.Get(NewLhd.PackSize);
Raw.Get(NewLhd.UnpSize);
Raw.Get(OldLhd.FileCRC);
Raw.Get(NewLhd.HeadSize);
Raw.Get(NewLhd.FileTime);
Raw.Get(OldLhd.FileAttr);
Raw.Get(OldLhd.Flags);
Raw.Get(OldLhd.UnpVer);
Raw.Get(OldLhd.NameSize);
Raw.Get(OldLhd.Method);
NewLhd.Flags=OldLhd.Flags|LONG_BLOCK;
NewLhd.UnpVer=(OldLhd.UnpVer==2) ? 13 : 10;
NewLhd.Method=OldLhd.Method+0x30;
NewLhd.NameSize=OldLhd.NameSize;
NewLhd.FileAttr=OldLhd.FileAttr;
NewLhd.FileCRC=OldLhd.FileCRC;
NewLhd.FullPackSize=NewLhd.PackSize;
NewLhd.FullUnpSize=NewLhd.UnpSize;
NewLhd.mtime.SetDos(NewLhd.FileTime);
NewLhd.ctime.Reset();
NewLhd.atime.Reset();
NewLhd.arctime.Reset();
Raw.Read(OldLhd.NameSize);
Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize);
NewLhd.FileName[OldLhd.NameSize]=0;
ConvertNameCase(NewLhd.FileName);
*NewLhd.FileNameW=0;
if (Raw.Size()!=0)
NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize;
CurHeaderType=FILE_HEAD;
}
return(NextBlockPos>CurBlockPos ? Raw.Size():0);
}
#endif
void Archive::ConvertNameCase(char *Name)
{
if (Cmd->ConvertNames==NAMES_UPPERCASE)
{
IntToExt(Name,Name);
strupper(Name);
ExtToInt(Name,Name);
}
if (Cmd->ConvertNames==NAMES_LOWERCASE)
{
IntToExt(Name,Name);
strlower(Name);
ExtToInt(Name,Name);
}
}
#ifndef SFX_MODULE
void Archive::ConvertNameCase(wchar *Name)
{
if (Cmd->ConvertNames==NAMES_UPPERCASE)
wcsupper(Name);
if (Cmd->ConvertNames==NAMES_LOWERCASE)
wcslower(Name);
}
#endif
bool Archive::IsArcDir()
{
return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY);
}
bool Archive::IsArcLabel()
{
return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8));
}
void Archive::ConvertAttributes()
{
#if defined(_WIN_ALL) || defined(_EMX)
switch(NewLhd.HostOS)
{
case HOST_MSDOS:
case HOST_OS2:
case HOST_WIN32:
break;
case HOST_UNIX:
case HOST_BEOS:
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
NewLhd.FileAttr=0x10;
else
NewLhd.FileAttr=0x20;
break;
default:
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
NewLhd.FileAttr=0x10;
else
NewLhd.FileAttr=0x20;
break;
}
#endif
#ifdef _UNIX
// umask defines which permission bits must not be set by default
// when creating a file or directory. The typical default value
// for the process umask is S_IWGRP | S_IWOTH (octal 022),
// resulting in 0644 mode for new files.
static mode_t mask = (mode_t) -1;
if (mask == (mode_t) -1)
{
// umask call returns the current umask value. Argument (022) is not
// really important here.
mask = umask(022);
// Restore the original umask value, which was changed to 022 above.
umask(mask);
}
switch(NewLhd.HostOS)
{
case HOST_MSDOS:
case HOST_OS2:
case HOST_WIN32:
{
// Mapping MSDOS, OS/2 and Windows file attributes to Unix.
if (NewLhd.FileAttr & 0x10) // FILE_ATTRIBUTE_DIRECTORY
{
// For directories we use 0777 mask.
NewLhd.FileAttr=0777 & ~mask;
}
else
if (NewLhd.FileAttr & 1) // FILE_ATTRIBUTE_READONLY
{
// For read only files we use 0444 mask with 'w' bits turned off.
NewLhd.FileAttr=0444 & ~mask;
}
else
{
// umask does not set +x for regular files, so we use 0666
// instead of 0777 as for directories.
NewLhd.FileAttr=0666 & ~mask;
}
}
break;
case HOST_UNIX:
case HOST_BEOS:
break;
default:
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
NewLhd.FileAttr=0x41ff & ~mask;
else
NewLhd.FileAttr=0x81b6 & ~mask;
break;
}
#endif
}
void Archive::ConvertUnknownHeader()
{
if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10))
NewLhd.Flags|=LHD_DIRECTORY;
if (NewLhd.HostOS>=HOST_MAX)
{
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
NewLhd.FileAttr=0x10;
else
NewLhd.FileAttr=0x20;
}
for (char *s=NewLhd.FileName;*s!=0;s=charnext(s))
{
if (*s=='/' || *s=='\\')
*s=CPATHDIVIDER;
#if defined(_APPLE) && !defined(UNICODE_SUPPORTED)
if ((byte)*s<32 || (byte)*s>127)
*s='_';
#endif
#if defined(_WIN_ALL) || defined(_EMX)
// ':' 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
// replace ':' now.
if (*s==':')
*s='_';
#endif
}
for (wchar *s=NewLhd.FileNameW;*s!=0;s++)
{
if (*s=='/' || *s=='\\')
*s=CPATHDIVIDER;
#if defined(_WIN_ALL) || defined(_EMX)
// ':' 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
// replace ':' now.
if (*s==':')
*s='_';
#endif
}
}
#ifndef SHELL_EXT
bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
{
if (HeaderCRC!=SubHead.HeadCRC)
{
#ifndef SHELL_EXT
Log(FileName,St(MSubHeadCorrupt));
#endif
ErrHandler.SetErrorCode(RARX_CRC);
return(false);
}
if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>/*PACK_VER*/36)
{
#ifndef SHELL_EXT
Log(FileName,St(MSubHeadUnknown));
#endif
return(false);
}
if (SubHead.PackSize==0 && (SubHead.Flags & LHD_SPLIT_AFTER)==0)
return(true);
SubDataIO.Init();
Unpack Unpack(&SubDataIO);
Unpack.Init();
if (DestFile==NULL)
{
UnpData->Alloc(SubHead.UnpSize);
SubDataIO.SetUnpackToMemory(&(*UnpData)[0],SubHead.UnpSize);
}
if (SubHead.Flags & LHD_PASSWORD)
if (Cmd->Password.IsSet())
SubDataIO.SetEncryption(SubHead.UnpVer,&Cmd->Password,
(SubHead.Flags & LHD_SALT) ? SubHead.Salt:NULL,false,
SubHead.UnpVer>=36);
else
return(false);
SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
SubDataIO.EnableShowProgress(false);
SubDataIO.SetFiles(this,DestFile);
SubDataIO.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER)!=0;
SubDataIO.SetSubHeader(&SubHead,NULL);
Unpack.SetDestSize(SubHead.UnpSize);
if (SubHead.Method==0x30)
CmdExtract::UnstoreFile(SubDataIO,SubHead.UnpSize);
else
Unpack.DoUnpack(SubHead.UnpVer,false);
if (SubHead.FileCRC!=~SubDataIO.UnpFileCRC)
{
#ifndef SHELL_EXT
Log(FileName,St(MSubHeadDataCRC),SubHead.FileName);
#endif
ErrHandler.SetErrorCode(RARX_CRC);
if (UnpData!=NULL)
UnpData->Reset();
return(false);
}
return(true);
}
#endif

131
src/unrar/array.hpp Normal file
View File

@ -0,0 +1,131 @@
#ifndef _RAR_ARRAY_
#define _RAR_ARRAY_
extern ErrorHandler ErrHandler;
template <class T> class Array
{
private:
T *Buffer;
size_t BufSize;
size_t AllocSize;
public:
Array();
Array(size_t Size);
~Array();
inline void CleanData();
inline T& operator [](size_t Item);
inline size_t Size(); // Returns the size in items, not in bytes.
void Add(size_t Items);
void Alloc(size_t Items);
void Reset();
void SoftReset();
void operator = (Array<T> &Src);
void Push(T Item);
T* Addr() {return(Buffer);}
};
template <class T> void Array<T>::CleanData()
{
Buffer=NULL;
BufSize=0;
AllocSize=0;
}
template <class T> Array<T>::Array()
{
CleanData();
}
template <class T> Array<T>::Array(size_t Size)
{
Buffer=(T *)malloc(sizeof(T)*Size);
if (Buffer==NULL && Size!=0)
ErrHandler.MemoryError();
AllocSize=BufSize=Size;
}
template <class T> Array<T>::~Array()
{
if (Buffer!=NULL)
free(Buffer);
}
template <class T> inline T& Array<T>::operator [](size_t Item)
{
return(Buffer[Item]);
}
template <class T> inline size_t Array<T>::Size()
{
return(BufSize);
}
template <class T> void Array<T>::Add(size_t Items)
{
BufSize+=Items;
if (BufSize>AllocSize)
{
size_t Suggested=AllocSize+AllocSize/4+32;
size_t NewSize=Max(BufSize,Suggested);
Buffer=(T *)realloc(Buffer,NewSize*sizeof(T));
if (Buffer==NULL)
ErrHandler.MemoryError();
AllocSize=NewSize;
}
}
template <class T> void Array<T>::Alloc(size_t Items)
{
if (Items>AllocSize)
Add(Items-BufSize);
else
BufSize=Items;
}
template <class T> void Array<T>::Reset()
{
if (Buffer!=NULL)
{
free(Buffer);
Buffer=NULL;
}
BufSize=0;
AllocSize=0;
}
// Reste buffer size, but preserve already allocated memory if any,
// so we can reuse it without wasting time to allocation.
template <class T> void Array<T>::SoftReset()
{
BufSize=0;
}
template <class T> void Array<T>::operator =(Array<T> &Src)
{
Reset();
Alloc(Src.BufSize);
if (Src.BufSize!=0)
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
}
template <class T> void Array<T>::Push(T Item)
{
Add(1);
(*this)[Size()-1]=Item;
}
#endif

113
src/unrar/beosea.cpp Normal file
View File

@ -0,0 +1,113 @@
void ExtractBeEA(Archive &Arc,char *FileName)
{
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RARX_CRC);
return;
}
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
{
Log(Arc.FileName,St(MEAUnknHeader),FileName);
return;
}
ComprDataIO DataIO;
Unpack Unpack(&DataIO);
Unpack.Init();
Array<byte> UnpData(Arc.EAHead.UnpSize);
DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
DataIO.EnableShowProgress(false);
DataIO.SetFiles(&Arc,NULL);
Unpack.SetDestSize(Arc.EAHead.UnpSize);
Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RARX_CRC);
return;
}
int fd = open(FileName,O_WRONLY);
if (fd==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
return;
}
int AttrPos=0;
while (AttrPos<Arc.EAHead.UnpSize)
{
unsigned char *CurItem=&UnpData[AttrPos];
int NameSize=CurItem[0]+((int)CurItem[1]<<8);
int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
char Name[1024];
if (NameSize>=sizeof(Name))
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
break;
}
memcpy(Name,CurItem+10,NameSize);
Name[NameSize]=0;
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
break;
}
AttrPos+=10+NameSize+Size;
}
close(fd);
mprintf(St(MShowEA));
}
void ExtractBeEANew(Archive &Arc,char *FileName)
{
Array<byte> SubData;
if (!Arc.ReadSubData(&SubData,NULL))
return;
int fd = open(FileName,O_WRONLY);
if (fd==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
return;
}
int AttrPos=0;
while (AttrPos<Arc.EAHead.UnpSize)
{
unsigned char *CurItem=&SubData[AttrPos];
int NameSize=CurItem[0]+((int)CurItem[1]<<8);
int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
char Name[1024];
if (NameSize>=sizeof(Name))
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
break;
}
memcpy(Name,CurItem+10,NameSize);
Name[NameSize]=0;
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
break;
}
AttrPos+=10+NameSize+Size;
}
close(fd);
mprintf(St(MShowEA));
}

1431
src/unrar/cmddata.cpp Normal file

File diff suppressed because it is too large Load Diff

64
src/unrar/cmddata.hpp Normal file
View File

@ -0,0 +1,64 @@
#ifndef _RAR_CMDDATA_
#define _RAR_CMDDATA_
#define DefaultStoreList "7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;taz;tgz;z;zip"
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
class CommandData:public RAROptions
{
private:
void ProcessSwitchesString(char *Str);
void ProcessSwitch(const char *Switch,const wchar *SwitchW=NULL);
void BadSwitch(const char *Switch);
bool ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode);
uint GetExclAttr(const char *Str);
bool FileLists;
bool NoMoreSwitches;
RAR_CMD_LIST_MODE ListMode;
bool BareOutput;
public:
CommandData();
~CommandData();
void Init();
void Close();
void PreprocessCommandLine(int argc, char *argv[]);
void ParseCommandLine(int argc, char *argv[]);
void ParseArg(char *Arg,wchar *ArgW);
void ParseDone();
void ParseEnvVar();
void ReadConfig();
bool PreprocessSwitch(const char *Switch);
void OutTitle();
void OutHelp(RAR_EXIT ExitCode);
bool IsSwitch(int Ch);
bool ExclCheck(char *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
bool ExclDirByAttr(uint FileAttr);
bool TimeCheck(RarTime &ft);
bool SizeCheck(int64 Size);
bool AnyFiltersActive();
int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH);
void ProcessCommand();
void AddArcName(const char *Name,const wchar *NameW);
bool GetArcName(char *Name,wchar *NameW,int MaxSize);
bool CheckWinSize();
int GetRecoverySize(const char *Str,int DefSize);
char Command[NM+16];
wchar CommandW[NM+16];
char ArcName[NM];
wchar ArcNameW[NM];
StringList *FileArgs;
StringList *ExclArgs;
StringList *InclArgs;
StringList *ArcNames;
StringList *StoreArgs;
};
#endif

48
src/unrar/coder.cpp Normal file
View File

@ -0,0 +1,48 @@
inline unsigned int RangeCoder::GetChar()
{
return(UnpackRead->GetChar());
}
void RangeCoder::InitDecoder(Unpack *UnpackRead)
{
RangeCoder::UnpackRead=UnpackRead;
low=code=0;
range=uint(-1);
for (int i=0;i < 4;i++)
code=(code << 8) | GetChar();
}
// (int) cast before "low" added only to suppress compiler warnings.
#define ARI_DEC_NORMALIZE(code,low,range,read) \
{ \
while ((low^(low+range))<TOP || range<BOT && ((range=-(int)low&(BOT-1)),1)) \
{ \
code=(code << 8) | read->GetChar(); \
range <<= 8; \
low <<= 8; \
} \
}
inline int RangeCoder::GetCurrentCount()
{
return (code-low)/(range /= SubRange.scale);
}
inline uint RangeCoder::GetCurrentShiftCount(uint SHIFT)
{
return (code-low)/(range >>= SHIFT);
}
inline void RangeCoder::Decode()
{
low += range*SubRange.LowCount;
range *= SubRange.HighCount-SubRange.LowCount;
}

25
src/unrar/coder.hpp Normal file
View File

@ -0,0 +1,25 @@
/****************************************************************************
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
****************************************************************************/
const uint TOP=1 << 24, BOT=1 << 15;
class RangeCoder
{
public:
void InitDecoder(Unpack *UnpackRead);
inline int GetCurrentCount();
inline uint GetCurrentShiftCount(uint SHIFT);
inline void Decode();
inline void PutChar(unsigned int c);
inline unsigned int GetChar();
uint low, code, range;
struct SUBRANGE
{
uint LowCount, HighCount, scale;
} SubRange;
Unpack *UnpackRead;
};

40
src/unrar/compress.hpp Normal file
View File

@ -0,0 +1,40 @@
#ifndef _RAR_COMPRESS_
#define _RAR_COMPRESS_
class ComprDataIO;
class PackingFileTable;
#define MAX_LZ_MATCH 0x101
#define MAXWINSIZE 0x400000
#define MAXWINMASK (MAXWINSIZE-1)
#define LOW_DIST_REP_COUNT 16
#define NC 299 /* alphabet = {0, 1, 2, ..., NC - 1} */
#define DC 60
#define LDC 17
#define RC 28
#define HUFF_TABLE_SIZE (NC+DC+RC+LDC)
#define BC 20
#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
#define DC20 48
#define RC20 28
#define BC20 19
#define MC20 257
// Largest alphabet size among all values listed above.
#define LARGEST_TABLE_SIZE 299
enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA};
enum FilterType {
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
FILTER_ITANIUM, FILTER_E8E9V2
};
#endif

319
src/unrar/consio.cpp Normal file
View File

@ -0,0 +1,319 @@
#include "rar.hpp"
#ifndef GUI
#include "log.cpp"
#endif
static int KbdAnsi(char *Addr,int Size);
#if !defined(GUI) && !defined(SILENT)
static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
static byte GetKey();
#endif
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
static bool Sound=false;
const int MaxMsgSize=2*NM+2048;
void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound)
{
::MsgStream=MsgStream;
::Sound=Sound;
}
#if !defined(GUI) && !defined(SILENT)
void mprintf(const char *fmt,...)
{
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
return;
char Msg[MaxMsgSize];
va_list argptr;
va_start(argptr,fmt);
vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
// Different vsnprintf implementation can return either -1 or >=MaxMsgSize
// if string is truncated. So we do not check exit code and always zero
// terminate the string for safety. It is faster than check for error.
Msg[ASIZE(Msg)-1] = 0;
RawPrint(Msg,MsgStream);
va_end(argptr);
}
#endif
#if !defined(GUI) && !defined(SILENT)
void eprintf(const char *fmt,...)
{
if (MsgStream==MSG_NULL)
return;
safebuf char Msg[MaxMsgSize];
va_list argptr;
va_start(argptr,fmt);
vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
// Different vsnprintf implementation can return either -1 or >=MaxMsgSize
// if string is truncated. So we do not check exit code and always zero
// terminate the string for safety. It is faster than check for error.
Msg[ASIZE(Msg)-1] = 0;
RawPrint(Msg,MSG_STDERR);
va_end(argptr);
}
#endif
#if !defined(GUI) && !defined(SILENT)
void RawPrint(char *Msg,MESSAGE_TYPE MessageType)
{
File OutFile;
switch(MessageType)
{
case MSG_STDOUT:
OutFile.SetHandleType(FILE_HANDLESTD);
break;
case MSG_STDERR:
case MSG_ERRONLY:
OutFile.SetHandleType(FILE_HANDLEERR);
break;
default:
return;
}
#ifdef _WIN_ALL
CharToOemA(Msg,Msg);
char OutMsg[MaxMsgSize];
size_t OutPos=0;
for (size_t I=0;Msg[I]!=0;I++)
{
if (Msg[I]=='\n' && (I==0 || Msg[I-1]!='\r') && OutPos<ASIZE(OutMsg)-1)
OutMsg[OutPos++]='\r';
if (OutPos<ASIZE(OutMsg)-1)
OutMsg[OutPos++]=Msg[I];
}
OutMsg[OutPos]=0;
strcpy(Msg,OutMsg);
#endif
#if defined(_UNIX) || defined(_EMX)
char OutMsg[MaxMsgSize],*OutPos=OutMsg;
for (size_t I=0;Msg[I]!=0;I++)
if (Msg[I]!='\r')
*(OutPos++)=Msg[I];
*OutPos=0;
strcpy(Msg,OutMsg);
#endif
OutFile.Write(Msg,strlen(Msg));
}
#endif
#ifndef SILENT
void Alarm()
{
#ifndef SFX_MODULE
if (Sound)
putchar('\007');
#endif
}
#endif
#ifndef SILENT
#ifndef GUI
void GetPasswordText(wchar *Str,uint MaxLength)
{
if (MaxLength==0)
return;
#ifdef _WIN_ALL
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
DWORD ConInMode,ConOutMode;
DWORD Read=0;
GetConsoleMode(hConIn,&ConInMode);
GetConsoleMode(hConOut,&ConOutMode);
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
ReadConsoleW(hConIn,Str,MaxLength-1,&Read,NULL);
Str[Read]=0;
SetConsoleMode(hConIn,ConInMode);
SetConsoleMode(hConOut,ConOutMode);
#else
char StrA[MAXPASSWORD];
#if defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
fgets(StrA,ASIZE(StrA)-1,stdin);
#else
strncpyz(StrA,getpass(""),ASIZE(StrA));
#endif
CharToWide(StrA,Str,MaxLength);
cleandata(StrA,sizeof(StrA));
#endif
Str[MaxLength-1]=0;
RemoveLF(Str);
}
#endif
#endif
#ifndef SILENT
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,
SecPassword *Password)
{
Alarm();
while (true)
{
char PromptStr[NM+256];
#if defined(_EMX) || defined(_BEOS)
strcpy(PromptStr,St(MAskPswEcho));
#else
strcpy(PromptStr,St(MAskPsw));
#endif
if (Type!=PASSWORD_GLOBAL)
{
strcat(PromptStr,St(MFor));
char *NameOnly=PointToName(FileName);
if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
strcat(PromptStr,NameOnly);
}
eprintf("\n%s: ",PromptStr);
wchar PlainPsw[MAXPASSWORD];
GetPasswordText(PlainPsw,ASIZE(PlainPsw));
if (*PlainPsw==0 && Type==PASSWORD_GLOBAL)
return(false);
if (Type==PASSWORD_GLOBAL)
{
eprintf(St(MReAskPsw));
wchar CmpStr[MAXPASSWORD];
GetPasswordText(CmpStr,ASIZE(CmpStr));
if (*CmpStr==0 || wcscmp(PlainPsw,CmpStr)!=0)
{
eprintf(St(MNotMatchPsw));
cleandata(PlainPsw,sizeof(PlainPsw));
cleandata(CmpStr,sizeof(CmpStr));
continue;
}
cleandata(CmpStr,sizeof(CmpStr));
}
Password->Set(PlainPsw);
cleandata(PlainPsw,sizeof(PlainPsw));
break;
}
return(true);
}
#endif
#if !defined(GUI) && !defined(SILENT)
byte GetKey()
{
char Str[80];
bool EndOfFile;
#if defined(__GNUC__) || defined(sun)
EndOfFile=(fgets(Str,sizeof(Str),stdin)==NULL);
#else
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
EndOfFile=(SrcFile.Read(Str,sizeof(Str))==0);
#endif
if (EndOfFile)
{
// Looks like stdin is a null device. We can enter to infinite loop
// calling Ask(), so let's better exit.
ErrHandler.Exit(RARX_USERBREAK);
}
return (byte)Str[0];
}
#endif
#if !defined(GUI) && !defined(SILENT)
int Ask(const char *AskStr)
{
const int MaxItems=10;
char Item[MaxItems][40];
int ItemKeyPos[MaxItems],NumItems=0;
for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
{
char *CurItem=Item[NumItems];
strncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
char *EndItem=strchr(CurItem,'_');
if (EndItem!=NULL)
*EndItem=0;
int KeyPos=0,CurKey;
while ((CurKey=CurItem[KeyPos])!=0)
{
bool Found=false;
for (int I=0;I<NumItems && !Found;I++)
if (loctoupper(Item[I][ItemKeyPos[I]])==loctoupper(CurKey))
Found=true;
if (!Found && CurKey!=' ')
break;
KeyPos++;
}
ItemKeyPos[NumItems]=KeyPos;
NumItems++;
}
for (int I=0;I<NumItems;I++)
{
eprintf(I==0 ? (NumItems>4 ? "\n":" "):", ");
int KeyPos=ItemKeyPos[I];
for (int J=0;J<KeyPos;J++)
eprintf("%c",Item[I][J]);
eprintf("[%c]%s",Item[I][KeyPos],&Item[I][KeyPos+1]);
}
eprintf(" ");
byte Ch=GetKey();
#if defined(_WIN_ALL)
OemToCharBuffA((LPCSTR)&Ch,(LPSTR)&Ch,1);
#endif
Ch=loctoupper(Ch);
for (int I=0;I<NumItems;I++)
if (Ch==(byte)Item[I][ItemKeyPos[I]])
return(I+1);
return(0);
}
#endif
int KbdAnsi(char *Addr,size_t Size)
{
int RetCode=0;
#ifndef GUI
for (size_t I=0;I<Size;I++)
if (Addr[I]==27 && Addr[I+1]=='[')
{
for (size_t J=I+2;J<Size;J++)
{
if (Addr[J]=='\"')
return(2);
if (!IsDigit(Addr[J]) && Addr[J]!=';')
break;
}
RetCode=1;
}
#endif
return(RetCode);
}
void OutComment(char *Comment,size_t Size)
{
#ifndef GUI
if (KbdAnsi(Comment,Size)==2)
return;
const size_t MaxOutSize=0x400;
for (size_t I=0;I<Size;I+=MaxOutSize)
{
char Msg[MaxOutSize+1];
size_t CopySize=Min(MaxOutSize,Size-I);
strncpy(Msg,Comment+I,CopySize);
Msg[CopySize]=0;
mprintf("%s",Msg);
}
mprintf("\n");
#endif
}

37
src/unrar/consio.hpp Normal file
View File

@ -0,0 +1,37 @@
#ifndef _RAR_CONSIO_
#define _RAR_CONSIO_
#if !defined(SILENT) && !defined(SFX_MODULE)
enum {SOUND_OK,SOUND_ALARM,SOUND_ERROR,SOUND_QUESTION};
#endif
enum PASSWORD_TYPE {PASSWORD_GLOBAL,PASSWORD_FILE,PASSWORD_ARCHIVE};
void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound);
#ifndef SILENT
void mprintf(const char *fmt,...);
void eprintf(const char *fmt,...);
void Alarm();
void GetPasswordText(wchar *Str,uint MaxLength);
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,SecPassword *Password);
int Ask(const char *AskStr);
#endif
void OutComment(char *Comment,size_t Size);
#ifdef SILENT
#ifdef __GNUC__
#define mprintf(args...)
#define eprintf(args...)
#else
inline void mprintf(const char *fmt,...) {}
inline void eprintf(const char *fmt,...) {}
#endif
inline void Alarm() {}
inline void GetPasswordText(wchar *Str,uint MaxLength) {}
inline bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,SecPassword *Password) {return(false);}
inline int Ask(const char *AskStr) {return(0);}
#endif
#endif

91
src/unrar/crc.cpp Normal file
View File

@ -0,0 +1,91 @@
// This CRC function is based on Intel Slicing-by-8 algorithm.
//
// Original Intel Slicing-by-8 code is available here:
//
// http://sourceforge.net/projects/slicing-by-8/
//
// Original Intel Slicing-by-8 code is licensed as:
//
// Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
//
// This software program is licensed subject to the BSD License,
// available at http://www.opensource.org/licenses/bsd-license.html
#include "rar.hpp"
// CRCTab duplicates crc_tables[0], but we still need it to decrypt
// old version RAR archives. GUI code might use it for ZIP encryption.
uint CRCTab[256];
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
void InitCRC()
{
for (uint I=0;I<256;I++) // Build the classic CRC32 lookup table.
{
uint C=I;
for (uint J=0;J<8;J++)
C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
CRCTab[I]=crc_tables[0][I]=C;
}
for (uint I=0;I<=256;I++) // Build additional lookup tables.
{
uint C=crc_tables[0][I];
for (uint J=1;J<8;J++)
{
C=crc_tables[0][(byte)C]^(C>>8);
crc_tables[J][I]=C;
}
}
}
uint CRC(uint StartCRC,const void *Addr,size_t Size)
{
if (CRCTab[1]==0)
InitCRC();
byte *Data=(byte *)Addr;
// Align Data to 8 for better performance.
for (;Size>0 && ((long)Data & 7);Size--,Data++)
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
for (;Size>=8;Size-=8,Data+=8)
{
#ifdef BIG_ENDIAN
StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
#else
StartCRC ^= *(uint32 *) Data;
#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][Data[4]] ^
crc_tables[2][Data[5]] ^
crc_tables[1][Data[6]] ^
crc_tables[0][Data[7]];
}
for (;Size>0;Size--,Data++) // Process left data.
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
return(StartCRC);
}
#ifndef SFX_MODULE
// For RAR 1.4 archives in case somebody still has them.
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
{
byte *Data=(byte *)Addr;
for (size_t I=0;I<Size;I++)
{
StartCRC=(StartCRC+Data[I])&0xffff;
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
}
return(StartCRC);
}
#endif

8
src/unrar/crc.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef _RAR_CRC_
#define _RAR_CRC_
void InitCRC();
uint CRC(uint StartCRC,const void *Addr,size_t Size);
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size);
#endif

387
src/unrar/crypt.cpp Normal file
View File

@ -0,0 +1,387 @@
#include "rar.hpp"
#ifndef SFX_MODULE
extern uint CRCTab[256];
#endif
#define NROUNDS 32
#define rol(x,n,xsize) (((x)<<(n)) | ((x)>>(xsize-(n))))
#define ror(x,n,xsize) (((x)>>(n)) | ((x)<<(xsize-(n))))
#define substLong(t) ( (uint)SubstTable[(uint)t&255] | \
((uint)SubstTable[(int)(t>> 8)&255]<< 8) | \
((uint)SubstTable[(int)(t>>16)&255]<<16) | \
((uint)SubstTable[(int)(t>>24)&255]<<24) )
CryptKeyCacheItem CryptData::Cache[4];
int CryptData::CachePos=0;
#ifndef SFX_MODULE
static byte InitSubstTable[256]={
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
};
#endif
void CryptData::DecryptBlock(byte *Buf,size_t Size)
{
rin.blockDecrypt(Buf,Size,Buf);
}
#ifndef SFX_MODULE
void CryptData::EncryptBlock20(byte *Buf)
{
uint A,B,C,D,T,TA,TB;
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0];
B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1];
C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2];
D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3];
#else
uint32 *BufPtr=(uint32 *)Buf;
A=BufPtr[0]^Key[0];
B=BufPtr[1]^Key[1];
C=BufPtr[2]^Key[2];
D=BufPtr[3]^Key[3];
#endif
for(int I=0;I<NROUNDS;I++)
{
T=((C+rol(D,11,32))^Key[I&3]);
TA=A^substLong(T);
T=((D^rol(C,17,32))+Key[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
C^=Key[0];
Buf[0]=(byte)C;
Buf[1]=(byte)(C>>8);
Buf[2]=(byte)(C>>16);
Buf[3]=(byte)(C>>24);
D^=Key[1];
Buf[4]=(byte)D;
Buf[5]=(byte)(D>>8);
Buf[6]=(byte)(D>>16);
Buf[7]=(byte)(D>>24);
A^=Key[2];
Buf[8]=(byte)A;
Buf[9]=(byte)(A>>8);
Buf[10]=(byte)(A>>16);
Buf[11]=(byte)(A>>24);
B^=Key[3];
Buf[12]=(byte)B;
Buf[13]=(byte)(B>>8);
Buf[14]=(byte)(B>>16);
Buf[15]=(byte)(B>>24);
#else
BufPtr[0]=C^Key[0];
BufPtr[1]=D^Key[1];
BufPtr[2]=A^Key[2];
BufPtr[3]=B^Key[3];
#endif
UpdKeys(Buf);
}
void CryptData::DecryptBlock20(byte *Buf)
{
byte InBuf[16];
uint A,B,C,D,T,TA,TB;
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0];
B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1];
C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2];
D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3];
#else
uint32 *BufPtr=(uint32 *)Buf;
A=BufPtr[0]^Key[0];
B=BufPtr[1]^Key[1];
C=BufPtr[2]^Key[2];
D=BufPtr[3]^Key[3];
#endif
memcpy(InBuf,Buf,sizeof(InBuf));
for(int I=NROUNDS-1;I>=0;I--)
{
T=((C+rol(D,11,32))^Key[I&3]);
TA=A^substLong(T);
T=((D^rol(C,17,32))+Key[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
C^=Key[0];
Buf[0]=(byte)C;
Buf[1]=(byte)(C>>8);
Buf[2]=(byte)(C>>16);
Buf[3]=(byte)(C>>24);
D^=Key[1];
Buf[4]=(byte)D;
Buf[5]=(byte)(D>>8);
Buf[6]=(byte)(D>>16);
Buf[7]=(byte)(D>>24);
A^=Key[2];
Buf[8]=(byte)A;
Buf[9]=(byte)(A>>8);
Buf[10]=(byte)(A>>16);
Buf[11]=(byte)(A>>24);
B^=Key[3];
Buf[12]=(byte)B;
Buf[13]=(byte)(B>>8);
Buf[14]=(byte)(B>>16);
Buf[15]=(byte)(B>>24);
#else
BufPtr[0]=C^Key[0];
BufPtr[1]=D^Key[1];
BufPtr[2]=A^Key[2];
BufPtr[3]=B^Key[3];
#endif
UpdKeys(InBuf);
}
void CryptData::UpdKeys(byte *Buf)
{
for (int I=0;I<16;I+=4)
{
Key[0]^=CRCTab[Buf[I]];
Key[1]^=CRCTab[Buf[I+1]];
Key[2]^=CRCTab[Buf[I+2]];
Key[3]^=CRCTab[Buf[I+3]];
}
}
void CryptData::Swap(byte *Ch1,byte *Ch2)
{
byte Ch=*Ch1;
*Ch1=*Ch2;
*Ch2=Ch;
}
#endif
void CryptData::SetCryptKeys(SecPassword *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
{
if (!Password->IsSet())
return;
wchar PlainPsw[MAXPASSWORD];
Password->Get(PlainPsw,ASIZE(PlainPsw));
if (OldOnly)
{
#ifndef SFX_MODULE
if (CRCTab[1]==0)
InitCRC();
char Psw[MAXPASSWORD];
memset(Psw,0,sizeof(Psw));
// We need to use ASCII password for older encryption algorithms.
WideToChar(PlainPsw,Psw,ASIZE(Psw));
Psw[ASIZE(Psw)-1]=0;
size_t PswLength=strlen(Psw);
SetOldKeys(Psw);
Key[0]=0xD3A3B879L;
Key[1]=0x3F6D12F7L;
Key[2]=0x7515A235L;
Key[3]=0xA4E7F123L;
memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
for (int J=0;J<256;J++)
for (size_t I=0;I<PswLength;I+=2)
{
uint N1=(byte)CRCTab [ (byte(Psw[I]) - J) &0xff];
uint N2=(byte)CRCTab [ (byte(Psw[I+1]) + J) &0xff];
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]);
}
for (size_t I=0;I<PswLength;I+=16)
EncryptBlock20((byte *)&Psw[I]);
cleandata(Psw,sizeof(Psw));
#endif
cleandata(PlainPsw,sizeof(PlainPsw));
return;
}
bool Cached=false;
for (uint I=0;I<ASIZE(Cache);I++)
if (Cache[I].Password==*Password &&
(Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&
Cache[I].HandsOffHash==HandsOffHash)
{
memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey));
memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit));
Cached=true;
break;
}
if (!Cached)
{
byte RawPsw[2*MAXPASSWORD+SALT_SIZE];
WideToRaw(PlainPsw,RawPsw);
size_t RawLength=2*wcslen(PlainPsw);
if (Salt!=NULL)
{
memcpy(RawPsw+RawLength,Salt,SALT_SIZE);
RawLength+=SALT_SIZE;
}
hash_context c;
hash_initial(&c);
const int HashRounds=0x40000;
for (int I=0;I<HashRounds;I++)
{
hash_process( &c, RawPsw, RawLength, HandsOffHash);
byte PswNum[3];
PswNum[0]=(byte)I;
PswNum[1]=(byte)(I>>8);
PswNum[2]=(byte)(I>>16);
hash_process( &c, PswNum, 3, HandsOffHash);
if (I%(HashRounds/16)==0)
{
hash_context tempc=c;
uint32 digest[5];
hash_final( &tempc, digest, HandsOffHash);
AESInit[I/(HashRounds/16)]=(byte)digest[4];
}
}
uint32 digest[5];
hash_final( &c, digest, HandsOffHash);
for (int I=0;I<4;I++)
for (int J=0;J<4;J++)
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
Cache[CachePos].Password=*Password;
if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true)
memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE);
Cache[CachePos].HandsOffHash=HandsOffHash;
memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey));
memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit));
CachePos=(CachePos+1)%ASIZE(Cache);
cleandata(RawPsw,sizeof(RawPsw));
}
rin.init(Encrypt ? Rijndael::Encrypt : Rijndael::Decrypt,AESKey,AESInit);
cleandata(PlainPsw,sizeof(PlainPsw));
}
#ifndef SFX_MODULE
void CryptData::SetOldKeys(const char *Password)
{
uint PswCRC=CRC(0xffffffff,Password,strlen(Password));
OldKey[0]=PswCRC&0xffff;
OldKey[1]=(PswCRC>>16)&0xffff;
OldKey[2]=OldKey[3]=0;
PN1=PN2=PN3=0;
byte Ch;
while ((Ch=*Password)!=0)
{
PN1+=Ch;
PN2^=Ch;
PN3+=Ch;
PN3=(byte)rol(PN3,1,8);
OldKey[2]^=Ch^CRCTab[Ch];
OldKey[3]+=Ch+(CRCTab[Ch]>>16);
Password++;
}
}
void CryptData::SetAV15Encryption()
{
OldKey[0]=0x4765;
OldKey[1]=0x9021;
OldKey[2]=0x7382;
OldKey[3]=0x5215;
}
void CryptData::SetCmt13Encryption()
{
PN1=0;
PN2=7;
PN3=77;
}
void CryptData::Crypt(byte *Data,uint Count,int Method)
{
if (Method==OLD_DECODE)
Decode13(Data,Count);
else
if (Method==OLD_ENCODE)
Encode13(Data,Count);
else
Crypt15(Data,Count);
}
void CryptData::Encode13(byte *Data,uint Count)
{
while (Count--)
{
PN2+=PN3;
PN1+=PN2;
*Data+=PN1;
Data++;
}
}
void CryptData::Decode13(byte *Data,uint Count)
{
while (Count--)
{
PN2+=PN3;
PN1+=PN2;
*Data-=PN1;
Data++;
}
}
void CryptData::Crypt15(byte *Data,uint Count)
{
while (Count--)
{
OldKey[0]+=0x1234;
OldKey[1]^=CRCTab[(OldKey[0] & 0x1fe)>>1];
OldKey[2]-=CRCTab[(OldKey[0] & 0x1fe)>>1]>>16;
OldKey[0]^=OldKey[2];
OldKey[3]=ror(OldKey[3]&0xffff,1,16)^OldKey[1];
OldKey[3]=ror(OldKey[3]&0xffff,1,16);
OldKey[0]^=OldKey[3];
*Data^=(byte)(OldKey[0]>>8);
Data++;
}
}
#endif

62
src/unrar/crypt.hpp Normal file
View File

@ -0,0 +1,62 @@
#ifndef _RAR_CRYPT_
#define _RAR_CRYPT_
enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
struct CryptKeyCacheItem
{
#ifndef _SFX_RTL_
CryptKeyCacheItem()
{
Password.Set(L"");
}
~CryptKeyCacheItem()
{
memset(AESKey,0,sizeof(AESKey));
memset(AESInit,0,sizeof(AESInit));
memset(&Password,0,sizeof(Password));
}
#endif
byte AESKey[16],AESInit[16];
SecPassword Password;
bool SaltPresent;
byte Salt[SALT_SIZE];
bool HandsOffHash;
};
class CryptData
{
private:
void Encode13(byte *Data,uint Count);
void Decode13(byte *Data,uint Count);
void Crypt15(byte *Data,uint Count);
void UpdKeys(byte *Buf);
void Swap(byte *Ch1,byte *Ch2);
void SetOldKeys(const char *Password);
Rijndael rin;
byte SubstTable[256];
uint Key[4];
ushort OldKey[4];
byte PN1,PN2,PN3;
byte AESKey[16],AESInit[16];
static CryptKeyCacheItem Cache[4];
static int CachePos;
public:
void SetCryptKeys(SecPassword *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
void SetAV15Encryption();
void SetCmt13Encryption();
void EncryptBlock20(byte *Buf);
void DecryptBlock20(byte *Buf);
void EncryptBlock(byte *Buf,size_t Size);
void DecryptBlock(byte *Buf,size_t Size);
void Crypt(byte *Data,uint Count,int Method);
static void SetSalt(byte *Salt,int SaltSize);
};
#endif

375
src/unrar/dll.cpp Normal file
View File

@ -0,0 +1,375 @@
#include "rar.hpp"
#include "dll.hpp"
static int RarErrorToDll(RAR_EXIT ErrCode);
struct DataSet
{
CommandData Cmd;
CmdExtract Extract;
Archive Arc;
int OpenMode;
int HeaderSize;
DataSet():Arc(&Cmd) {};
};
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
{
RAROpenArchiveDataEx rx;
memset(&rx,0,sizeof(rx));
rx.ArcName=r->ArcName;
rx.OpenMode=r->OpenMode;
rx.CmtBuf=r->CmtBuf;
rx.CmtBufSize=r->CmtBufSize;
HANDLE hArc=RAROpenArchiveEx(&rx);
r->OpenResult=rx.OpenResult;
r->CmtSize=rx.CmtSize;
r->CmtState=rx.CmtState;
return(hArc);
}
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
{
DataSet *Data=NULL;
try
{
r->OpenResult=0;
Data=new DataSet;
Data->Cmd.DllError=0;
Data->OpenMode=r->OpenMode;
Data->Cmd.FileArgs->AddString("*");
char an[NM];
if (r->ArcName==NULL && r->ArcNameW!=NULL)
{
WideToChar(r->ArcNameW,an,NM);
r->ArcName=an;
}
Data->Cmd.AddArcName(r->ArcName,r->ArcNameW);
Data->Cmd.Overwrite=OVERWRITE_ALL;
Data->Cmd.VersionControl=1;
Data->Cmd.Callback=r->Callback;
Data->Cmd.UserData=r->UserData;
if (!Data->Arc.Open(r->ArcName,r->ArcNameW,0))
{
r->OpenResult=ERAR_EOPEN;
delete Data;
return(NULL);
}
if (!Data->Arc.IsArchive(false))
{
r->OpenResult=Data->Cmd.DllError!=0 ? Data->Cmd.DllError:ERAR_BAD_ARCHIVE;
delete Data;
return(NULL);
}
r->Flags=Data->Arc.NewMhd.Flags;
Array<byte> CmtData;
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
{
r->Flags|=2;
size_t Size=CmtData.Size()+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);
if (Size<=r->CmtBufSize)
r->CmtBuf[r->CmtSize-1]=0;
}
else
r->CmtState=r->CmtSize=0;
if (Data->Arc.Signed)
r->Flags|=0x20;
Data->Extract.ExtractArchiveInit(&Data->Cmd,Data->Arc);
return((HANDLE)Data);
}
catch (RAR_EXIT ErrCode)
{
if (Data!=NULL && Data->Cmd.DllError!=0)
r->OpenResult=Data->Cmd.DllError;
else
r->OpenResult=RarErrorToDll(ErrCode);
if (Data != NULL)
delete Data;
return(NULL);
}
catch (std::bad_alloc) // Catch 'new' exception.
{
r->OpenResult=ERAR_NO_MEMORY;
if (Data != NULL)
delete Data;
}
}
int PASCAL RARCloseArchive(HANDLE hArcData)
{
DataSet *Data=(DataSet *)hArcData;
bool Success=Data==NULL ? false:Data->Arc.Close();
delete Data;
return(Success ? 0:ERAR_ECLOSE);
}
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
{
struct RARHeaderDataEx X;
memset(&X,0,sizeof(X));
int Code=RARReadHeaderEx(hArcData,&X);
strncpyz(D->ArcName,X.ArcName,ASIZE(D->ArcName));
strncpyz(D->FileName,X.FileName,ASIZE(D->FileName));
D->Flags=X.Flags;
D->PackSize=X.PackSize;
D->UnpSize=X.UnpSize;
D->HostOS=X.HostOS;
D->FileCRC=X.FileCRC;
D->FileTime=X.FileTime;
D->UnpVer=X.UnpVer;
D->Method=X.Method;
D->FileAttr=X.FileAttr;
D->CmtSize=0;
D->CmtState=0;
return Code;
}
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
{
DataSet *Data=(DataSet *)hArcData;
try
{
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
{
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Extract.SignatureFound=false;
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return(RARReadHeaderEx(hArcData,D));
}
else
return(ERAR_EOPEN);
return(Data->Arc.BrokenFileHeader ? ERAR_BAD_DATA:ERAR_END_ARCHIVE);
}
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)!=0)
{
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
if (Code==0)
return(RARReadHeaderEx(hArcData,D));
else
return(Code);
}
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
if (*Data->Arc.FileNameW)
wcsncpy(D->ArcNameW,Data->Arc.FileNameW,ASIZE(D->ArcNameW));
else
CharToWide(Data->Arc.FileName,D->ArcNameW);
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
if (*Data->Arc.NewLhd.FileNameW)
wcsncpy(D->FileNameW,Data->Arc.NewLhd.FileNameW,ASIZE(D->FileNameW));
else
{
#ifdef _WIN_ALL
char AnsiName[NM];
OemToCharA(Data->Arc.NewLhd.FileName,AnsiName);
if (!CharToWide(AnsiName,D->FileNameW,ASIZE(D->FileNameW)))
*D->FileNameW=0;
#else
if (!CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW,ASIZE(D->FileNameW)))
*D->FileNameW=0;
#endif
}
D->Flags=Data->Arc.NewLhd.Flags;
D->PackSize=Data->Arc.NewLhd.PackSize;
D->PackSizeHigh=Data->Arc.NewLhd.HighPackSize;
D->UnpSize=Data->Arc.NewLhd.UnpSize;
D->UnpSizeHigh=Data->Arc.NewLhd.HighUnpSize;
D->HostOS=Data->Arc.NewLhd.HostOS;
D->FileCRC=Data->Arc.NewLhd.FileCRC;
D->FileTime=Data->Arc.NewLhd.FileTime;
D->UnpVer=Data->Arc.NewLhd.UnpVer;
D->Method=Data->Arc.NewLhd.Method;
D->FileAttr=Data->Arc.NewLhd.FileAttr;
D->CmtSize=0;
D->CmtState=0;
}
catch (RAR_EXIT ErrCode)
{
return(Data->Cmd.DllError!=0 ? Data->Cmd.DllError:RarErrorToDll(ErrCode));
}
return(0);
}
int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
{
DataSet *Data=(DataSet *)hArcData;
try
{
Data->Cmd.DllError=0;
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
Operation==RAR_SKIP && !Data->Arc.Solid)
{
if (Data->Arc.Volume &&
Data->Arc.GetHeaderType()==FILE_HEAD &&
(Data->Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0)
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Extract.SignatureFound=false;
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return(0);
}
else
return(ERAR_EOPEN);
Data->Arc.SeekToNext();
}
else
{
Data->Cmd.DllOpMode=Operation;
if (DestPath!=NULL || DestName!=NULL)
{
#ifdef _WIN_ALL
OemToCharA(NullToEmpty(DestPath),Data->Cmd.ExtrPath);
#else
strcpy(Data->Cmd.ExtrPath,NullToEmpty(DestPath));
#endif
AddEndSlash(Data->Cmd.ExtrPath);
#ifdef _WIN_ALL
OemToCharA(NullToEmpty(DestName),Data->Cmd.DllDestName);
#else
strcpy(Data->Cmd.DllDestName,NullToEmpty(DestName));
#endif
}
else
{
*Data->Cmd.ExtrPath=0;
*Data->Cmd.DllDestName=0;
}
if (DestPathW!=NULL || DestNameW!=NULL)
{
wcsncpy(Data->Cmd.ExtrPathW,NullToEmpty(DestPathW),NM-2);
AddEndSlash(Data->Cmd.ExtrPathW);
wcsncpy(Data->Cmd.DllDestNameW,NullToEmpty(DestNameW),NM-1);
if (*Data->Cmd.DllDestNameW!=0 && *Data->Cmd.DllDestName==0)
WideToChar(Data->Cmd.DllDestNameW,Data->Cmd.DllDestName);
}
else
{
*Data->Cmd.ExtrPathW=0;
*Data->Cmd.DllDestNameW=0;
}
strcpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? "X":"T");
Data->Cmd.Test=Operation!=RAR_EXTRACT;
bool Repeat=false;
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
// Now we process extra file information if any.
//
// Archive can be closed if we process volumes, next volume is missing
// and current one is already removed or deleted. So we need to check
// if archive is still open to avoid calling file operations on
// the invalid file handle. Some of our file operations like Seek()
// process such invalid handle correctly, some not.
while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 &&
Data->Arc.GetHeaderType()==NEWSUB_HEAD)
{
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
Data->Arc.SeekToNext();
}
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
}
}
catch (RAR_EXIT ErrCode)
{
return(Data->Cmd.DllError!=0 ? Data->Cmd.DllError:RarErrorToDll(ErrCode));
}
return(Data->Cmd.DllError);
}
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
{
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL));
}
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
{
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName));
}
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.ChangeVolProc=ChangeVolProc;
}
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.Callback=Callback;
Data->Cmd.UserData=UserData;
}
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.ProcessDataProc=ProcessDataProc;
}
#ifndef RAR_NOCRYPT
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
{
DataSet *Data=(DataSet *)hArcData;
wchar PasswordW[MAXPASSWORD];
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
Data->Cmd.Password.Set(PasswordW);
cleandata(PasswordW,sizeof(PasswordW));
}
#endif
int PASCAL RARGetDllVersion()
{
return(RAR_DLL_VERSION);
}
static int RarErrorToDll(RAR_EXIT ErrCode)
{
switch(ErrCode)
{
case RARX_FATAL:
return(ERAR_EREAD);
case RARX_CRC:
return(ERAR_BAD_DATA);
case RARX_WRITE:
return(ERAR_EWRITE);
case RARX_OPEN:
return(ERAR_EOPEN);
case RARX_CREATE:
return(ERAR_ECREATE);
case RARX_MEMORY:
return(ERAR_NO_MEMORY);
case RARX_SUCCESS:
return(0);
default:
return(ERAR_UNKNOWN);
}
}

12
src/unrar/dll.def Normal file
View File

@ -0,0 +1,12 @@
EXPORTS
RAROpenArchive
RAROpenArchiveEx
RARCloseArchive
RARReadHeader
RARReadHeaderEx
RARProcessFile
RARSetCallback
RARSetChangeVolProc
RARSetProcessDataProc
RARSetPassword
RARGetDllVersion

147
src/unrar/dll.hpp Normal file
View File

@ -0,0 +1,147 @@
#ifndef _UNRAR_DLL_
#define _UNRAR_DLL_
#pragma pack(1)
#define ERAR_END_ARCHIVE 10
#define ERAR_NO_MEMORY 11
#define ERAR_BAD_DATA 12
#define ERAR_BAD_ARCHIVE 13
#define ERAR_UNKNOWN_FORMAT 14
#define ERAR_EOPEN 15
#define ERAR_ECREATE 16
#define ERAR_ECLOSE 17
#define ERAR_EREAD 18
#define ERAR_EWRITE 19
#define ERAR_SMALL_BUF 20
#define ERAR_UNKNOWN 21
#define ERAR_MISSING_PASSWORD 22
#define RAR_OM_LIST 0
#define RAR_OM_EXTRACT 1
#define RAR_OM_LIST_INCSPLIT 2
#define RAR_SKIP 0
#define RAR_TEST 1
#define RAR_EXTRACT 2
#define RAR_VOL_ASK 0
#define RAR_VOL_NOTIFY 1
#define RAR_DLL_VERSION 5
#ifdef _UNIX
#define CALLBACK
#define PASCAL
#define LONG long
#define HANDLE void *
#define LPARAM long
#define UINT unsigned int
#endif
struct RARHeaderData
{
char ArcName[260];
char FileName[260];
unsigned int Flags;
unsigned int PackSize;
unsigned int UnpSize;
unsigned int HostOS;
unsigned int FileCRC;
unsigned int FileTime;
unsigned int UnpVer;
unsigned int Method;
unsigned int FileAttr;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
};
struct RARHeaderDataEx
{
char ArcName[1024];
wchar_t ArcNameW[1024];
char FileName[1024];
wchar_t FileNameW[1024];
unsigned int Flags;
unsigned int PackSize;
unsigned int PackSizeHigh;
unsigned int UnpSize;
unsigned int UnpSizeHigh;
unsigned int HostOS;
unsigned int FileCRC;
unsigned int FileTime;
unsigned int UnpVer;
unsigned int Method;
unsigned int FileAttr;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int Reserved[1024];
};
struct RAROpenArchiveData
{
char *ArcName;
unsigned int OpenMode;
unsigned int OpenResult;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
};
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
struct RAROpenArchiveDataEx
{
char *ArcName;
wchar_t *ArcNameW;
unsigned int OpenMode;
unsigned int OpenResult;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int Flags;
UNRARCALLBACK Callback;
LPARAM UserData;
unsigned int Reserved[28];
};
enum UNRARCALLBACK_MESSAGES {
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD,UCM_CHANGEVOLUMEW,
UCM_NEEDPASSWORDW
};
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
#ifdef __cplusplus
extern "C" {
#endif
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData);
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData);
int PASCAL RARCloseArchive(HANDLE hArcData);
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName);
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
void PASCAL RARSetPassword(HANDLE hArcData,char *Password);
int PASCAL RARGetDllVersion();
#ifdef __cplusplus
}
#endif
#pragma pack()
#endif

28
src/unrar/dll.rc Normal file
View File

@ -0,0 +1,28 @@
#include <windows.h>
#include <commctrl.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4, 20, 100, 526
PRODUCTVERSION 4, 20, 100, 526
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "CompanyName", "Alexander Roshal\0"
VALUE "ProductName", "RAR decompression library\0"
VALUE "FileDescription", "RAR decompression library\0"
VALUE "FileVersion", "4.20.0\0"
VALUE "ProductVersion", "4.20.0\0"
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2012\0"
VALUE "OriginalFilename", "Unrar.dll\0"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0, 0
}
}

57
src/unrar/encname.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "rar.hpp"
EncodeFileName::EncodeFileName()
{
Flags=0;
FlagBits=0;
FlagsPos=0;
DestSize=0;
}
void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,
size_t MaxDecSize)
{
size_t EncPos=0,DecPos=0;
byte HighByte=EncName[EncPos++];
while (EncPos<EncSize && DecPos<MaxDecSize)
{
if (FlagBits==0)
{
Flags=EncName[EncPos++];
FlagBits=8;
}
switch(Flags>>6)
{
case 0:
NameW[DecPos++]=EncName[EncPos++];
break;
case 1:
NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8);
break;
case 2:
NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8);
EncPos+=2;
break;
case 3:
{
int Length=EncName[EncPos++];
if (Length & 0x80)
{
byte Correction=EncName[EncPos++];
for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
NameW[DecPos]=((Name[DecPos]+Correction)&0xff)+(HighByte<<8);
}
else
for (Length+=2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
NameW[DecPos]=Name[DecPos];
}
break;
}
Flags<<=2;
FlagBits-=2;
}
NameW[DecPos<MaxDecSize ? DecPos:MaxDecSize-1]=0;
}

20
src/unrar/encname.hpp Normal file
View File

@ -0,0 +1,20 @@
#ifndef _RAR_ENCNAME_
#define _RAR_ENCNAME_
class EncodeFileName
{
private:
void AddFlags(int Value);
byte *EncName;
byte Flags;
uint FlagBits;
size_t FlagsPos;
size_t DestSize;
public:
EncodeFileName();
size_t Encode(char *Name,wchar *NameW,byte *EncName);
void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
};
#endif

405
src/unrar/errhnd.cpp Normal file
View File

@ -0,0 +1,405 @@
#include "rar.hpp"
static bool UserBreak;
ErrorHandler::ErrorHandler()
{
Clean();
}
void ErrorHandler::Clean()
{
ExitCode=RARX_SUCCESS;
ErrCount=0;
EnableBreak=true;
Silent=false;
DoShutdown=false;
}
void ErrorHandler::MemoryError()
{
MemoryErrorMsg();
Throw(RARX_MEMORY);
}
void ErrorHandler::OpenError(const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
OpenErrorMsg(FileName);
Throw(RARX_OPEN);
#endif
}
void ErrorHandler::CloseError(const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
if (!UserBreak)
{
ErrMsg(NULL,St(MErrFClose),FileName);
SysErrMsg();
}
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RARX_FATAL);
#endif
}
void ErrorHandler::ReadError(const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
ReadErrorMsg(NULL,NULL,FileName,FileNameW);
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RARX_FATAL);
#endif
}
bool ErrorHandler::AskRepeatRead(const char *FileName,const wchar *FileNameW)
{
#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE)
if (!Silent)
{
SysErrMsg();
mprintf("\n");
Log(NULL,St(MErrRead),FileName);
return(Ask(St(MRetryAbort))==1);
}
#endif
return(false);
}
void ErrorHandler::WriteError(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
WriteErrorMsg(ArcName,ArcNameW,FileName,FileNameW);
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RARX_WRITE);
#endif
}
#ifdef _WIN_ALL
void ErrorHandler::WriteErrorFAT(const char *FileName,const wchar *FileNameW)
{
#if !defined(SILENT) && !defined(SFX_MODULE)
SysErrMsg();
ErrMsg(NULL,St(MNTFSRequired),FileName);
#endif
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
Throw(RARX_WRITE);
#endif
}
#endif
bool ErrorHandler::AskRepeatWrite(const char *FileName,const wchar *FileNameW,bool DiskFull)
{
#if !defined(SILENT) && !defined(_WIN_CE)
if (!Silent)
{
SysErrMsg();
mprintf("\n");
Log(NULL,St(DiskFull ? MNotEnoughDisk:MErrWrite),FileName);
return(Ask(St(MRetryAbort))==1);
}
#endif
return(false);
}
void ErrorHandler::SeekError(const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
if (!UserBreak)
{
ErrMsg(NULL,St(MErrSeek),FileName);
SysErrMsg();
}
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RARX_FATAL);
#endif
}
void ErrorHandler::GeneralErrMsg(const char *Msg)
{
#ifndef SILENT
Log(NULL,"%s",Msg);
SysErrMsg();
#endif
}
void ErrorHandler::MemoryErrorMsg()
{
#ifndef SILENT
ErrMsg(NULL,St(MErrOutMem));
#endif
}
void ErrorHandler::OpenErrorMsg(const char *FileName,const wchar *FileNameW)
{
OpenErrorMsg(NULL,NULL,FileName,FileNameW);
}
void ErrorHandler::OpenErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
if (FileName!=NULL)
Log(ArcName,St(MCannotOpen),FileName);
Alarm();
SysErrMsg();
#endif
}
void ErrorHandler::CreateErrorMsg(const char *FileName,const wchar *FileNameW)
{
CreateErrorMsg(NULL,NULL,FileName,FileNameW);
}
void ErrorHandler::CreateErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
if (FileName!=NULL)
Log(ArcName,St(MCannotCreate),FileName);
Alarm();
#if defined(_WIN_ALL) && !defined(_WIN_CE) && defined(MAX_PATH)
CheckLongPathErrMsg(FileName,FileNameW);
#endif
SysErrMsg();
#endif
}
// Check the path length and display the error message if it is too long.
void ErrorHandler::CheckLongPathErrMsg(const char *FileName,const wchar *FileNameW)
{
#if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined (SILENT) && defined(MAX_PATH)
if (GetLastError()==ERROR_PATH_NOT_FOUND)
{
wchar WideFileName[NM];
GetWideName(FileName,FileNameW,WideFileName,ASIZE(WideFileName));
size_t NameLength=wcslen(WideFileName);
if (!IsFullPath(WideFileName))
{
wchar CurDir[NM];
GetCurrentDirectoryW(ASIZE(CurDir),CurDir);
NameLength+=wcslen(CurDir)+1;
}
if (NameLength>MAX_PATH)
{
Log(NULL,St(MMaxPathLimit),MAX_PATH);
}
}
#endif
}
void ErrorHandler::ReadErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
ErrMsg(ArcName,St(MErrRead),FileName);
SysErrMsg();
#endif
}
void ErrorHandler::WriteErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
{
#ifndef SILENT
ErrMsg(ArcName,St(MErrWrite),FileName);
SysErrMsg();
#endif
}
void ErrorHandler::Exit(RAR_EXIT ExitCode)
{
#ifndef SFX_MODULE
Alarm();
#endif
Throw(ExitCode);
}
#ifndef GUI
void ErrorHandler::ErrMsg(const char *ArcName,const char *fmt,...)
{
safebuf char Msg[NM+1024];
va_list argptr;
va_start(argptr,fmt);
vsprintf(Msg,fmt,argptr);
va_end(argptr);
#ifdef _WIN_ALL
if (UserBreak)
Sleep(5000);
#endif
Alarm();
if (*Msg)
{
Log(ArcName,"\n%s",Msg);
mprintf("\n%s\n",St(MProgAborted));
}
}
#endif
void ErrorHandler::SetErrorCode(RAR_EXIT Code)
{
switch(Code)
{
case RARX_WARNING:
case RARX_USERBREAK:
if (ExitCode==RARX_SUCCESS)
ExitCode=Code;
break;
case RARX_FATAL:
if (ExitCode==RARX_SUCCESS || ExitCode==RARX_WARNING)
ExitCode=RARX_FATAL;
break;
default:
ExitCode=Code;
break;
}
ErrCount++;
}
#if !defined(GUI) && !defined(_SFX_RTL_)
#ifdef _WIN_ALL
BOOL __stdcall ProcessSignal(DWORD SigType)
#else
#if defined(__sun)
extern "C"
#endif
void _stdfunction ProcessSignal(int SigType)
#endif
{
#ifdef _WIN_ALL
// When a console application is run as a service, this allows the service
// to continue running after the user logs off.
if (SigType==CTRL_LOGOFF_EVENT)
return(TRUE);
#endif
UserBreak=true;
mprintf(St(MBreak));
for (int I=0;!File::RemoveCreated() && I<3;I++)
{
#ifdef _WIN_ALL
Sleep(100);
#endif
}
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE) && !defined(RARDLL)
ExtRes.UnloadDLL();
#endif
exit(RARX_USERBREAK);
#if defined(_WIN_ALL) && !defined(_MSC_VER)
// never reached, just to avoid a compiler warning
return(TRUE);
#endif
}
#endif
void ErrorHandler::SetSignalHandlers(bool Enable)
{
EnableBreak=Enable;
#if !defined(GUI) && !defined(_SFX_RTL_)
#ifdef _WIN_ALL
SetConsoleCtrlHandler(Enable ? ProcessSignal:NULL,TRUE);
// signal(SIGBREAK,Enable ? ProcessSignal:SIG_IGN);
#else
signal(SIGINT,Enable ? ProcessSignal:SIG_IGN);
signal(SIGTERM,Enable ? ProcessSignal:SIG_IGN);
#endif
#endif
}
void ErrorHandler::Throw(RAR_EXIT Code)
{
if (Code==RARX_USERBREAK && !EnableBreak)
return;
ErrHandler.SetErrorCode(Code);
#ifdef ALLOW_EXCEPTIONS
throw Code;
#else
File::RemoveCreated();
exit(Code);
#endif
}
void ErrorHandler::SysErrMsg()
{
#if !defined(SFX_MODULE) && !defined(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++;
}
// We use ASCII for output in Windows console, so let's convert Unicode
// message to single byte.
size_t Length=wcslen(CurMsg)*2; // Must be enough for DBCS characters.
char *MsgA=(char *)malloc(Length+2);
if (MsgA!=NULL)
{
WideToChar(CurMsg,MsgA,Length+1);
MsgA[Length]=0;
Log(NULL,"\n%s",MsgA);
free(MsgA);
}
CurMsg=EndMsg;
}
}
LocalFree( lpMsgBuf );
#endif
#if defined(_UNIX) || defined(_EMX)
if (errno!=0)
{
char *err=strerror(errno);
if (err!=NULL)
Log(NULL,"\n%s",err);
}
#endif
#endif
}

67
src/unrar/errhnd.hpp Normal file
View File

@ -0,0 +1,67 @@
#ifndef _RAR_ERRHANDLER_
#define _RAR_ERRHANDLER_
#ifndef SFX_MODULE
#define ALLOW_EXCEPTIONS
#endif
enum RAR_EXIT // RAR exit code.
{
RARX_SUCCESS = 0,
RARX_WARNING = 1,
RARX_FATAL = 2,
RARX_CRC = 3,
RARX_LOCK = 4,
RARX_WRITE = 5,
RARX_OPEN = 6,
RARX_USERERROR = 7,
RARX_MEMORY = 8,
RARX_CREATE = 9,
RARX_NOFILES = 10,
RARX_USERBREAK = 255
};
class ErrorHandler
{
private:
void ErrMsg(const char *ArcName,const char *fmt,...);
RAR_EXIT ExitCode;
int ErrCount;
bool EnableBreak;
bool Silent;
bool DoShutdown;
public:
ErrorHandler();
void Clean();
void MemoryError();
void OpenError(const char *FileName,const wchar *FileNameW);
void CloseError(const char *FileName,const wchar *FileNameW);
void ReadError(const char *FileName,const wchar *FileNameW);
bool AskRepeatRead(const char *FileName,const wchar *FileNameW);
void WriteError(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
void WriteErrorFAT(const char *FileName,const wchar *FileNameW);
bool AskRepeatWrite(const char *FileName,const wchar *FileNameW,bool DiskFull);
void SeekError(const char *FileName,const wchar *FileNameW);
void GeneralErrMsg(const char *Msg);
void MemoryErrorMsg();
void OpenErrorMsg(const char *FileName,const wchar *FileNameW=NULL);
void OpenErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
void CreateErrorMsg(const char *FileName,const wchar *FileNameW=NULL);
void CreateErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
void CheckLongPathErrMsg(const char *FileName,const wchar *FileNameW);
void ReadErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
void WriteErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
void Exit(RAR_EXIT ExitCode);
void SetErrorCode(RAR_EXIT Code);
RAR_EXIT GetErrorCode() {return(ExitCode);}
int GetErrorCount() {return(ErrCount);}
void SetSignalHandlers(bool Enable);
void Throw(RAR_EXIT Code);
void SetSilent(bool Mode) {Silent=Mode;};
void SetShutdown(bool Mode) {DoShutdown=Mode;};
void SysErrMsg();
};
#endif

76
src/unrar/extinfo.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "rar.hpp"
#ifdef _WIN_ALL
#include "win32acl.cpp"
#include "win32stm.cpp"
#endif
#ifdef _BEOS
#include "beosea.cpp"
#endif
#if defined(_EMX) && !defined(_DJGPP)
#include "os2ea.cpp"
#endif
#ifdef _UNIX
#include "uowners.cpp"
#endif
#ifndef SFX_MODULE
void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW)
{
switch(Arc.SubBlockHead.SubType)
{
#if defined(_EMX) && !defined(_DJGPP)
case EA_HEAD:
if (Cmd->ProcessEA)
ExtractOS2EA(Arc,Name);
break;
#endif
#ifdef _UNIX
case UO_HEAD:
if (Cmd->ProcessOwners)
ExtractUnixOwner(Arc,Name);
break;
#endif
#ifdef _BEOS
case BEEA_HEAD:
if (Cmd->ProcessEA)
ExtractBeEA(Arc,Name);
break;
#endif
#ifdef _WIN_ALL
case NTACL_HEAD:
if (Cmd->ProcessOwners)
ExtractACL(Arc,Name,NameW);
break;
case STREAM_HEAD:
ExtractStreams(Arc,Name,NameW);
break;
#endif
}
}
#endif
void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW)
{
#if defined(_EMX) && !defined(_DJGPP)
if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_OS2EA))
ExtractOS2EANew(Arc,Name);
#endif
#ifdef _UNIX
if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
ExtractUnixOwnerNew(Arc,Name);
#endif
#ifdef _BEOS
if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
ExtractUnixOwnerNew(Arc,Name);
#endif
#ifdef _WIN_ALL
if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
ExtractACLNew(Arc,Name,NameW);
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
ExtractStreamsNew(Arc,Name,NameW);
#endif
}

8
src/unrar/extinfo.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef _RAR_EXTINFO_
#define _RAR_EXTINFO_
void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW);
void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW);
#endif

1026
src/unrar/extract.cpp Normal file

File diff suppressed because it is too large Load Diff

49
src/unrar/extract.hpp Normal file
View File

@ -0,0 +1,49 @@
#ifndef _RAR_EXTRACT_
#define _RAR_EXTRACT_
enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
class CmdExtract
{
private:
EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
RarTime StartTime; // time when extraction started
ComprDataIO DataIO;
Unpack *Unp;
unsigned long TotalFileCount;
unsigned long FileCount;
unsigned long MatchedArgs;
bool FirstFile;
bool AllMatchesExact;
bool ReconstructDone;
// If any non-zero solid file was successfully unpacked before current.
// If true and if current encrypted file is broken, obviously
// the password is correct and we can report broken CRC without
// any wrong password hints.
bool AnySolidDataUnpackedWell;
char ArcName[NM];
wchar ArcNameW[NM];
SecPassword Password;
bool PasswordAll;
bool PrevExtracted;
char DestFileName[NM];
wchar DestFileNameW[NM];
bool PasswordCancelled;
public:
CmdExtract();
~CmdExtract();
void DoExtract(CommandData *Cmd);
void ExtractArchiveInit(CommandData *Cmd,Archive &Arc);
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,
bool &Repeat);
static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize);
bool SignatureFound;
};
#endif

260
src/unrar/filcreat.cpp Normal file
View File

@ -0,0 +1,260 @@
#include "rar.hpp"
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize,
uint FileTime,bool WriteOnly)
{
if (UserReject!=NULL)
*UserReject=false;
#if defined(_WIN_ALL) && !defined(_WIN_CE)
bool ShortNameChanged=false;
#endif
while (FileExist(Name,NameW))
{
#if defined(_WIN_ALL) && !defined(_WIN_CE)
if (!ShortNameChanged)
{
// Avoid the infinite loop if UpdateExistingShortName returns
// the same name.
ShortNameChanged=true;
// Maybe our long name matches the short name of existing file.
// Let's check if we can change the short name.
wchar WideName[NM];
GetWideName(Name,NameW,WideName,ASIZE(WideName));
if (UpdateExistingShortName(WideName))
{
if (Name!=NULL && *Name!=0)
WideToChar(WideName,Name);
if (NameW!=NULL && *NameW!=0)
wcscpy(NameW,WideName);
continue;
}
}
// Allow short name check again. It is necessary, because rename and
// autorename below can change the name, so we need to check it again.
ShortNameChanged=false;
#endif
if (Mode==OVERWRITE_NONE)
{
if (UserReject!=NULL)
*UserReject=true;
return(false);
}
// Must be before Cmd->AllYes check or -y switch would override -or.
if (Mode==OVERWRITE_AUTORENAME)
{
if (!GetAutoRenamedName(Name,NameW))
Mode=OVERWRITE_DEFAULT;
continue;
}
#ifdef SILENT
Mode=OVERWRITE_ALL;
#endif
// This check must be after OVERWRITE_AUTORENAME processing or -y switch
// would override -or.
if (Cmd->AllYes || Mode==OVERWRITE_ALL)
break;
if (Mode==OVERWRITE_DEFAULT || Mode==OVERWRITE_FORCE_ASK)
{
char NewName[NM];
wchar NewNameW[NM];
*NewNameW=0;
eprintf(St(MFileExists),Name);
int Choice=Ask(St(MYesNoAllRenQ));
if (Choice==1)
break;
if (Choice==2)
{
if (UserReject!=NULL)
*UserReject=true;
return(false);
}
if (Choice==3)
{
Cmd->Overwrite=OVERWRITE_ALL;
break;
}
if (Choice==4)
{
if (UserReject!=NULL)
*UserReject=true;
Cmd->Overwrite=OVERWRITE_NONE;
return(false);
}
if (Choice==5)
{
#ifndef GUI
mprintf(St(MAskNewName));
#ifdef _WIN_ALL
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
int Size=SrcFile.Read(NewName,sizeof(NewName)-1);
NewName[Size]=0;
OemToCharA(NewName,NewName);
#else
if (fgets(NewName,sizeof(NewName),stdin)==NULL)
{
// Process fgets failure as if user answered 'No'.
if (UserReject!=NULL)
*UserReject=true;
return(false);
}
#endif
RemoveLF(NewName);
#endif
if (PointToName(NewName)==NewName)
strcpy(PointToName(Name),NewName);
else
strcpy(Name,NewName);
if (NameW!=NULL)
if (PointToName(NewNameW)==NewNameW)
wcscpy(PointToName(NameW),NewNameW);
else
wcscpy(NameW,NewNameW);
continue;
}
if (Choice==6)
ErrHandler.Exit(RARX_USERBREAK);
}
}
uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
if (NewFile!=NULL && NewFile->Create(Name,NameW,FileMode))
return(true);
PrepareToDelete(Name,NameW);
CreatePath(Name,NameW,true);
return(NewFile!=NULL ? NewFile->Create(Name,NameW,FileMode):DelFile(Name,NameW));
}
bool GetAutoRenamedName(char *Name,wchar *NameW)
{
char NewName[NM];
wchar NewNameW[NM];
if (Name!=NULL && strlen(Name)>ASIZE(NewName)-10 ||
NameW!=NULL && wcslen(NameW)>ASIZE(NewNameW)-10)
return(false);
char *Ext=NULL;
if (Name!=NULL && *Name!=0)
{
Ext=GetExt(Name);
if (Ext==NULL)
Ext=Name+strlen(Name);
}
wchar *ExtW=NULL;
if (NameW!=NULL && *NameW!=0)
{
ExtW=GetExt(NameW);
if (ExtW==NULL)
ExtW=NameW+wcslen(NameW);
}
*NewName=0;
*NewNameW=0;
for (int FileVer=1;;FileVer++)
{
if (Name!=NULL && *Name!=0)
sprintf(NewName,"%.*s(%d)%s",int(Ext-Name),Name,FileVer,Ext);
if (NameW!=NULL && *NameW!=0)
sprintfw(NewNameW,ASIZE(NewNameW),L"%.*s(%d)%s",int(ExtW-NameW),NameW,FileVer,ExtW);
if (!FileExist(NewName,NewNameW))
{
if (Name!=NULL && *Name!=0)
strcpy(Name,NewName);
if (NameW!=NULL && *NameW!=0)
wcscpy(NameW,NewNameW);
break;
}
if (FileVer>=1000000)
return(false);
}
return(true);
}
#if defined(_WIN_ALL) && !defined(_WIN_CE)
// If we find a file, which short name is equal to 'Name', we try to change
// its short name, while preserving the long name. It helps when unpacking
// an archived file, which long name is equal to short name of already
// existing file. Otherwise we would overwrite the already existing file,
// even though its long name does not match the name of unpacking file.
bool UpdateExistingShortName(wchar *Name)
{
// 'Name' is the name of file which we want to create. Let's check
// if file with such name is exist. If it does not, we return.
FindData fd;
if (!FindFile::FastFind(NULL,Name,&fd))
return(false);
// We continue only if file has a short name, which does not match its
// long name, and this short name is equal to name of file which we need
// to create.
if (*fd.ShortName==0 || wcsicomp(PointToName(fd.NameW),fd.ShortName)==0 ||
wcsicomp(PointToName(Name),fd.ShortName)!=0)
return(false);
// Generate the temporary new name for existing file.
wchar NewName[NM];
*NewName=0;
for (int I=0;I<10000 && *NewName==0;I+=123)
{
// Here we copy the path part of file to create. We'll make the temporary
// file in the same folder.
wcsncpyz(NewName,Name,ASIZE(NewName));
// Here we set the random name part.
sprintfw(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
// If such file is already exist, try next random name.
if (FileExist(NULL,NewName))
*NewName=0;
}
// If we could not generate the name not used by any other file, we return.
if (*NewName==0)
return(false);
// FastFind returns the name without path, but we need the fully qualified
// name for renaming, so we use the path from file to create and long name
// from existing file.
wchar FullName[NM];
wcsncpyz(FullName,Name,ASIZE(FullName));
wcscpy(PointToName(FullName),PointToName(fd.NameW));
// Rename the existing file to randomly generated name. Normally it changes
// the short name too.
if (!MoveFileW(FullName,NewName))
return(false);
// Now we need to create the temporary empty file with same name as
// short name of our already existing file. We do it to occupy its previous
// short name and not allow to use it again when renaming the file back to
// its original long name.
File KeepShortFile;
bool Created=false;
if (!FileExist(NULL,Name))
Created=KeepShortFile.Create(NULL,Name);
// Now we rename the existing file from temporary name to original long name.
// Since its previous short name is occupied by another file, it should
// get another short name.
MoveFileW(NewName,FullName);
if (Created)
{
// Delete the temporary zero length file occupying the short name,
KeepShortFile.Close();
KeepShortFile.Delete();
}
// We successfully changed the short name. Maybe sometimes we'll simplify
// this function by use of SetFileShortName Windows API call.
// But SetFileShortName is not available in older Windows.
return(true);
}
#endif

13
src/unrar/filcreat.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef _RAR_FILECREATE_
#define _RAR_FILECREATE_
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize=INT64NDF,
uint FileTime=0,bool WriteOnly=false);
bool GetAutoRenamedName(char *Name,wchar *NameW);
#if defined(_WIN_ALL) && !defined(_WIN_CE)
bool UpdateExistingShortName(wchar *Name);
#endif
#endif

710
src/unrar/file.cpp Normal file
View File

@ -0,0 +1,710 @@
#include "rar.hpp"
static File *CreatedFiles[256];
static int RemoveCreatedActive=0;
File::File()
{
hFile=BAD_HANDLE;
*FileName=0;
*FileNameW=0;
NewFile=false;
LastWrite=false;
HandleType=FILE_HANDLENORMAL;
SkipClose=false;
IgnoreReadErrors=false;
ErrorType=FILE_SUCCESS;
OpenShared=false;
AllowDelete=true;
CloseCount=0;
AllowExceptions=true;
#ifdef _WIN_ALL
NoSequentialRead=false;
CreateMode=FMF_UNDEFINED;
#endif
}
File::~File()
{
if (hFile!=BAD_HANDLE && !SkipClose)
if (NewFile)
Delete();
else
Close();
}
void File::operator = (File &SrcFile)
{
hFile=SrcFile.hFile;
strcpy(FileName,SrcFile.FileName);
NewFile=SrcFile.NewFile;
LastWrite=SrcFile.LastWrite;
HandleType=SrcFile.HandleType;
SrcFile.SkipClose=true;
}
bool File::Open(const char *Name,const wchar *NameW,uint Mode)
{
ErrorType=FILE_SUCCESS;
FileHandle hNewFile;
bool OpenShared=File::OpenShared || (Mode & FMF_OPENSHARED)!=0;
bool UpdateMode=(Mode & FMF_UPDATE)!=0;
bool WriteMode=(Mode & FMF_WRITE)!=0;
#ifdef _WIN_ALL
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ;
if (UpdateMode)
Access|=GENERIC_WRITE;
uint ShareMode=FILE_SHARE_READ;
if (OpenShared)
ShareMode|=FILE_SHARE_WRITE;
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
if (WinNT() && NameW!=NULL && *NameW!=0)
hNewFile=CreateFileW(NameW,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
else
hNewFile=CreateFileA(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
if (hNewFile==BAD_HANDLE && GetLastError()==ERROR_FILE_NOT_FOUND)
ErrorType=FILE_NOTFOUND;
#else
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
#ifdef O_BINARY
flags|=O_BINARY;
#if defined(_AIX) && defined(_LARGE_FILE_API)
flags|=O_LARGEFILE;
#endif
#endif
#if defined(_EMX) && !defined(_DJGPP)
int sflags=OpenShared ? SH_DENYNO:SH_DENYWR;
int handle=sopen(Name,flags,sflags);
#else
int handle=open(Name,flags);
#ifdef LOCK_EX
#ifdef _OSF_SOURCE
extern "C" int flock(int, int);
#endif
if (!OpenShared && UpdateMode && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
{
close(handle);
return(false);
}
#endif
#endif
hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
if (hNewFile==BAD_HANDLE && errno==ENOENT)
ErrorType=FILE_NOTFOUND;
#endif
NewFile=false;
HandleType=FILE_HANDLENORMAL;
SkipClose=false;
bool Success=hNewFile!=BAD_HANDLE;
if (Success)
{
hFile=hNewFile;
// We use memove instead of strcpy and wcscpy to avoid problems
// with overlapped buffers. While we do not call this function with
// really overlapped buffers yet, we do call it with Name equal to
// FileName like Arc.Open(Arc.FileName,Arc.FileNameW,...).
if (NameW!=NULL)
memmove(FileNameW,NameW,(wcslen(NameW)+1)*sizeof(*NameW));
else
*FileNameW=0;
if (Name!=NULL)
memmove(FileName,Name,strlen(Name)+1);
else
WideToChar(NameW,FileName);
AddFileToList(hFile);
}
return(Success);
}
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
void File::TOpen(const char *Name,const wchar *NameW)
{
if (!WOpen(Name,NameW))
ErrHandler.Exit(RARX_OPEN);
}
#endif
bool File::WOpen(const char *Name,const wchar *NameW)
{
if (Open(Name,NameW))
return(true);
ErrHandler.OpenErrorMsg(Name,NameW);
return(false);
}
bool File::Create(const char *Name,const wchar *NameW,uint Mode)
{
// OpenIndiana based NAS and CIFS shares fail to set the file time if file
// was created in read+write mode and some data was written and not flushed
// before SetFileTime call. So we should use the write only mode if we plan
// SetFileTime call and do not need to read from file.
bool WriteMode=(Mode & FMF_WRITE)!=0;
bool ShareRead=(Mode & FMF_SHAREREAD)!=0 || File::OpenShared;
#ifdef _WIN_ALL
CreateMode=Mode;
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ|GENERIC_WRITE;
DWORD ShareMode=ShareRead ? FILE_SHARE_READ:0;
if (WinNT() && NameW!=NULL && *NameW!=0)
hFile=CreateFileW(NameW,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
else
hFile=CreateFileA(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
#else
hFile=fopen(Name,WriteMode ? WRITEBINARY:CREATEBINARY);
#endif
NewFile=true;
HandleType=FILE_HANDLENORMAL;
SkipClose=false;
if (NameW!=NULL)
wcscpy(FileNameW,NameW);
else
*FileNameW=0;
if (Name!=NULL)
strcpy(FileName,Name);
else
WideToChar(NameW,FileName);
AddFileToList(hFile);
return(hFile!=BAD_HANDLE);
}
void File::AddFileToList(FileHandle hFile)
{
if (hFile!=BAD_HANDLE)
for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
if (CreatedFiles[I]==NULL)
{
CreatedFiles[I]=this;
break;
}
}
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
void File::TCreate(const char *Name,const wchar *NameW,uint Mode)
{
if (!WCreate(Name,NameW,Mode))
ErrHandler.Exit(RARX_FATAL);
}
#endif
bool File::WCreate(const char *Name,const wchar *NameW,uint Mode)
{
if (Create(Name,NameW,Mode))
return(true);
ErrHandler.SetErrorCode(RARX_CREATE);
ErrHandler.CreateErrorMsg(Name,NameW);
return(false);
}
bool File::Close()
{
bool Success=true;
if (HandleType!=FILE_HANDLENORMAL)
HandleType=FILE_HANDLENORMAL;
else
if (hFile!=BAD_HANDLE)
{
if (!SkipClose)
{
#ifdef _WIN_ALL
Success=CloseHandle(hFile)==TRUE;
#else
Success=fclose(hFile)!=EOF;
#endif
if (Success || !RemoveCreatedActive)
for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
if (CreatedFiles[I]==this)
{
CreatedFiles[I]=NULL;
break;
}
}
hFile=BAD_HANDLE;
if (!Success && AllowExceptions)
ErrHandler.CloseError(FileName,FileNameW);
}
CloseCount++;
return(Success);
}
void File::Flush()
{
#ifdef _WIN_ALL
FlushFileBuffers(hFile);
#else
fflush(hFile);
#endif
}
bool File::Delete()
{
if (HandleType!=FILE_HANDLENORMAL)
return(false);
if (hFile!=BAD_HANDLE)
Close();
if (!AllowDelete)
return(false);
return(DelFile(FileName,FileNameW));
}
bool File::Rename(const char *NewName,const wchar *NewNameW)
{
// we do not need to rename if names are already same
bool Success=strcmp(FileName,NewName)==0;
if (Success && *FileNameW!=0 && *NullToEmpty(NewNameW)!=0)
Success=wcscmp(FileNameW,NewNameW)==0;
if (!Success)
Success=RenameFile(FileName,FileNameW,NewName,NewNameW);
if (Success)
{
// renamed successfully, storing the new name
strcpy(FileName,NewName);
wcscpy(FileNameW,NullToEmpty(NewNameW));
}
return(Success);
}
void File::Write(const void *Data,size_t Size)
{
if (Size==0)
return;
#ifndef _WIN_CE
if (HandleType!=FILE_HANDLENORMAL)
switch(HandleType)
{
case FILE_HANDLESTD:
#ifdef _WIN_ALL
hFile=GetStdHandle(STD_OUTPUT_HANDLE);
#else
hFile=stdout;
#endif
break;
case FILE_HANDLEERR:
#ifdef _WIN_ALL
hFile=GetStdHandle(STD_ERROR_HANDLE);
#else
hFile=stderr;
#endif
break;
}
#endif
while (1)
{
bool Success=false;
#ifdef _WIN_ALL
DWORD Written=0;
if (HandleType!=FILE_HANDLENORMAL)
{
// writing to stdout can fail in old Windows if data block is too large
const size_t MaxSize=0x4000;
for (size_t I=0;I<Size;I+=MaxSize)
{
Success=WriteFile(hFile,(byte *)Data+I,(DWORD)Min(Size-I,MaxSize),&Written,NULL)==TRUE;
if (!Success)
break;
}
}
else
Success=WriteFile(hFile,Data,(DWORD)Size,&Written,NULL)==TRUE;
#else
int Written=fwrite(Data,1,Size,hFile);
Success=Written==Size && !ferror(hFile);
#endif
if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
{
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(RARDLL)
int ErrCode=GetLastError();
int64 FilePos=Tell();
uint64 FreeSize=GetFreeDisk(FileName);
SetLastError(ErrCode);
if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
ErrHandler.WriteErrorFAT(FileName,FileNameW);
#endif
if (ErrHandler.AskRepeatWrite(FileName,FileNameW,false))
{
#ifndef _WIN_ALL
clearerr(hFile);
#endif
if (Written<Size && Written>0)
Seek(Tell()-Written,SEEK_SET);
continue;
}
ErrHandler.WriteError(NULL,NULL,FileName,FileNameW);
}
break;
}
LastWrite=true;
}
int File::Read(void *Data,size_t Size)
{
int64 FilePos=0; // Initialized only to suppress some compilers warning.
if (IgnoreReadErrors)
FilePos=Tell();
int ReadSize;
while (true)
{
ReadSize=DirectRead(Data,Size);
if (ReadSize==-1)
{
ErrorType=FILE_READERROR;
if (AllowExceptions)
if (IgnoreReadErrors)
{
ReadSize=0;
for (size_t I=0;I<Size;I+=512)
{
Seek(FilePos+I,SEEK_SET);
size_t SizeToRead=Min(Size-I,512);
int ReadCode=DirectRead(Data,SizeToRead);
ReadSize+=(ReadCode==-1) ? 512:ReadCode;
}
}
else
{
if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName,FileNameW))
continue;
ErrHandler.ReadError(FileName,FileNameW);
}
}
break;
}
return(ReadSize);
}
// Returns -1 in case of error.
int File::DirectRead(void *Data,size_t Size)
{
#ifdef _WIN_ALL
const size_t MaxDeviceRead=20000;
#endif
#ifndef _WIN_CE
if (HandleType==FILE_HANDLESTD)
{
#ifdef _WIN_ALL
if (Size>MaxDeviceRead)
Size=MaxDeviceRead;
hFile=GetStdHandle(STD_INPUT_HANDLE);
#else
hFile=stdin;
#endif
}
#endif
#ifdef _WIN_ALL
DWORD Read;
if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
{
if (IsDevice() && Size>MaxDeviceRead)
return(DirectRead(Data,MaxDeviceRead));
if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE)
return(0);
return(-1);
}
return(Read);
#else
if (LastWrite)
{
fflush(hFile);
LastWrite=false;
}
clearerr(hFile);
size_t ReadSize=fread(Data,1,Size,hFile);
if (ferror(hFile))
return(-1);
return((int)ReadSize);
#endif
}
void File::Seek(int64 Offset,int Method)
{
if (!RawSeek(Offset,Method) && AllowExceptions)
ErrHandler.SeekError(FileName,FileNameW);
}
bool File::RawSeek(int64 Offset,int Method)
{
if (hFile==BAD_HANDLE)
return(true);
if (Offset<0 && Method!=SEEK_SET)
{
Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
Method=SEEK_SET;
}
#ifdef _WIN_ALL
LONG HighDist=(LONG)(Offset>>32);
if (SetFilePointer(hFile,(LONG)Offset,&HighDist,Method)==0xffffffff &&
GetLastError()!=NO_ERROR)
return(false);
#else
LastWrite=false;
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
if (fseeko(hFile,Offset,Method)!=0)
#else
if (fseek(hFile,(long)Offset,Method)!=0)
#endif
return(false);
#endif
return(true);
}
int64 File::Tell()
{
if (hFile==BAD_HANDLE)
if (AllowExceptions)
ErrHandler.SeekError(FileName,FileNameW);
else
return(-1);
#ifdef _WIN_ALL
LONG HighDist=0;
uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
if (LowDist==0xffffffff && GetLastError()!=NO_ERROR)
if (AllowExceptions)
ErrHandler.SeekError(FileName,FileNameW);
else
return(-1);
return(INT32TO64(HighDist,LowDist));
#else
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
return(ftello(hFile));
#else
return(ftell(hFile));
#endif
#endif
}
void File::Prealloc(int64 Size)
{
#ifdef _WIN_ALL
if (RawSeek(Size,SEEK_SET))
{
Truncate();
Seek(0,SEEK_SET);
}
#endif
#if defined(_UNIX) && defined(USE_FALLOCATE)
// fallocate is rather new call. Only latest kernels support it.
// So we are not using it by default yet.
int fd = fileno(hFile);
if (fd >= 0)
fallocate(fd, 0, 0, Size);
#endif
}
byte File::GetByte()
{
byte Byte=0;
Read(&Byte,1);
return(Byte);
}
void File::PutByte(byte Byte)
{
Write(&Byte,1);
}
bool File::Truncate()
{
#ifdef _WIN_ALL
return(SetEndOfFile(hFile)==TRUE);
#else
return(false);
#endif
}
void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
{
#ifdef _WIN_ALL
// Workaround for OpenIndiana NAS time bug. If we cannot create a file
// in write only mode, we need to flush the write buffer before calling
// SetFileTime or file time will not be changed.
if (CreateMode!=FMF_UNDEFINED && (CreateMode & FMF_WRITE)==0)
FlushFileBuffers(hFile);
bool sm=ftm!=NULL && ftm->IsSet();
bool sc=ftc!=NULL && ftc->IsSet();
bool sa=fta!=NULL && fta->IsSet();
FILETIME fm,fc,fa;
if (sm)
ftm->GetWin32(&fm);
if (sc)
ftc->GetWin32(&fc);
if (sa)
fta->GetWin32(&fa);
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
#endif
}
void File::SetCloseFileTime(RarTime *ftm,RarTime *fta)
{
#if defined(_UNIX) || defined(_EMX)
SetCloseFileTimeByName(FileName,ftm,fta);
#endif
}
void File::SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta)
{
#if defined(_UNIX) || defined(_EMX)
bool setm=ftm!=NULL && ftm->IsSet();
bool seta=fta!=NULL && fta->IsSet();
if (setm || seta)
{
utimbuf ut;
if (setm)
ut.modtime=ftm->GetUnix();
else
ut.modtime=fta->GetUnix();
if (seta)
ut.actime=fta->GetUnix();
else
ut.actime=ut.modtime;
utime(Name,&ut);
}
#endif
}
void File::GetOpenFileTime(RarTime *ft)
{
#ifdef _WIN_ALL
FILETIME FileTime;
GetFileTime(hFile,NULL,NULL,&FileTime);
*ft=FileTime;
#endif
#if defined(_UNIX) || defined(_EMX)
struct stat st;
fstat(fileno(hFile),&st);
*ft=st.st_mtime;
#endif
}
int64 File::FileLength()
{
SaveFilePos SavePos(*this);
Seek(0,SEEK_END);
return(Tell());
}
void File::SetHandleType(FILE_HANDLETYPE Type)
{
HandleType=Type;
}
bool File::IsDevice()
{
if (hFile==BAD_HANDLE)
return(false);
#ifdef _WIN_ALL
uint Type=GetFileType(hFile);
return(Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE);
#else
return(isatty(fileno(hFile)));
#endif
}
#ifndef SFX_MODULE
void File::fprintf(const char *fmt,...)
{
va_list argptr;
va_start(argptr,fmt);
safebuf char Msg[2*NM+1024],OutMsg[2*NM+1024];
vsprintf(Msg,fmt,argptr);
#ifdef _WIN_ALL
for (int Src=0,Dest=0;;Src++)
{
char CurChar=Msg[Src];
if (CurChar=='\n')
OutMsg[Dest++]='\r';
OutMsg[Dest++]=CurChar;
if (CurChar==0)
break;
}
#else
strcpy(OutMsg,Msg);
#endif
Write(OutMsg,strlen(OutMsg));
va_end(argptr);
}
#endif
bool File::RemoveCreated()
{
RemoveCreatedActive++;
bool RetCode=true;
for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
if (CreatedFiles[I]!=NULL)
{
CreatedFiles[I]->SetExceptions(false);
bool Success;
if (CreatedFiles[I]->NewFile)
Success=CreatedFiles[I]->Delete();
else
Success=CreatedFiles[I]->Close();
if (Success)
CreatedFiles[I]=NULL;
else
RetCode=false;
}
RemoveCreatedActive--;
return(RetCode);
}
#ifndef SFX_MODULE
int64 File::Copy(File &Dest,int64 Length)
{
Array<char> Buffer(0x10000);
int64 CopySize=0;
bool CopyAll=(Length==INT64NDF);
while (CopyAll || Length>0)
{
Wait();
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
int ReadSize=Read(&Buffer[0],SizeToRead);
if (ReadSize==0)
break;
Dest.Write(&Buffer[0],ReadSize);
CopySize+=ReadSize;
if (!CopyAll)
Length-=ReadSize;
}
return(CopySize);
}
#endif

120
src/unrar/file.hpp Normal file
View File

@ -0,0 +1,120 @@
#ifndef _RAR_FILE_
#define _RAR_FILE_
#ifdef _WIN_ALL
typedef HANDLE FileHandle;
#define BAD_HANDLE INVALID_HANDLE_VALUE
#else
typedef FILE* FileHandle;
#define BAD_HANDLE NULL
#endif
class RAROptions;
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD,FILE_HANDLEERR};
enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR};
struct FileStat
{
uint FileAttr;
uint FileTime;
int64 FileSize;
bool IsDir;
};
enum FILE_MODE_FLAGS {
// Request read only access to file. Default for Open.
FMF_READ=0,
// Request both read and write access to file. Default for Create.
FMF_UPDATE=1,
// Request write only access to file.
FMF_WRITE=2,
// Open files which are already opened for write by other programs.
FMF_OPENSHARED=4,
// Provide read access to created file for other programs.
FMF_SHAREREAD=8,
// Mode flags are not defined yet.
FMF_UNDEFINED=256
};
class File
{
private:
void AddFileToList(FileHandle hFile);
FileHandle hFile;
bool LastWrite;
FILE_HANDLETYPE HandleType;
bool SkipClose;
bool IgnoreReadErrors;
bool NewFile;
bool AllowDelete;
bool AllowExceptions;
#ifdef _WIN_ALL
bool NoSequentialRead;
uint CreateMode;
#endif
protected:
bool OpenShared; // Set by 'Archive' class.
public:
char FileName[NM];
wchar FileNameW[NM];
FILE_ERRORTYPE ErrorType;
uint CloseCount;
public:
File();
virtual ~File();
void operator = (File &SrcFile);
bool Open(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_READ);
void TOpen(const char *Name,const wchar *NameW=NULL);
bool WOpen(const char *Name,const wchar *NameW=NULL);
bool Create(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
void TCreate(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
bool WCreate(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
bool Close();
void Flush();
bool Delete();
bool Rename(const char *NewName,const wchar *NewNameW=NULL);
void Write(const void *Data,size_t Size);
int Read(void *Data,size_t Size);
int DirectRead(void *Data,size_t Size);
void Seek(int64 Offset,int Method);
bool RawSeek(int64 Offset,int Method);
int64 Tell();
void Prealloc(int64 Size);
byte GetByte();
void PutByte(byte Byte);
bool Truncate();
void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
static void SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta);
void GetOpenFileTime(RarTime *ft);
bool IsOpened() {return(hFile!=BAD_HANDLE);};
int64 FileLength();
void SetHandleType(FILE_HANDLETYPE Type);
FILE_HANDLETYPE GetHandleType() {return(HandleType);};
bool IsDevice();
void fprintf(const char *fmt,...);
static bool RemoveCreated();
FileHandle GetHandle() {return(hFile);};
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;};
char *GetName() {return(FileName);}
int64 Copy(File &Dest,int64 Length=INT64NDF);
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
#ifdef _WIN_ALL
void RemoveSequentialFlag() {NoSequentialRead=true;}
#endif
};
#endif

564
src/unrar/filefn.cpp Normal file
View File

@ -0,0 +1,564 @@
#include "rar.hpp"
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr)
{
#ifdef _WIN_ALL
BOOL RetCode;
if (WinNT() && NameW!=NULL && *NameW!=0)
RetCode=CreateDirectoryW(NameW,NULL);
else
if (Name!=NULL)
RetCode=CreateDirectoryA(Name,NULL);
else
return(MKDIR_BADPATH);
if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
{
if (SetAttr)
SetFileAttr(Name,NameW,Attr);
return(MKDIR_SUCCESS);
}
int ErrCode=GetLastError();
if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
return(MKDIR_BADPATH);
return(MKDIR_ERROR);
#else
// No Unicode in the rest of function, so Name must be not NULL.
if (Name==NULL)
return(MKDIR_BADPATH);
#endif
#ifdef _EMX
#ifdef _DJGPP
if (mkdir(Name,(Attr & FA_RDONLY) ? 0:S_IWUSR)==0)
#else
if (__mkdir(Name)==0)
#endif
{
if (SetAttr)
SetFileAttr(Name,NameW,Attr);
return(MKDIR_SUCCESS);
}
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
#endif
#ifdef _UNIX
mode_t uattr=SetAttr ? (mode_t)Attr:0777;
int ErrCode=mkdir(Name,uattr);
if (ErrCode==-1)
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
return(MKDIR_SUCCESS);
#endif
}
bool CreatePath(const char *Path,bool SkipLastName)
{
if (Path==NULL || *Path==0)
return(false);
#if defined(_WIN_ALL) || defined(_EMX)
uint DirAttr=0;
#else
uint DirAttr=0777;
#endif
bool Success=true;
for (const char *s=Path;*s!=0;s=charnext(s))
{
if (s-Path>=NM)
break;
// Process all kinds of path separators, so user can enter Unix style
// path in Windows or Windows in Unix.
if (IsPathDiv(*s))
{
char DirName[NM];
strncpy(DirName,Path,s-Path);
DirName[s-Path]=0;
if (MakeDir(DirName,NULL,true,DirAttr)==MKDIR_SUCCESS)
{
#ifndef GUI
mprintf(St(MCreatDir),DirName);
mprintf(" %s",St(MOk));
#endif
}
else
Success=false;
}
}
if (!SkipLastName)
if (!IsPathDiv(*PointToLastChar(Path)))
if (MakeDir(Path,NULL,true,DirAttr)!=MKDIR_SUCCESS)
Success=false;
return(Success);
}
bool CreatePath(const wchar *Path,bool SkipLastName)
{
if (Path==NULL || *Path==0)
return(false);
#if defined(_WIN_ALL) || defined(_EMX)
uint DirAttr=0;
#else
uint DirAttr=0777;
#endif
bool Success=true;
for (const wchar *s=Path;*s!=0;s++)
{
if (s-Path>=NM)
break;
// Process all kinds of path separators, so user can enter Unix style
// path in Windows or Windows in Unix.
if (IsPathDiv(*s))
{
wchar DirName[NM];
wcsncpy(DirName,Path,s-Path);
DirName[s-Path]=0;
if (MakeDir(NULL,DirName,true,DirAttr)==MKDIR_SUCCESS)
{
#ifndef GUI
char DirNameA[NM];
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
DirNameA[ASIZE(DirNameA)-1]=0;
mprintf(St(MCreatDir),DirNameA);
mprintf(" %s",St(MOk));
#endif
}
else
Success=false;
}
}
if (!SkipLastName)
if (!IsPathDiv(*PointToLastChar(Path)))
if (MakeDir(NULL,Path,true,DirAttr)!=MKDIR_SUCCESS)
Success=false;
return(Success);
}
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
{
#ifdef _WIN_ALL
// If we are in Windows, let's try Unicode path first. In Unix we do not
// need it (Unix MakeDir will fails with Unicode only name).
if (PathW!=NULL && *PathW!=0)
return(CreatePath(PathW,SkipLastName));
#endif
if (Path!=NULL && *Path!=0)
return(CreatePath(Path,SkipLastName));
return(false);
}
void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta)
{
#ifdef _WIN_ALL
if (!WinNT())
return;
bool sm=ftm!=NULL && ftm->IsSet();
bool sc=ftc!=NULL && ftc->IsSet();
bool sa=fta!=NULL && fta->IsSet();
unsigned int DirAttr=GetFileAttr(Name,NameW);
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0);
if (ResetAttr)
SetFileAttr(Name,NameW,0);
wchar DirNameW[NM];
GetWideName(Name,NameW,DirNameW,ASIZE(DirNameW));
HANDLE hFile=CreateFileW(DirNameW,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
if (hFile==INVALID_HANDLE_VALUE)
return;
FILETIME fm,fc,fa;
if (sm)
ftm->GetWin32(&fm);
if (sc)
ftc->GetWin32(&fc);
if (sa)
fta->GetWin32(&fa);
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
CloseHandle(hFile);
if (ResetAttr)
SetFileAttr(Name,NameW,DirAttr);
#endif
#if defined(_UNIX) || defined(_EMX)
File::SetCloseFileTimeByName(Name,ftm,fta);
#endif
}
bool IsRemovable(const char *Name)
{
#ifdef _WIN_ALL
char Root[NM];
GetPathRoot(Name,Root);
int Type=GetDriveTypeA(*Root!=0 ? Root:NULL);
return(Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM);
#elif defined(_EMX)
char Drive=etoupper(Name[0]);
return((Drive=='A' || Drive=='B') && Name[1]==':');
#else
return(false);
#endif
}
#ifndef SFX_MODULE
int64 GetFreeDisk(const char *Name)
{
#ifdef _WIN_ALL
char Root[NM];
GetPathRoot(Name,Root);
typedef BOOL (WINAPI *GETDISKFREESPACEEX)(
LPCSTR,PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER
);
static GETDISKFREESPACEEX pGetDiskFreeSpaceEx=NULL;
if (pGetDiskFreeSpaceEx==NULL)
{
HMODULE hKernel=GetModuleHandleW(L"kernel32.dll");
if (hKernel!=NULL)
pGetDiskFreeSpaceEx=(GETDISKFREESPACEEX)GetProcAddress(hKernel,"GetDiskFreeSpaceExA");
}
if (pGetDiskFreeSpaceEx!=NULL)
{
GetFilePath(Name,Root,ASIZE(Root));
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
if (pGetDiskFreeSpaceEx(*Root ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
return(INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart));
}
// We are here if we failed to load GetDiskFreeSpaceExA.
DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters;
if (!GetDiskFreeSpaceA(*Root ? Root:NULL,&SectorsPerCluster,&BytesPerSector,&FreeClusters,&TotalClusters))
return(1457664);
int64 FreeSize=SectorsPerCluster*BytesPerSector;
FreeSize=FreeSize*FreeClusters;
return(FreeSize);
#elif defined(_BEOS)
char Root[NM];
GetFilePath(Name,Root,ASIZE(Root));
dev_t Dev=dev_for_path(*Root ? Root:".");
if (Dev<0)
return(1457664);
fs_info Info;
if (fs_stat_dev(Dev,&Info)!=0)
return(1457664);
int64 FreeSize=Info.block_size;
FreeSize=FreeSize*Info.free_blocks;
return(FreeSize);
#elif defined(_UNIX)
return(1457664);
#elif defined(_EMX)
int Drive=IsDiskLetter(Name) ? etoupper(Name[0])-'A'+1:0;
#ifndef _DJGPP
if (_osmode == OS2_MODE)
{
FSALLOCATE fsa;
if (DosQueryFSInfo(Drive,1,&fsa,sizeof(fsa))!=0)
return(1457664);
int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
FreeSize=FreeSize*fsa.cUnitAvail;
return(FreeSize);
}
else
#endif
{
union REGS regs,outregs;
memset(&regs,0,sizeof(regs));
regs.h.ah=0x36;
regs.h.dl=Drive;
#ifdef _DJGPP
int86 (0x21,&regs,&outregs);
#else
_int86 (0x21,&regs,&outregs);
#endif
if (outregs.x.ax==0xffff)
return(1457664);
int64 FreeSize=outregs.x.ax*outregs.x.cx;
FreeSize=FreeSize*outregs.x.bx;
return(FreeSize);
}
#else
#define DISABLEAUTODETECT
return(1457664);
#endif
}
#endif
bool FileExist(const char *Name,const wchar *NameW)
{
#ifdef _WIN_ALL
if (WinNT() && NameW!=NULL && *NameW!=0)
return(GetFileAttributesW(NameW)!=0xffffffff);
else
return(Name!=NULL && GetFileAttributesA(Name)!=0xffffffff);
#elif defined(ENABLE_ACCESS)
return(access(Name,0)==0);
#else
FindData FD;
return(FindFile::FastFind(Name,NameW,&FD));
#endif
}
bool FileExist(const wchar *Name)
{
return FileExist(NULL,Name);
}
bool WildFileExist(const char *Name,const wchar *NameW)
{
if (IsWildcard(Name,NameW))
{
FindFile Find;
Find.SetMask(Name);
Find.SetMaskW(NameW);
FindData fd;
return(Find.Next(&fd));
}
return(FileExist(Name,NameW));
}
bool IsDir(uint Attr)
{
#if defined (_WIN_ALL) || defined(_EMX)
return(Attr!=0xffffffff && (Attr & 0x10)!=0);
#endif
#if defined(_UNIX)
return((Attr & 0xF000)==0x4000);
#endif
}
bool IsUnreadable(uint Attr)
{
#if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
return(S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr));
#endif
return(false);
}
bool IsLabel(uint Attr)
{
#if defined (_WIN_ALL) || defined(_EMX)
return((Attr & 8)!=0);
#else
return(false);
#endif
}
bool IsLink(uint Attr)
{
#ifdef _UNIX
return((Attr & 0xF000)==0xA000);
#else
return(false);
#endif
}
bool IsDeleteAllowed(uint FileAttr)
{
#if defined(_WIN_ALL) || defined(_EMX)
return((FileAttr & (FA_RDONLY|FA_SYSTEM|FA_HIDDEN))==0);
#else
return((FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR));
#endif
}
void PrepareToDelete(const char *Name,const wchar *NameW)
{
#if defined(_WIN_ALL) || defined(_EMX)
SetFileAttr(Name,NameW,0);
#endif
#ifdef _UNIX
if (Name!=NULL)
chmod(Name,S_IRUSR|S_IWUSR|S_IXUSR);
#endif
}
uint GetFileAttr(const char *Name,const wchar *NameW)
{
#ifdef _WIN_ALL
if (WinNT() && NameW!=NULL && *NameW!=0)
return(GetFileAttributesW(NameW));
else
return(GetFileAttributesA(Name));
#elif defined(_DJGPP)
return(_chmod(Name,0));
#else
struct stat st;
if (stat(Name,&st)!=0)
return(0);
#ifdef _EMX
return(st.st_attr);
#else
return(st.st_mode);
#endif
#endif
}
bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr)
{
bool Success;
#ifdef _WIN_ALL
if (WinNT() && NameW!=NULL && *NameW!=0)
Success=SetFileAttributesW(NameW,Attr)!=0;
else
if (Name!=NULL)
Success=SetFileAttributesA(Name,Attr)!=0;
else
Success=false;
#elif defined(_DJGPP)
Success=_chmod(Name,1,Attr)!=-1;
#elif defined(_EMX)
Success=__chmod(Name,1,Attr)!=-1;
#elif defined(_UNIX)
Success=chmod(Name,(mode_t)Attr)==0;
#else
Success=false;
#endif
return(Success);
}
#ifndef SFX_MODULE
uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)
{
SaveFilePos SavePos(*SrcFile);
const size_t BufSize=0x10000;
Array<byte> Data(BufSize);
int64 BlockCount=0;
uint DataCRC=0xffffffff;
#if !defined(SILENT) && !defined(_WIN_CE)
int64 FileLength=SrcFile->FileLength();
if (ShowMode!=CALCCRC_SHOWNONE)
{
mprintf(St(MCalcCRC));
mprintf(" ");
}
#endif
SrcFile->Seek(0,SEEK_SET);
while (true)
{
size_t SizeToRead;
if (Size==INT64NDF) // If we process the entire file.
SizeToRead=BufSize; // Then always attempt to read the entire buffer.
else
SizeToRead=(size_t)Min((int64)BufSize,Size);
int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
if (ReadSize==0)
break;
++BlockCount;
if ((BlockCount & 15)==0)
{
#if !defined(SILENT) && !defined(_WIN_CE)
if (ShowMode==CALCCRC_SHOWALL)
mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength));
#endif
Wait();
}
DataCRC=CRC(DataCRC,&Data[0],ReadSize);
if (Size!=INT64NDF)
Size-=ReadSize;
}
#if !defined(SILENT) && !defined(_WIN_CE)
if (ShowMode==CALCCRC_SHOWALL)
mprintf("\b\b\b\b ");
#endif
return(DataCRC^0xffffffff);
}
#endif
bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW)
{
return(rename(SrcName,DestName)==0);
}
bool DelFile(const char *Name)
{
return(DelFile(Name,NULL));
}
bool DelFile(const char *Name,const wchar *NameW)
{
return(Name!=NULL && remove(Name)==0);
}
#if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
bool SetFileCompression(char *Name,wchar *NameW,bool State)
{
wchar FileNameW[NM];
GetWideName(Name,NameW,FileNameW,ASIZE(FileNameW));
HANDLE hFile=CreateFileW(FileNameW,FILE_READ_DATA|FILE_WRITE_DATA,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if (hFile==INVALID_HANDLE_VALUE)
return(false);
SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
DWORD Result;
int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
sizeof(NewState),NULL,0,&Result,NULL);
CloseHandle(hFile);
return(RetCode!=0);
}
#endif

48
src/unrar/filefn.hpp Normal file
View File

@ -0,0 +1,48 @@
#ifndef _RAR_FILEFN_
#define _RAR_FILEFN_
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr);
bool CreatePath(const char *Path,bool SkipLastName);
bool CreatePath(const wchar *Path,bool SkipLastName);
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta);
bool IsRemovable(const char *Name);
#ifndef SFX_MODULE
int64 GetFreeDisk(const char *Name);
#endif
bool FileExist(const char *Name,const wchar *NameW=NULL);
bool FileExist(const wchar *Name);
bool WildFileExist(const char *Name,const wchar *NameW=NULL);
bool IsDir(uint Attr);
bool IsUnreadable(uint Attr);
bool IsLabel(uint Attr);
bool IsLink(uint Attr);
void SetSFXMode(const char *FileName);
void EraseDiskContents(const char *FileName);
bool IsDeleteAllowed(uint FileAttr);
void PrepareToDelete(const char *Name,const wchar *NameW=NULL);
uint GetFileAttr(const char *Name,const wchar *NameW=NULL);
bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr);
enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL};
uint CalcFileCRC(File *SrcFile,int64 Size=INT64NDF,CALCCRC_SHOWMODE ShowMode=CALCCRC_SHOWNONE);
bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW);
bool DelFile(const char *Name);
bool DelFile(const char *Name,const wchar *NameW);
bool DelDir(const char *Name);
bool DelDir(const char *Name,const wchar *NameW);
#if defined(_WIN_ALL) && !defined(_WIN_CE)
bool SetFileCompression(char *Name,wchar *NameW,bool State);
#endif
#endif

208
src/unrar/filestr.cpp Normal file
View File

@ -0,0 +1,208 @@
#include "rar.hpp"
static bool IsUnicode(byte *Data,int Size);
bool ReadTextFile(
const char *Name,
const wchar *NameW,
StringList *List,
bool Config,
bool AbortOnError,
RAR_CHARSET SrcCharset,
bool Unquote,
bool SkipComments,
bool ExpandEnvStr)
{
char FileName[NM];
*FileName=0;
if (Name!=NULL)
if (Config)
GetConfigName(Name,FileName,true);
else
strcpy(FileName,Name);
wchar FileNameW[NM];
*FileNameW=0;
#ifdef _WIN_ALL
if (NameW!=NULL)
if (Config)
GetConfigName(NameW,FileNameW,true);
else
wcscpy(FileNameW,NameW);
#endif
File SrcFile;
if (FileName!=NULL && *FileName!=0 || FileNameW!=NULL && *FileNameW!=0)
{
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName,FileNameW):SrcFile.Open(FileName,FileNameW,0);
if (!OpenCode)
{
if (AbortOnError)
ErrHandler.Exit(RARX_OPEN);
return(false);
}
}
else
SrcFile.SetHandleType(FILE_HANDLESTD);
unsigned int DataSize=0,ReadSize;
const int ReadBlock=1024;
Array<char> Data(ReadBlock+5);
while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0)
{
DataSize+=ReadSize;
Data.Add(ReadSize);
}
memset(&Data[DataSize],0,5);
if (SrcCharset==RCH_UNICODE ||
SrcCharset==RCH_DEFAULT && IsUnicode((byte *)&Data[0],DataSize))
{
// Unicode in native system format, can be more than 2 bytes per character.
Array<wchar> DataW(Data.Size()/2+1);
for (size_t I=2;I<Data.Size()-1;I+=2)
{
// Need to convert Data to (byte) first to prevent the sign extension
// to higher bytes.
DataW[(I-2)/2]=(wchar)((byte)Data[I])+(wchar)((byte)Data[I+1])*256;
}
wchar *CurStr=&DataW[0];
Array<char> AnsiName;
while (*CurStr!=0)
{
wchar *NextStr=CurStr,*CmtPtr=NULL;
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
{
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
{
*NextStr=0;
CmtPtr=NextStr;
}
NextStr++;
}
*NextStr=0;
for (wchar *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
{
if (*SpacePtr!=' ' && *SpacePtr!='\t')
break;
*SpacePtr=0;
}
if (*CurStr)
{
// Length and AddSize must be defined as signed, because AddSize
// can be negative.
int Length=(int)wcslen(CurStr);
int AddSize=4*(Length-(int)AnsiName.Size()+1);
if (AddSize>0)
AnsiName.Add(AddSize);
if (Unquote && *CurStr=='\"' && CurStr[Length-1]=='\"')
{
CurStr[Length-1]=0;
CurStr++;
}
WideToChar(CurStr,&AnsiName[0],AnsiName.Size());
bool Expanded=false;
#if defined(_WIN_ALL) && !defined(_WIN_CE)
if (ExpandEnvStr && *CurStr=='%')
{
// Expanding environment variables in Windows version.
char ExpName[NM];
wchar ExpNameW[NM];
*ExpNameW=0;
int ret,retw=1;
ret=ExpandEnvironmentStringsA(&AnsiName[0],ExpName,ASIZE(ExpName));
if (ret!=0 && WinNT())
retw=ExpandEnvironmentStringsW(CurStr,ExpNameW,ASIZE(ExpNameW));
Expanded=ret!=0 && ret<ASIZE(ExpName) &&
retw!=0 && retw<ASIZE(ExpNameW);
if (Expanded)
List->AddString(ExpName,ExpNameW);
}
#endif
if (!Expanded)
List->AddString(&AnsiName[0],CurStr);
}
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
CurStr++;
}
}
else
{
char *CurStr=&Data[0];
while (*CurStr!=0)
{
char *NextStr=CurStr,*CmtPtr=NULL;
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
{
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
{
*NextStr=0;
CmtPtr=NextStr;
}
NextStr++;
}
*NextStr=0;
for (char *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
{
if (*SpacePtr!=' ' && *SpacePtr!='\t')
break;
*SpacePtr=0;
}
if (*CurStr)
{
if (Unquote && *CurStr=='\"')
{
size_t Length=strlen(CurStr);
if (CurStr[Length-1]=='\"')
{
CurStr[Length-1]=0;
CurStr++;
}
}
#if defined(_WIN_ALL)
if (SrcCharset==RCH_OEM)
OemToCharA(CurStr,CurStr);
#endif
bool Expanded=false;
#if defined(_WIN_ALL) && !defined(_WIN_CE)
if (ExpandEnvStr && *CurStr=='%')
{
// Expanding environment variables in Windows version.
char ExpName[NM];
int ret=ExpandEnvironmentStringsA(CurStr,ExpName,ASIZE(ExpName));
Expanded=ret!=0 && ret<ASIZE(ExpName);
if (Expanded)
List->AddString(ExpName);
}
#endif
if (!Expanded)
List->AddString(CurStr);
}
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
CurStr++;
}
}
return(true);
}
bool IsUnicode(byte *Data,int Size)
{
if (Size<4 || Data[0]!=0xff || Data[1]!=0xfe)
return(false);
for (int I=2;I<Size;I++)
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
return(true);
return(false);
}

16
src/unrar/filestr.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef _RAR_FILESTR_
#define _RAR_FILESTR_
bool ReadTextFile(
const char *Name,
const wchar *NameW,
StringList *List,
bool Config,
bool AbortOnError=false,
RAR_CHARSET SrcCharset=RCH_DEFAULT,
bool Unquote=false,
bool SkipComments=false,
bool ExpandEnvStr=false
);
#endif

291
src/unrar/find.cpp Normal file
View File

@ -0,0 +1,291 @@
#include "rar.hpp"
FindFile::FindFile()
{
*FindMask=0;
*FindMaskW=0;
FirstCall=true;
#ifdef _WIN_ALL
hFind=INVALID_HANDLE_VALUE;
#else
dirp=NULL;
#endif
}
FindFile::~FindFile()
{
#ifdef _WIN_ALL
if (hFind!=INVALID_HANDLE_VALUE)
FindClose(hFind);
#else
if (dirp!=NULL)
closedir(dirp);
#endif
}
void FindFile::SetMask(const char *FindMask)
{
strcpy(FindFile::FindMask,NullToEmpty(FindMask));
if (*FindMaskW==0)
CharToWide(FindMask,FindMaskW);
FirstCall=true;
}
void FindFile::SetMaskW(const wchar *FindMaskW)
{
if (FindMaskW==NULL)
return;
wcscpy(FindFile::FindMaskW,FindMaskW);
if (*FindMask==0)
WideToChar(FindMaskW,FindMask);
FirstCall=true;
}
bool FindFile::Next(struct FindData *fd,bool GetSymLink)
{
fd->Error=false;
if (*FindMask==0)
return(false);
#ifdef _WIN_ALL
if (FirstCall)
{
if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE)
return(false);
}
else
if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE)
return(false);
#else
if (FirstCall)
{
char DirName[NM];
strcpy(DirName,FindMask);
RemoveNameFromPath(DirName);
if (*DirName==0)
strcpy(DirName,".");
if ((dirp=opendir(DirName))==NULL)
{
fd->Error=(errno!=ENOENT);
return(false);
}
}
while (1)
{
struct dirent *ent=readdir(dirp);
if (ent==NULL)
return(false);
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
continue;
if (CmpName(FindMask,ent->d_name,MATCH_NAMES))
{
char FullName[NM];
strcpy(FullName,FindMask);
*PointToName(FullName)=0;
if (strlen(FullName)+strlen(ent->d_name)>=ASIZE(FullName)-1)
{
#ifndef SILENT
Log(NULL,"\n%s%s",FullName,ent->d_name);
Log(NULL,St(MPathTooLong));
#endif
return(false);
}
strcat(FullName,ent->d_name);
if (!FastFind(FullName,NULL,fd,GetSymLink))
{
ErrHandler.OpenErrorMsg(FullName);
continue;
}
strcpy(fd->Name,FullName);
break;
}
}
*fd->NameW=0;
#ifdef _APPLE
if (!LowAscii(fd->Name))
UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
if (!LowAscii(fd->Name) && UnicodeEnabled())
CharToWide(fd->Name,fd->NameW);
#endif
#endif
fd->Flags=0;
fd->IsDir=IsDir(fd->FileAttr);
FirstCall=false;
char *Name=PointToName(fd->Name);
if (strcmp(Name,".")==0 || strcmp(Name,"..")==0)
return(Next(fd));
return(true);
}
bool FindFile::FastFind(const char *FindMask,const wchar *FindMaskW,FindData *fd,bool GetSymLink)
{
fd->Error=false;
#ifndef _UNIX
if (IsWildcard(FindMask,FindMaskW))
return(false);
#endif
#ifdef _WIN_ALL
HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd);
if (hFind==INVALID_HANDLE_VALUE)
return(false);
FindClose(hFind);
#else
struct stat st;
if (GetSymLink)
{
#ifdef SAVE_LINKS
if (lstat(FindMask,&st)!=0)
#else
if (stat(FindMask,&st)!=0)
#endif
{
fd->Error=(errno!=ENOENT);
return(false);
}
}
else
if (stat(FindMask,&st)!=0)
{
fd->Error=(errno!=ENOENT);
return(false);
}
#ifdef _DJGPP
fd->FileAttr=_chmod(FindMask,0);
#elif defined(_EMX)
fd->FileAttr=st.st_attr;
#else
fd->FileAttr=st.st_mode;
#endif
fd->IsDir=IsDir(st.st_mode);
fd->Size=st.st_size;
fd->mtime=st.st_mtime;
fd->atime=st.st_atime;
fd->ctime=st.st_ctime;
fd->FileTime=fd->mtime.GetDos();
strcpy(fd->Name,FindMask);
*fd->NameW=0;
#ifdef _APPLE
if (!LowAscii(fd->Name))
UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
if (!LowAscii(fd->Name) && UnicodeEnabled())
CharToWide(fd->Name,fd->NameW);
#endif
#endif
fd->Flags=0;
fd->IsDir=IsDir(fd->FileAttr);
return(true);
}
#ifdef _WIN_ALL
HANDLE FindFile::Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,FindData *fd)
{
#ifndef _WIN_CE
if (WinNT())
#endif
{
wchar WideMask[NM];
if (MaskW!=NULL && *MaskW!=0)
wcscpy(WideMask,MaskW);
else
CharToWide(Mask,WideMask);
WIN32_FIND_DATAW FindData;
if (hFind==INVALID_HANDLE_VALUE)
{
hFind=FindFirstFileW(WideMask,&FindData);
if (hFind==INVALID_HANDLE_VALUE)
{
int SysErr=GetLastError();
fd->Error=(SysErr!=ERROR_FILE_NOT_FOUND &&
SysErr!=ERROR_PATH_NOT_FOUND &&
SysErr!=ERROR_NO_MORE_FILES);
}
}
else
if (!FindNextFileW(hFind,&FindData))
{
hFind=INVALID_HANDLE_VALUE;
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
}
if (hFind!=INVALID_HANDLE_VALUE)
{
wcscpy(fd->NameW,WideMask);
wcscpy(PointToName(fd->NameW),FindData.cFileName);
WideToChar(fd->NameW,fd->Name);
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
fd->FileAttr=FindData.dwFileAttributes;
wcscpy(fd->ShortName,FindData.cAlternateFileName);
fd->ftCreationTime=FindData.ftCreationTime;
fd->ftLastAccessTime=FindData.ftLastAccessTime;
fd->ftLastWriteTime=FindData.ftLastWriteTime;
fd->mtime=FindData.ftLastWriteTime;
fd->ctime=FindData.ftCreationTime;
fd->atime=FindData.ftLastAccessTime;
fd->FileTime=fd->mtime.GetDos();
#ifndef _WIN_CE
// if (LowAscii(fd->NameW))
// *fd->NameW=0;
#endif
}
}
#ifndef _WIN_CE
else
{
char CharMask[NM];
if (Mask!=NULL && *Mask!=0)
strcpy(CharMask,Mask);
else
WideToChar(MaskW,CharMask);
WIN32_FIND_DATAA FindData;
if (hFind==INVALID_HANDLE_VALUE)
{
hFind=FindFirstFileA(CharMask,&FindData);
if (hFind==INVALID_HANDLE_VALUE)
{
int SysErr=GetLastError();
fd->Error=SysErr!=ERROR_FILE_NOT_FOUND && SysErr!=ERROR_PATH_NOT_FOUND;
}
}
else
if (!FindNextFileA(hFind,&FindData))
{
hFind=INVALID_HANDLE_VALUE;
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
}
if (hFind!=INVALID_HANDLE_VALUE)
{
strcpy(fd->Name,CharMask);
strcpy(PointToName(fd->Name),FindData.cFileName);
CharToWide(fd->Name,fd->NameW);
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
fd->FileAttr=FindData.dwFileAttributes;
CharToWide(FindData.cAlternateFileName,fd->ShortName);
fd->ftCreationTime=FindData.ftCreationTime;
fd->ftLastAccessTime=FindData.ftLastAccessTime;
fd->ftLastWriteTime=FindData.ftLastWriteTime;
fd->mtime=FindData.ftLastWriteTime;
fd->ctime=FindData.ftCreationTime;
fd->atime=FindData.ftLastAccessTime;
fd->FileTime=fd->mtime.GetDos();
// if (LowAscii(fd->Name))
// *fd->NameW=0;
}
}
#endif
fd->Flags=0;
return(hFind);
}
#endif

53
src/unrar/find.hpp Normal file
View File

@ -0,0 +1,53 @@
#ifndef _RAR_FINDDATA_
#define _RAR_FINDDATA_
enum FINDDATA_FLAGS {
FDDF_SECONDDIR=1 // Second encounter of same directory in SCAN_GETDIRSTWICE ScanTree mode.
};
struct FindData
{
char Name[NM];
wchar NameW[NM];
int64 Size;
uint FileAttr;
uint FileTime;
bool IsDir;
RarTime mtime;
RarTime ctime;
RarTime atime;
#ifdef _WIN_ALL
wchar ShortName[NM];
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
#endif
uint Flags;
bool Error;
};
class FindFile
{
private:
#ifdef _WIN_ALL
static HANDLE Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd);
#endif
char FindMask[NM];
wchar FindMaskW[NM];
bool FirstCall;
#ifdef _WIN_ALL
HANDLE hFind;
#else
DIR *dirp;
#endif
public:
FindFile();
~FindFile();
void SetMask(const char *FindMask);
void SetMaskW(const wchar *FindMaskW);
bool Next(FindData *fd,bool GetSymLink=false);
static bool FastFind(const char *FindMask,const wchar *FindMaskW,FindData *fd,bool GetSymLink=false);
};
#endif

35
src/unrar/getbits.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "rar.hpp"
BitInput::BitInput()
{
// getbits attempts to read data from InAddr, InAddr+1, InAddr+2 positions.
// So let's allocate two additional bytes for situation, when we need to
// read only 1 byte from the last position of buffer and avoid a crash
// from access to next 2 bytes, which contents we do not need.
size_t BufSize=MAX_SIZE+2;
InBuf=new byte[BufSize];
// Ensure that we get predictable results when accessing bytes in area
// not filled with read data.
memset(InBuf,0,BufSize);
}
BitInput::~BitInput()
{
delete[] InBuf;
}
void BitInput::faddbits(uint Bits)
{
// Function wrapped version of inline addbits to save code size.
addbits(Bits);
}
uint BitInput::fgetbits()
{
// Function wrapped version of inline getbits to save code size.
return(getbits());
}

51
src/unrar/getbits.hpp Normal file
View File

@ -0,0 +1,51 @@
#ifndef _RAR_GETBITS_
#define _RAR_GETBITS_
class BitInput
{
public:
enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer.
protected:
int InAddr; // Curent byte position in the buffer.
int InBit; // Current bit position in the current byte.
public:
BitInput();
~BitInput();
byte *InBuf; // Dynamically allocated input buffer.
void InitBitInput()
{
InAddr=InBit=0;
}
// Move forward by 'Bits' bits.
void addbits(uint Bits)
{
Bits+=InBit;
InAddr+=Bits>>3;
InBit=Bits&7;
}
// Return 16 bits from current position in the buffer.
// Bit at (InAddr,InBit) has the highest position in returning data.
uint getbits()
{
uint BitField=(uint)InBuf[InAddr] << 16;
BitField|=(uint)InBuf[InAddr+1] << 8;
BitField|=(uint)InBuf[InAddr+2];
BitField >>= (8-InBit);
return(BitField & 0xffff);
}
void faddbits(uint Bits);
uint fgetbits();
// Check if buffer has enough space for IncPtr bytes. Returns 'true'
// if buffer will be overflown.
bool Overflow(uint IncPtr)
{
return(InAddr+IncPtr>=MAX_SIZE);
}
};
#endif

4
src/unrar/global.cpp Normal file
View File

@ -0,0 +1,4 @@
#define INCLUDEGLOBAL
#include "rar.hpp"

15
src/unrar/global.hpp Normal file
View File

@ -0,0 +1,15 @@
#ifndef _RAR_GLOBAL_
#define _RAR_GLOBAL_
#ifdef INCLUDEGLOBAL
#define EXTVAR
#else
#define EXTVAR extern
#endif
EXTVAR ErrorHandler ErrHandler;
#endif

327
src/unrar/headers.hpp Normal file
View File

@ -0,0 +1,327 @@
#ifndef _RAR_HEADERS_
#define _RAR_HEADERS_
#define SIZEOF_MARKHEAD 7
#define SIZEOF_OLDMHD 7
#define SIZEOF_NEWMHD 13
#define SIZEOF_OLDLHD 21
#define SIZEOF_NEWLHD 32
#define SIZEOF_SHORTBLOCKHEAD 7
#define SIZEOF_LONGBLOCKHEAD 11
#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 PACK_VER 29
#define PACK_CRYPT_VER 29
#define UNP_VER 36
#define CRYPT_VER 29
#define AV_VER 20
#define PROTECT_VER 20
#define MHD_VOLUME 0x0001U
// Old style main archive comment embed into main archive header. Must not
// be used in new archives anymore. Must never be used with MHD_ENCRYPTVER
// or other flags changing the size of main header. RAR expects the fixed
// size of main header preceding the comment if MHD_COMMENT is found.
#define MHD_COMMENT 0x0002U
#define MHD_LOCK 0x0004U
#define MHD_SOLID 0x0008U
#define MHD_PACK_COMMENT 0x0010U
#define MHD_NEWNUMBERING 0x0010U
#define MHD_AV 0x0020U
#define MHD_PROTECT 0x0040U
#define MHD_PASSWORD 0x0080U
#define MHD_FIRSTVOLUME 0x0100U
#define MHD_ENCRYPTVER 0x0200U
#define LHD_SPLIT_BEFORE 0x0001U
#define LHD_SPLIT_AFTER 0x0002U
#define LHD_PASSWORD 0x0004U
// Old style file comment embed into file header. Must not be used
// in new archives anymore.
#define LHD_COMMENT 0x0008U
#define LHD_SOLID 0x0010U
#define LHD_WINDOWMASK 0x00e0U
#define LHD_WINDOW64 0x0000U
#define LHD_WINDOW128 0x0020U
#define LHD_WINDOW256 0x0040U
#define LHD_WINDOW512 0x0060U
#define LHD_WINDOW1024 0x0080U
#define LHD_WINDOW2048 0x00a0U
#define LHD_WINDOW4096 0x00c0U
#define LHD_DIRECTORY 0x00e0U
#define LHD_LARGE 0x0100U
#define LHD_UNICODE 0x0200U
#define LHD_SALT 0x0400U
#define LHD_VERSION 0x0800U
#define LHD_EXTTIME 0x1000U
#define LHD_EXTAREA 0x2000U
#define SKIP_IF_UNKNOWN 0x4000U
#define LONG_BLOCK 0x8000U
#define EARC_NEXT_VOLUME 0x0001U // Not last volume.
#define EARC_DATACRC 0x0002U // Store CRC32 of RAR archive (now is used only in volumes).
#define EARC_REVSPACE 0x0004U // Reserve space for end of REV file 7 byte record.
#define EARC_VOLNUMBER 0x0008U // Store a number of current volume.
enum HEADER_TYPE {
MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76,
SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a,
ENDARC_HEAD=0x7b
};
enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
enum HOST_SYSTEM {
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
HOST_BEOS=5,HOST_MAX
};
#define SUBHEAD_TYPE_CMT "CMT"
#define SUBHEAD_TYPE_ACL "ACL"
#define SUBHEAD_TYPE_STREAM "STM"
#define SUBHEAD_TYPE_UOWNER "UOW"
#define SUBHEAD_TYPE_AV "AV"
#define SUBHEAD_TYPE_RR "RR"
#define SUBHEAD_TYPE_OS2EA "EA2"
#define SUBHEAD_TYPE_BEOSEA "EABE"
/* new file inherits a subblock when updating a host file */
#define SUBHEAD_FLAGS_INHERITED 0x80000000
#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001
struct OldMainHeader
{
byte Mark[4];
ushort HeadSize;
byte Flags;
};
struct OldFileHeader
{
uint PackSize;
uint UnpSize;
ushort FileCRC;
ushort HeadSize;
uint FileTime;
byte FileAttr;
byte Flags;
byte UnpVer;
byte NameSize;
byte Method;
};
struct MarkHeader
{
byte Mark[7];
};
struct BaseBlock
{
ushort HeadCRC;
HEADER_TYPE HeadType; // 1 byte.
ushort Flags;
ushort HeadSize;
bool IsSubBlock()
{
if (HeadType==SUB_HEAD)
return(true);
if (HeadType==NEWSUB_HEAD && (Flags & LHD_SOLID)!=0)
return(true);
return(false);
}
};
struct BlockHeader:BaseBlock
{
union {
uint DataSize;
uint PackSize;
};
};
struct MainHeader:BaseBlock
{
ushort HighPosAV;
uint PosAV;
byte EncryptVer;
};
#define SALT_SIZE 8
struct FileHeader:BlockHeader
{
uint UnpSize;
byte HostOS;
uint FileCRC;
uint FileTime;
byte UnpVer;
byte Method;
ushort NameSize;
union {
uint FileAttr;
uint SubFlags;
};
/* optional */
uint HighPackSize;
uint HighUnpSize;
/* names */
char FileName[NM];
wchar FileNameW[NM];
/* optional */
Array<byte> SubData;
byte Salt[SALT_SIZE];
RarTime mtime;
RarTime ctime;
RarTime atime;
RarTime arctime;
/* dummy */
int64 FullPackSize;
int64 FullUnpSize;
void Clear(size_t SubDataSize)
{
SubData.Alloc(SubDataSize);
Flags=LONG_BLOCK;
SubFlags=0;
}
bool CmpName(const char *Name)
{
return(strcmp(FileName,Name)==0);
}
FileHeader& operator = (FileHeader &hd)
{
SubData.Reset();
memcpy(this,&hd,sizeof(*this));
SubData.CleanData();
SubData=hd.SubData;
return(*this);
}
};
struct EndArcHeader:BaseBlock
{
// Optional CRC32 of entire archive up to start of EndArcHeader block.
// Present if EARC_DATACRC flag is set.
uint ArcDataCRC;
// Optional number of current volume.
// Present if EARC_VOLNUMBER flag is set.
ushort VolNumber;
// 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
};
// SubBlockHeader and its successors were used in RAR 2.x format.
// RAR 3.x uses FileHeader with NEWSUB_HEAD HeadType for subblocks.
struct SubBlockHeader:BlockHeader
{
ushort SubType;
byte Level;
};
struct CommentHeader:BaseBlock
{
ushort UnpSize;
byte UnpVer;
byte Method;
ushort CommCRC;
};
struct ProtectHeader:BlockHeader
{
byte Version;
ushort RecSectors;
uint TotalBlocks;
byte Mark[8];
};
struct AVHeader:BaseBlock
{
byte UnpVer;
byte Method;
byte AVVer;
uint AVInfoCRC;
};
struct SignHeader:BaseBlock
{
uint CreationTime;
ushort ArcNameSize;
ushort UserNameSize;
};
struct UnixOwnersHeader:SubBlockHeader
{
ushort OwnerNameSize;
ushort GroupNameSize;
/* dummy */
char OwnerName[NM];
char GroupName[NM];
};
struct EAHeader:SubBlockHeader
{
uint UnpSize;
byte UnpVer;
byte Method;
uint EACRC;
};
struct StreamHeader:SubBlockHeader
{
uint UnpSize;
byte UnpVer;
byte Method;
uint StreamCRC;
ushort StreamNameSize;
/* dummy */
byte StreamName[NM];
};
struct MacFInfoHeader:SubBlockHeader
{
uint fileType;
uint fileCreator;
};
#endif

24
src/unrar/isnt.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "rar.hpp"
#ifdef _WIN_ALL
DWORD WinNT()
{
static int dwPlatformId=-1;
static DWORD dwMajorVersion,dwMinorVersion;
if (dwPlatformId==-1)
{
OSVERSIONINFO WinVer;
WinVer.dwOSVersionInfoSize=sizeof(WinVer);
GetVersionEx(&WinVer);
dwPlatformId=WinVer.dwPlatformId;
dwMajorVersion=WinVer.dwMajorVersion;
dwMinorVersion=WinVer.dwMinorVersion;
}
DWORD Result=0;
if (dwPlatformId==VER_PLATFORM_WIN32_NT)
Result=dwMajorVersion*0x100+dwMinorVersion;
return(Result);
}
#endif

11
src/unrar/isnt.hpp Normal file
View File

@ -0,0 +1,11 @@
#ifndef _RAR_ISNT_
#define _RAR_ISNT_
enum WINNT_VERSION {
WNT_NONE=0,WNT_NT351=0x0333,WNT_NT4=0x0400,WNT_W2000=0x0500,
WNT_WXP=0x0501,WNT_W2003=0x0502,WNT_VISTA=0x0600,WNT_W7=0x0601
};
DWORD WinNT();
#endif

42
src/unrar/license.txt Normal file
View File

@ -0,0 +1,42 @@
****** ***** ****** UnRAR - free utility for RAR archives
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
****** ******* ****** License for use and distribution of
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** ** ** ** ** ** FREE portable version
~~~~~~~~~~~~~~~~~~~~~
The source code of UnRAR utility is freeware. This means:
1. All copyrights to RAR and the utility UnRAR are exclusively
owned by the author - Alexander Roshal.
2. UnRAR source code may be used in any software to handle
RAR archives without limitations free of charge, but cannot be
used to develop RAR (WinRAR) compatible archiver and to
re-create RAR compression algorithm, which is proprietary.
Distribution of modified UnRAR source code in separate form
or as a part of other software is permitted, provided that
full text of this paragraph, starting from "UnRAR source code"
words, is included in license, or in documentation if license
is not available, and in source code comments of resulting package.
3. The UnRAR utility may be freely distributed. It is allowed
to distribute UnRAR inside of other software packages.
4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
OR MISUSING THIS SOFTWARE.
5. Installing and using the UnRAR utility signifies acceptance of
these terms and conditions of the license.
6. If you don't agree with terms of the license you must remove
UnRAR files from your storage devices and cease to use the
utility.
Thank you for your interest in RAR and UnRAR.
Alexander L. Roshal

391
src/unrar/list.cpp Normal file
View File

@ -0,0 +1,391 @@
#include "rar.hpp"
static void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare);
static void ListSymLink(Archive &Arc);
static void ListFileAttr(uint A,int HostOS);
static void ListOldSubHeader(Archive &Arc);
static void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical);
void ListArchive(CommandData *Cmd)
{
int64 SumPackSize=0,SumUnpSize=0;
uint ArcCount=0,SumFileCount=0;
bool Technical=(Cmd->Command[1]=='T');
bool Bare=(Cmd->Command[1]=='B');
bool Verbose=(*Cmd->Command=='V');
char ArcName[NM];
wchar ArcNameW[NM];
while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
{
Archive Arc(Cmd);
#ifdef _WIN_ALL
Arc.RemoveSequentialFlag();
#endif
if (!Arc.WOpen(ArcName,ArcNameW))
continue;
bool FileMatched=true;
while (1)
{
int64 TotalPackSize=0,TotalUnpSize=0;
uint FileCount=0;
if (Arc.IsArchive(true))
{
// if (!Arc.IsOpened())
// break;
bool TitleShown=false;
if (!Bare)
{
Arc.ViewComment();
mprintf("\n");
if (Arc.Solid)
mprintf(St(MListSolid));
if (Arc.SFXSize>0)
mprintf(St(MListSFX));
if (Arc.Volume)
if (Arc.Solid)
mprintf(St(MListVol1));
else
mprintf(St(MListVol2));
else
if (Arc.Solid)
mprintf(St(MListArc1));
else
mprintf(St(MListArc2));
mprintf(" %s\n",Arc.FileName);
if (Technical)
{
if (Arc.Protected)
mprintf(St(MListRecRec));
if (Arc.Locked)
mprintf(St(MListLock));
}
}
while(Arc.ReadHeader()>0)
{
int HeaderType=Arc.GetHeaderType();
if (HeaderType==ENDARC_HEAD)
break;
switch(HeaderType)
{
case FILE_HEAD:
IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName);
FileMatched=Cmd->IsProcessFile(Arc.NewLhd)!=0;
if (FileMatched)
{
ListFileHeader(Arc.NewLhd,Verbose,Technical,TitleShown,Bare);
if (!(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
{
TotalUnpSize+=Arc.NewLhd.FullUnpSize;
FileCount++;
}
TotalPackSize+=Arc.NewLhd.FullPackSize;
if (Technical)
ListSymLink(Arc);
#ifndef SFX_MODULE
if (Verbose)
Arc.ViewFileComment();
#endif
}
break;
#ifndef SFX_MODULE
case SUB_HEAD:
if (Technical && FileMatched && !Bare)
ListOldSubHeader(Arc);
break;
#endif
case NEWSUB_HEAD:
if (FileMatched && !Bare)
{
if (Technical)
ListFileHeader(Arc.SubHead,Verbose,true,TitleShown,false);
ListNewSubHeader(Cmd,Arc,Technical);
}
break;
}
Arc.SeekToNext();
}
if (!Bare)
if (TitleShown)
{
mprintf("\n");
for (int I=0;I<79;I++)
mprintf("-");
char UnpSizeText[20];
itoa(TotalUnpSize,UnpSizeText);
char PackSizeText[20];
itoa(TotalPackSize,PackSizeText);
mprintf("\n%5lu %16s %8s %3d%%",FileCount,UnpSizeText,
PackSizeText,ToPercentUnlim(TotalPackSize,TotalUnpSize));
SumFileCount+=FileCount;
SumUnpSize+=TotalUnpSize;
SumPackSize+=TotalPackSize;
#ifndef SFX_MODULE
if (Arc.EndArcHead.Flags & EARC_VOLNUMBER)
{
mprintf(" ");
mprintf(St(MVolumeNumber),Arc.EndArcHead.VolNumber+1);
}
#endif
mprintf("\n");
}
else
mprintf(St(MListNoFiles));
ArcCount++;
#ifndef NOVOLUME
if (Cmd->VolSize!=0 && ((Arc.NewLhd.Flags & LHD_SPLIT_AFTER) ||
Arc.GetHeaderType()==ENDARC_HEAD &&
(Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)!=0) &&
MergeArchive(Arc,NULL,false,*Cmd->Command))
{
Arc.Seek(0,SEEK_SET);
}
else
#endif
break;
}
else
{
if (Cmd->ArcNames->ItemsCount()<2 && !Bare)
mprintf(St(MNotRAR),Arc.FileName);
break;
}
}
}
if (ArcCount>1 && !Bare)
{
char UnpSizeText[20],PackSizeText[20];
itoa(SumUnpSize,UnpSizeText);
itoa(SumPackSize,PackSizeText);
mprintf("\n%5lu %16s %8s %3d%%\n",SumFileCount,UnpSizeText,
PackSizeText,ToPercentUnlim(SumPackSize,SumUnpSize));
}
}
void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare)
{
if (!Bare)
{
if (!TitleShown)
{
if (Verbose)
mprintf(St(MListPathComm));
else
mprintf(St(MListName));
mprintf(St(MListTitle));
if (Technical)
mprintf(St(MListTechTitle));
for (int I=0;I<79;I++)
mprintf("-");
TitleShown=true;
}
if (hd.HeadType==NEWSUB_HEAD)
mprintf(St(MSubHeadType),hd.FileName);
mprintf("\n%c",(hd.Flags & LHD_PASSWORD) ? '*' : ' ');
}
char *Name=hd.FileName;
#ifdef UNICODE_SUPPORTED
char ConvertedName[NM];
if ((hd.Flags & LHD_UNICODE)!=0 && *hd.FileNameW!=0 && UnicodeEnabled())
{
if (WideToChar(hd.FileNameW,ConvertedName) && *ConvertedName!=0)
Name=ConvertedName;
}
#endif
if (Bare)
{
mprintf("%s\n",Verbose ? Name:PointToName(Name));
return;
}
if (Verbose)
mprintf("%s\n%12s ",Name,"");
else
mprintf("%-12s",PointToName(Name));
char UnpSizeText[20],PackSizeText[20];
if (hd.FullUnpSize==INT64NDF)
strcpy(UnpSizeText,"?");
else
itoa(hd.FullUnpSize,UnpSizeText);
itoa(hd.FullPackSize,PackSizeText);
mprintf(" %8s %8s ",UnpSizeText,PackSizeText);
if ((hd.Flags & LHD_SPLIT_BEFORE) && (hd.Flags & LHD_SPLIT_AFTER))
mprintf(" <->");
else
if (hd.Flags & LHD_SPLIT_BEFORE)
mprintf(" <--");
else
if (hd.Flags & LHD_SPLIT_AFTER)
mprintf(" -->");
else
mprintf("%3d%%",ToPercentUnlim(hd.FullPackSize,hd.FullUnpSize));
char DateStr[50];
hd.mtime.GetText(DateStr,false);
mprintf(" %s ",DateStr);
if (hd.HeadType==NEWSUB_HEAD)
mprintf(" %c....B ",(hd.SubFlags & SUBHEAD_FLAGS_INHERITED) ? 'I' : '.');
else
ListFileAttr(hd.FileAttr,hd.HostOS);
mprintf(" %8.8X",hd.FileCRC);
mprintf(" m%d",hd.Method-0x30);
if ((hd.Flags & LHD_WINDOWMASK)<=6*32)
mprintf("%c",((hd.Flags&LHD_WINDOWMASK)>>5)+'a');
else
mprintf(" ");
mprintf(" %d.%d",hd.UnpVer/10,hd.UnpVer%10);
static const char *RarOS[]={
"DOS","OS/2","Windows","Unix","Mac OS","BeOS","WinCE","","",""
};
if (Technical)
mprintf("\n%22s %8s %4s",
(hd.HostOS<ASIZE(RarOS) ? RarOS[hd.HostOS]:""),
(hd.Flags & LHD_SOLID) ? St(MYes):St(MNo),
(hd.Flags & LHD_VERSION) ? St(MYes):St(MNo));
}
void ListSymLink(Archive &Arc)
{
if (Arc.NewLhd.HostOS==HOST_UNIX && (Arc.NewLhd.FileAttr & 0xF000)==0xA000)
if ((Arc.NewLhd.Flags & LHD_PASSWORD)==0)
{
char FileName[NM];
int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1);
Arc.Read(FileName,DataSize);
FileName[DataSize]=0;
mprintf("\n%22s %s","-->",FileName);
}
else
{
// Link data are encrypted. We would need to ask for password
// and initialize decryption routine to display the link target.
mprintf("\n%22s %s","-->","*<-?->");
}
}
void ListFileAttr(uint A,int HostOS)
{
switch(HostOS)
{
case HOST_MSDOS:
case HOST_OS2:
case HOST_WIN32:
case HOST_MACOS:
mprintf(" %c%c%c%c%c%c%c ",
(A & 0x08) ? 'V' : '.',
(A & 0x10) ? 'D' : '.',
(A & 0x01) ? 'R' : '.',
(A & 0x02) ? 'H' : '.',
(A & 0x04) ? 'S' : '.',
(A & 0x20) ? 'A' : '.',
(A & 0x800) ? 'C' : '.');
break;
case HOST_UNIX:
case HOST_BEOS:
switch (A & 0xF000)
{
case 0x4000:
mprintf("d");
break;
case 0xA000:
mprintf("l");
break;
default:
mprintf("-");
break;
}
mprintf("%c%c%c%c%c%c%c%c%c",
(A & 0x0100) ? 'r' : '-',
(A & 0x0080) ? 'w' : '-',
(A & 0x0040) ? ((A & 0x0800) ? 's':'x'):((A & 0x0800) ? 'S':'-'),
(A & 0x0020) ? 'r' : '-',
(A & 0x0010) ? 'w' : '-',
(A & 0x0008) ? ((A & 0x0400) ? 's':'x'):((A & 0x0400) ? 'S':'-'),
(A & 0x0004) ? 'r' : '-',
(A & 0x0002) ? 'w' : '-',
(A & 0x0001) ? 'x' : '-');
break;
}
}
#ifndef SFX_MODULE
void ListOldSubHeader(Archive &Arc)
{
switch(Arc.SubBlockHead.SubType)
{
case EA_HEAD:
mprintf(St(MListEAHead));
break;
case UO_HEAD:
mprintf(St(MListUOHead),Arc.UOHead.OwnerName,Arc.UOHead.GroupName);
break;
case MAC_HEAD:
mprintf(St(MListMACHead1),Arc.MACHead.fileType>>24,Arc.MACHead.fileType>>16,Arc.MACHead.fileType>>8,Arc.MACHead.fileType);
mprintf(St(MListMACHead2),Arc.MACHead.fileCreator>>24,Arc.MACHead.fileCreator>>16,Arc.MACHead.fileCreator>>8,Arc.MACHead.fileCreator);
break;
case BEEA_HEAD:
mprintf(St(MListBeEAHead));
break;
case NTACL_HEAD:
mprintf(St(MListNTACLHead));
break;
case STREAM_HEAD:
mprintf(St(MListStrmHead),Arc.StreamHead.StreamName);
break;
default:
mprintf(St(MListUnkHead),Arc.SubBlockHead.SubType);
break;
}
}
#endif
void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical)
{
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_CMT) &&
(Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0 && !Cmd->DisableComment)
{
Array<byte> CmtData;
size_t ReadSize=Arc.ReadCommentData(&CmtData,NULL);
if (ReadSize!=0)
{
mprintf(St(MFileComment));
OutComment((char *)&CmtData[0],ReadSize);
}
}
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM) &&
(Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0)
{
size_t DestSize=Arc.SubHead.SubData.Size()/2;
wchar DestNameW[NM];
char DestName[NM];
if (DestSize<sizeof(DestName))
{
RawToWide(&Arc.SubHead.SubData[0],DestNameW,DestSize);
DestNameW[DestSize]=0;
WideToChar(DestNameW,DestName);
mprintf("\n %s",DestName);
}
}
}

6
src/unrar/list.hpp Normal file
View File

@ -0,0 +1,6 @@
#ifndef _RAR_LIST_
#define _RAR_LIST_
void ListArchive(CommandData *Cmd);
#endif

357
src/unrar/loclang.hpp Normal file
View File

@ -0,0 +1,357 @@
#define MYesNo "_Yes_No"
#define MYesNoAll "_Yes_No_All"
#define MYesNoAllQ "_Yes_No_All_nEver_Quit"
#define MYesNoAllRenQ "_Yes_No_All_nEver_Rename_Quit"
#define MContinueQuit "_Continue_Quit"
#define MRetryAbort "_Retry_Abort"
#define MCopyright "\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d"
#define MRegTo "\nRegistered to %s\n"
#define MShare "\nTrial version Type RAR -? for help\n"
#define MUCopyright "\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
#define MBeta "beta"
#define MMonthJan "Jan"
#define MMonthFeb "Feb"
#define MMonthMar "Mar"
#define MMonthApr "Apr"
#define MMonthMay "May"
#define MMonthJun "Jun"
#define MMonthJul "Jul"
#define MMonthAug "Aug"
#define MMonthSep "Sep"
#define MMonthOct "Oct"
#define MMonthNov "Nov"
#define MMonthDec "Dec"
#define MRARTitle1 "\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
#define MUNRARTitle1 "\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
#define MRARTitle2 "\n <@listfiles...> <path_to_extract\\>"
#define MCHelpCmd "\n\n<Commands>"
#define MCHelpCmdA "\n a Add files to archive"
#define MCHelpCmdC "\n c Add archive comment"
#define MCHelpCmdCF "\n cf Add files comment"
#define MCHelpCmdCH "\n ch Change archive parameters"
#define MCHelpCmdCW "\n cw Write archive comment to file"
#define MCHelpCmdD "\n d Delete files from archive"
#define MCHelpCmdE "\n e Extract files to current directory"
#define MCHelpCmdF "\n f Freshen files in archive"
#define MCHelpCmdI "\n i[par]=<str> Find string in archives"
#define MCHelpCmdK "\n k Lock archive"
#define MCHelpCmdL "\n l[t,b] List archive [technical, bare]"
#define MCHelpCmdM "\n m[f] Move to archive [files only]"
#define MCHelpCmdP "\n p Print file to stdout"
#define MCHelpCmdR "\n r Repair archive"
#define MCHelpCmdRC "\n rc Reconstruct missing volumes"
#define MCHelpCmdRN "\n rn Rename archived files"
#define MCHelpCmdRR "\n rr[N] Add data recovery record"
#define MCHelpCmdRV "\n rv[N] Create recovery volumes"
#define MCHelpCmdS "\n s[name|-] Convert archive to or from SFX"
#define MCHelpCmdT "\n t Test archive files"
#define MCHelpCmdU "\n u Update files in archive"
#define MCHelpCmdV "\n v[t,b] Verbosely list archive [technical,bare]"
#define MCHelpCmdX "\n x Extract files with full path"
#define MCHelpSw "\n\n<Switches>"
#define MCHelpSwm "\n - Stop switches scanning"
#define MCHelpSwAT "\n @[+] Disable [enable] file lists"
#define MCHelpSwAC "\n ac Clear Archive attribute after compression or extraction"
#define MCHelpSwAD "\n ad Append archive name to destination path"
#define MCHelpSwAG "\n ag[format] Generate archive name using the current date"
#define MCHelpSwAI "\n ai Ignore file attributes"
#define MCHelpSwAO "\n ao Add files with Archive attribute set"
#define MCHelpSwAP "\n ap<path> Set path inside archive"
#define MCHelpSwAS "\n as Synchronize archive contents"
#define MCHelpSwAV "\n av Put authenticity verification (registered versions only)"
#define MCHelpSwAVm "\n av- Disable authenticity verification check"
#define MCHelpSwCm "\n c- Disable comments show"
#define MCHelpSwCFGm "\n cfg- Disable read configuration"
#define MCHelpSwCL "\n cl Convert names to lower case"
#define MCHelpSwCU "\n cu Convert names to upper case"
#define MCHelpSwDF "\n df Delete files after archiving"
#define MCHelpSwDH "\n dh Open shared files"
#define MCHelpSwDR "\n dr Delete files to Recycle Bin"
#define MCHelpSwDS "\n ds Disable name sort for solid archive"
#define MCHelpSwDW "\n dw Wipe files after archiving"
#define MCHelpSwEa "\n e[+]<attr> Set file exclude and include attributes"
#define MCHelpSwED "\n ed Do not add empty directories"
#define MCHelpSwEE "\n ee Do not save and extract extended attributes"
#define MCHelpSwEN "\n en Do not put 'end of archive' block"
#define MCHelpSwEP "\n ep Exclude paths from names"
#define MCHelpSwEP1 "\n ep1 Exclude base directory from names"
#define MCHelpSwEP2 "\n ep2 Expand paths to full"
#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter"
#define MCHelpSwF "\n f Freshen files"
#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers"
#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages"
#define MCHelpSwIEML "\n ieml[addr] Send archive by email"
#define MCHelpSwIERR "\n ierr Send all messages to stderr"
#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)"
#define MCHelpSwINUL "\n inul Disable all messages"
#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation"
#define MCHelpSwISND "\n isnd Enable sound"
#define MCHelpSwK "\n k Lock archive"
#define MCHelpSwKB "\n kb Keep broken extracted files"
#define MCHelpSwLog "\n log[f][=name] Write names to log file"
#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)"
#define MCHelpSwMC "\n mc<par> Set advanced compression parameters"
#define MCHelpSwMD "\n md<size> Dictionary size in KB (64,128,256,512,1024,2048,4096 or A-G)"
#define MCHelpSwMS "\n ms[ext;ext] Specify file types to store"
#define MCHelpSwMT "\n mt<threads> Set the number of threads"
#define MCHelpSwN "\n n<file> Include only specified file"
#define MCHelpSwNa "\n n@ Read file names to include from stdin"
#define MCHelpSwNal "\n n@<list> Include files listed in specified list file"
#define MCHelpSwO "\n o[+|-] Set the overwrite mode"
#define MCHelpSwOC "\n oc Set NTFS Compressed attribute"
#define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file"
#define MCHelpSwOR "\n or Rename files automatically"
#define MCHelpSwOS "\n os Save NTFS streams"
#define MCHelpSwOW "\n ow Save or restore file owner and group"
#define MCHelpSwP "\n p[password] Set password"
#define MCHelpSwPm "\n p- Do not query password"
#define MCHelpSwR "\n r Recurse subdirectories"
#define MCHelpSwRm "\n r- Disable recursion"
#define MCHelpSwR0 "\n r0 Recurse subdirectories for wildcard names only"
#define MCHelpSwRI "\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms"
#define MCHelpSwRR "\n rr[N] Add data recovery record"
#define MCHelpSwRV "\n rv[N] Create recovery volumes"
#define MCHelpSwS "\n s[<N>,v[-],e] Create solid archive"
#define MCHelpSwSm "\n s- Disable solid archiving"
#define MCHelpSwSC "\n sc<chr>[obj] Specify the character set"
#define MCHelpSwSFX "\n sfx[name] Create SFX archive"
#define MCHelpSwSI "\n si[name] Read data from standard input (stdin)"
#define MCHelpSwSL "\n sl<size> Process files with size less than specified"
#define MCHelpSwSM "\n sm<size> Process files with size more than specified"
#define MCHelpSwT "\n t Test files after archiving"
#define MCHelpSwTK "\n tk Keep original archive time"
#define MCHelpSwTL "\n tl Set archive time to latest file"
#define MCHelpSwTN "\n tn<time> Process files newer than <time>"
#define MCHelpSwTO "\n to<time> Process files older than <time>"
#define MCHelpSwTA "\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
#define MCHelpSwTB "\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
#define MCHelpSwTS "\n ts<m,c,a>[N] Save or restore file time (modification, creation, access)"
#define MCHelpSwU "\n u Update files"
#define MCHelpSwV "\n v Create volumes with size autodetection or list all volumes"
#define MCHelpSwVUnr "\n v List all volumes"
#define MCHelpSwVn "\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]"
#define MCHelpSwVD "\n vd Erase disk contents before creating volume"
#define MCHelpSwVER "\n ver[n] File version control"
#define MCHelpSwVN "\n vn Use the old style volume naming scheme"
#define MCHelpSwVP "\n vp Pause before each volume"
#define MCHelpSwW "\n w<path> Assign work directory"
#define MCHelpSwX "\n x<file> Exclude specified file"
#define MCHelpSwXa "\n x@ Read file names to exclude from stdin"
#define MCHelpSwXal "\n x@<list> Exclude files listed in specified list file"
#define MCHelpSwY "\n y Assume Yes on all queries"
#define MCHelpSwZ "\n z[file] Read archive comment from file"
#define MBadArc "\nERROR: Bad archive %s\n"
#define MAskPsw "Enter password (will not be echoed)"
#define MAskPswEcho "Enter password"
#define MReAskPsw "\nReenter password: "
#define MFor " for "
#define MNotMatchPsw "\nERROR: Passwords do not match\n"
#define MErrWrite "Write error in the file %s"
#define MErrRead "Read error in the file %s"
#define MErrSeek "Seek error in the file %s"
#define MErrFClose "Cannot close the file %s"
#define MErrOutMem "Not enough memory"
#define MErrBrokenArc "Corrupt archive - use 'Repair' command"
#define MProgAborted "Program aborted"
#define MErrRename "\nCannot rename %s to %s"
#define MAbsNextVol "\nCannot find volume %s"
#define MBreak "\nUser break\n"
#define MAskCreatVol "\nCreate next volume ?"
#define MAskNextDisk "\nDisk full. Insert next"
#define MCreatVol "\n\nCreating %sarchive %s\n"
#define MAskNextVol "\nInsert disk with %s"
#define MTestVol "\n\nTesting archive %s\n"
#define MExtrVol "\n\nExtracting from %s\n"
#define MConverting "\nConverting %s"
#define MCvtToSFX "\nConvert archives to SFX"
#define MCvtFromSFX "\nRemoving SFX module"
#define MNotSFX "\n%s is not SFX archive"
#define MNotRAR "\n%s is not RAR archive"
#define MNotFirstVol "\n%s is not the first volume"
#define MCvtOldFormat "\n%s - cannot convert to SFX archive with old format"
#define MCannotCreate "\nCannot create %s"
#define MCannotOpen "\nCannot open %s"
#define MUnknownMeth "\nUnknown method in %s"
#define MVerRequired "\nYou need RAR %d.%d to unpack it"
#define MNewRarFormat "\nUnsupported archive format. Please update RAR to a newer version."
#define MOk " OK"
#define MDone "\nDone"
#define MLockingArc "\nLocking archive"
#define MNotMdfOld "\n\nERROR: Cannot modify old format archive"
#define MNotMdfLock "\n\nERROR: Locked archive"
#define MNotMdfVol "\n\nERROR: Cannot modify volume"
#define MVerifyAV "\nVerifying authenticity information ... "
#define MFailedAV " Failed\n"
#define MStrAV1 "\n\nArchive %s"
#define MStrAV2 "\ncreated at %s"
#define MStrAV3 "\nby %s\n"
#define MLogFailedAV "Invalid authenticity information"
#define MAddingAV "\nAdding authenticity verification "
#define MAVOldStyle "\n\nOld style authenticity information"
#define MPackAskReg "\nEvaluation copy. Please register.\n"
#define MCreateArchive "\nCreating %sarchive %s\n"
#define MUpdateArchive "\nUpdating %sarchive %s\n"
#define MAddSolid "solid "
#define MAddFile "\nAdding %-58s "
#define MUpdFile "\nUpdating %-58s "
#define MAddPoints "\n... %-58s "
#define MCannotUpdPswSolid "\nERROR: Cannot update solid archives with password\n"
#define MMoveDelFiles "\n\nDeleting files %s..."
#define MMoveDelDirs "and directories"
#define MMoveDelFile "\nDeleting %-30s"
#define MMoveDeleted " deleted"
#define MMoveNotDeleted " NOT DELETED"
#define MClearAttrib "\n\nClearing attributes..."
#define MMoveDelDir "\nDeleting directory %-30s"
#define MWarErrFOpen "\nWARNING: Cannot open %d %s"
#define MErrOpenFiles "files"
#define MErrOpenFile "file"
#define MAddNoFiles "\nWARNING: No files"
#define MMdfEncrSol "\n%s: encrypted"
#define MCannotMdfEncrSol "\nCannot modify solid archive containing encrypted files"
#define MAddAnalyze "\nAnalyzing archived files: "
#define MRepacking "\nRepacking archived files: "
#define MCRCFailed "\n%-20s - CRC failed"
#define MExtrTest "\n\nTesting archive %s\n"
#define MExtracting "\n\nExtracting from %s\n"
#define MUseCurPsw "\n%s - use current password ?"
#define MCreatDir "\nCreating %-56s"
#define MExtrSkipFile "\nSkipping %-56s"
#define MExtrTestFile "\nTesting %-56s"
#define MExtrFile "\nExtracting %-56s"
#define MExtrPoints "\n... %-56s"
#define MExtrErrMkDir "\nCannot create directory %s"
#define MExtrPrinting "\n------ Printing %s\n\n"
#define MEncrBadCRC "\nCRC failed in the encrypted file %s. Corrupt file or wrong password."
#define MExtrNoFiles "\nNo files to extract"
#define MExtrAllOk "\nAll OK"
#define MExtrTotalErr "\nTotal errors: %ld"
#define MFileExists "\n\n%s already exists. Overwrite it ?"
#define MAskOverwrite "\nOverwrite %s ?"
#define MAskNewName "\nEnter new name: "
#define MLogMainHead "\nThe archive header is corrupt"
#define MLogFileHead "\n%s - the file header is corrupt"
#define MLogCommHead "\nThe comment header is corrupt\n"
#define MLogProtectHead "The data recovery header is corrupt"
#define MReadStdinCmt "\nReading comment from stdin\n"
#define MReadCommFrom "\nReading comment from %s"
#define MDelComment "\nDeleting comment from %s"
#define MAddComment "\nAdding comment to %s"
#define MFCommAdd "\nAdding file comments"
#define MAskFComm "\n\nReading comment for %s : %s from stdin\n"
#define MLogCommBrk "\nThe archive comment is corrupt"
#define MCommAskCont "\nPress 'Enter' to continue or 'Q' to quit:"
#define MLogBrokFCmt "\nThe file comment is corrupt"
#define MWriteCommTo "\nWrite comment to %s"
#define MCommNotPres "\nComment is not present"
#define MDelFrom "\nDeleting from %s"
#define MDeleting "\nDeleting %s"
#define MEraseArc "\nErasing empty archive %s"
#define MNoDelFiles "\nNo files to delete"
#define MLogTitle "\n\n-------- %2d %s %d, archive %s\n"
#define MPathTooLong "\nERROR: Path too long\n"
#define MListSolid "Solid "
#define MListSFX "SFX "
#define MListVol1 "volume"
#define MListVol2 "Volume"
#define MListArc1 "archive"
#define MListArc2 "Archive"
#define MListRecRec "\nRecovery record is present\n"
#define MListLock "\nLock is present\n"
#define MListPathComm "\nPathname/Comment\n "
#define MListName "\n Name "
#define MListTitle " Size Packed Ratio Date Time Attr CRC Meth Ver\n"
#define MListTechTitle " Host OS Solid Old\n"
#define MListEAHead "\n OS/2 extended attributes"
#define MListUOHead "\n Unix Owner/Group data: %-14s %-14s"
#define MListBeEAHead "\n BeOS extended attributes"
#define MListNTACLHead "\n NTFS security data"
#define MListStrmHead "\n NTFS stream: %s"
#define MListUnkHead "\n Unknown subheader type: 0x%04x"
#define MFileComment "\nComment: "
#define MYes "Yes"
#define MNo "No"
#define MListNoFiles " 0 files\n"
#define MRprReconstr "\nReconstructing %s"
#define MRprBuild "\nBuilding %s"
#define MRprOldFormat "\nCannot repair archive with old format"
#define MRprFind "\nFound %s"
#define MRprAskIsSol "\nThe archive header is corrupt. Mark archive as solid ?"
#define MRprNoFiles "\nNo files found"
#define MRprSuspEntry "\n\nSuspicious entry %s"
#define MRprDir "\nDirectory"
#define MRprSuspSize "\nSize %ld Packed %ld"
#define MRprSuspAdd "\nAdd it to archive ?"
#define MLogUnexpEOF "\nUnexpected end of archive"
#define MRepAskReconst "\nReconstruct archive structure ?"
#define MRecScanning "\nScanning..."
#define MRecRNotFound "\nData recovery record not found"
#define MRecRFound "\nData recovery record found"
#define MRecSecDamage "\nSector %ld (offsets %lX...%lX) damaged"
#define MRecCorrected " - data recovered"
#define MRecFailed " - cannot recover data"
#define MAddRecRec "\nAdding data recovery record"
#define MEraseForVolume "\n\nErasing contents of drive %c:\n"
#define MGetOwnersError "\nWARNING: Cannot get %s owner and group\n"
#define MErrGetOwnerID "\nWARNING: Cannot get owner %s ID\n"
#define MErrGetGroupID "\nWARNING: Cannot get group %s ID\n"
#define MOwnersBroken "\nERROR: %s group and owner data are corrupt\n"
#define MSetOwnersError "\nWARNING: Cannot set %s owner and group\n"
#define MErrLnkRead "\nWARNING: Cannot read symbolic link %s"
#define MErrCreateLnk "\nWARNING: Cannot create link %s"
#define MSymLinkExists "\nWARNING: Symbolic link %s already exists"
#define MAskRetryCreate "\nCannot create %s. Retry ?"
#define MListMACHead1 "\n Mac OS file type: %c%c%c%c ; "
#define MListMACHead2 "file creator: %c%c%c%c\n"
#define MDataBadCRC "\n%-20s : packed data CRC failed in volume %s"
#define MFileRO "\n%s is read-only"
#define MACLGetError "\nWARNING: Cannot get %s security data\n"
#define MACLSetError "\nWARNING: Cannot set %s security data\n"
#define MACLBroken "\nERROR: %s security data are corrupt\n"
#define MACLUnknown "\nWARNING: Unknown format of %s security data\n"
#define MStreamBroken "\nERROR: %s stream data are corrupt\n"
#define MStreamUnknown "\nWARNING: Unknown format of %s stream data\n"
#define MInvalidName "\nERROR: Invalid file name %s"
#define MEABroken "\nERROR: %s extended attributes are corrupt\n"
#define MEAUnknHeader "\nWARNING: %s - unknown format of extended attributes\n"
#define MCannotSetEA "\nWARNING: cannot set extended attributes to %s\n"
#define MCannotGetEA "\nERROR: Cannot get extended attributes of %s\n"
#define MShowEA " (+EA)"
#define MSkipEA "\n...skipping extended attributes"
#define MProcessArc "\n\nProcessing archive %s"
#define MSyncScanError "\nFile search errors, cannot synchronize archive"
#define MCorrectingName "\nWARNING: Attempting to correct the invalid file name"
#define MUnpCannotMerge "\nWARNING: You need to start extraction from a previous volume to unpack %s"
#define MUnknownOption "\nERROR: Unknown option: %s"
#define MSubHeadCorrupt "\nERROR: Corrupt data header found, ignored"
#define MSubHeadUnknown "\nWARNING: Unknown data header format, ignored"
#define MSubHeadDataCRC "\nERROR: Corrupt %s data block"
#define MSubHeadType "\nData header type: %s"
#define MScanError "\nCannot read contents of %s"
#define MNotVolume "\n%s is not volume"
#define MRecVolDiffSets "\nERROR: %s and %s belong to different sets"
#define MRecVolMissing "\n%d volumes missing"
#define MRecVolFound "\n%d recovery volumes found"
#define MRecVolAllExist "\nNothing to reconstruct"
#define MRecVolCannotFix "\nReconstruction impossible"
#define MReconstructing "\nReconstructing..."
#define MCreating "\nCreating %s"
#define MRenaming "\nRenaming %s to %s"
#define MNTFSRequired "\nWrite error: only NTFS file system supports files larger than 4 GB"
#define MErrChangeAttr "\nWARNING: Cannot change attributes of %s"
#define MWrongSFXVer "\nERROR: default SFX module does not support RAR %d.%d archives"
#define MCannotEncName "\nCannot encrypt archive already contained encrypted files"
#define MCannotEmail "\nCannot email the file %s"
#define MCopyrightS "\nRAR SFX archive"
#define MSHelpCmd "\n\n<Commands>"
#define MSHelpCmdE "\n -x Extract from archive (default)"
#define MSHelpCmdT "\n -t Test archive files"
#define MSHelpCmdV "\n -v Verbosely list contents of archive"
#define MMaxPathLimit "\nTotal path and file name length must not exceed %d characters"
#define MRecVolLimit "\nTotal number of usual and recovery volumes must not exceed 255"
#define MVolumeNumber "volume %d"
#define MCannotDelete "\nCannot delete %s"
#define MCalcCRC "\nCalculating the control sum"
#define MTooLargeSFXArc "\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB."
#define MCalcCRCAllVol "\nCalculating control sums of all volumes."
#define MNotEnoughDisk "\nERROR: Not enough disk space for %s."

24
src/unrar/log.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "rar.hpp"
static char LogName[NM];
void InitLogOptions(char *LogName)
{
strcpy(::LogName,LogName);
}
#ifndef SILENT
void Log(const char *ArcName,const char *Format,...)
{
safebuf char Msg[2*NM+1024];
va_list ArgPtr;
va_start(ArgPtr,Format);
vsprintf(Msg,Format,ArgPtr);
va_end(ArgPtr);
eprintf("%s",Msg);
}
#endif

18
src/unrar/log.hpp Normal file
View File

@ -0,0 +1,18 @@
#ifndef _RAR_LOG_
#define _RAR_LOG_
void InitLogOptions(char *LogName);
#ifndef SILENT
void Log(const char *ArcName,const char *Format,...);
#endif
#ifdef SILENT
#ifdef __GNUC__
#define Log(args...)
#else
inline void Log(const char *a,const char *b,const char *c=NULL,const char *d=NULL) {}
#endif
#endif
#endif

493
src/unrar/makefile.bcc Normal file
View File

@ -0,0 +1,493 @@
.AUTODEPEND
basepath = $(BASEPATHCC)
binpath = $(basepath)\bin
libpath = $(basepath)\lib
rarpath = .
incpath = $(basepath)\include;$(rarpath)
cc = $(binpath)\bcc32
link = $(binpath)\ilink32
objpath = .
guiopt = -WC -H=$(objpath)\rar.csm
!ifdef SFX_MODULE
guiopt=$(guiopt) -x-
!endif
!ifdef DEBUG
optdeb=-Od -k -vi- -DDEBUG
!else
# -O is not safe to use with -pr and int64 return values, so let's turn it off
optdeb=-O1 -O- -k-
#optdeb=-Ob -Oe -Og -Oi -Ol -Om -Op -OS -Ov -Z -Oc
!endif
optunrar=-DUNRAR
linkdest=unrar.exe
!ifdef SFX_MODULE
optunrar=-DUNRAR -DSFX_MODULE
linkdest=sfx.exe
!endif
linkopt = -L$(libpath) -ap -c -v -s -V4.0 -Gn
compopt = -P -c -I$(incpath) -R -v -vi -w-pch -w-par -K -f-\
-ff- -a4 -pr -RT- $(optdeb) $(guiopt) $(optunrar) -d -w-8072
!ifdef RARDLL
SILENT=true
linkdest=unrar.dll
linkopt=$(linkopt) -Tpd
compopt=$(compopt) -DRARDLL
!else
linkopt=$(linkopt) -Tpe -B:0x400000
!endif
!ifdef SILENT
compopt=$(compopt) -DSILENT
!endif
rar: $(linkdest)
Dep_SFX= \
$(objpath)\strlist.obj\
$(objpath)\strfn.obj\
$(objpath)\pathfn.obj\
$(objpath)\secpassword.obj\
$(objpath)\cmddata.obj\
$(objpath)\consio.obj\
$(objpath)\savepos.obj\
$(objpath)\smallfn.obj\
$(objpath)\file.obj\
$(objpath)\filefn.obj\
$(objpath)\filcreat.obj\
$(objpath)\sha1.obj\
$(objpath)\archive.obj\
$(objpath)\arcread.obj\
$(objpath)\unicode.obj\
$(objpath)\system.obj\
$(objpath)\isnt.obj\
$(objpath)\crc.obj\
$(objpath)\crypt.obj\
$(objpath)\rijndael.obj\
$(objpath)\rawread.obj\
$(objpath)\encname.obj\
$(objpath)\resource.obj\
$(objpath)\match.obj\
$(objpath)\find.obj\
$(objpath)\timefn.obj\
$(objpath)\getbits.obj\
$(objpath)\rarvm.obj\
$(objpath)\rdwrfn.obj\
$(objpath)\options.obj\
$(objpath)\ulinks.obj\
$(objpath)\errhnd.obj\
$(objpath)\volume.obj\
$(objpath)\rs.obj\
$(objpath)\recvol.obj\
$(objpath)\extinfo.obj\
$(objpath)\extract.obj\
$(objpath)\unpack.obj\
$(objpath)\rar.obj\
$(objpath)\global.obj
Dep_Unrar = \
$(objpath)\filestr.obj\
$(objpath)\scantree.obj
Dep_Dll = \
$(objpath)\dll.obj
#Dep_SFXOnly = $(objpath)\rtl.obj
!ifndef GUI
!ifndef SILENT
Dep_Console = \
$(objpath)\list.obj
!endif
!endif
!ifdef SFX_MODULE
Dep = $(Dep_SFX) $(Dep_SFXOnly)
!else
Dep = $(Dep_SFX) $(Dep_Unrar)
!endif
!ifndef GUI
Dep = $(Dep) $(Dep_Console)
!endif
!ifdef RARDLL
Dep = $(Dep) $(Dep_Dll)
!endif
!ifdef GUI
$(linkdest) : $(Dep)
echo Done
!else
$(linkdest) : $(Dep)
$(link) @&&|
$(linkopt) +
#!ifdef SFX_MODULE
#$(objpath)\dummy.obj+
#$(objpath)\ll.obj+
#$(objpath)\rtl.obj+
#!else
!ifdef RARDLL
$(libpath)\c0d32.obj+
!else
$(libpath)\c0x32.obj+
!endif
#!endif
$(objpath)\strlist.obj+
$(objpath)\strfn.obj+
$(objpath)\pathfn.obj+
$(objpath)\savepos.obj+
$(objpath)\smallfn.obj+
$(objpath)\global.obj+
$(objpath)\file.obj+
$(objpath)\filefn.obj+
$(objpath)\filcreat.obj+
$(objpath)\sha1.obj+
$(objpath)\archive.obj+
$(objpath)\arcread.obj+
$(objpath)\unicode.obj+
$(objpath)\system.obj+
$(objpath)\isnt.obj+
$(objpath)\crc.obj+
$(objpath)\crypt.obj+
$(objpath)\rijndael.obj+
$(objpath)\rawread.obj+
$(objpath)\encname.obj+
$(objpath)\resource.obj+
$(objpath)\match.obj+
$(objpath)\find.obj+
!ifndef SFX_MODULE
$(objpath)\filestr.obj+
$(objpath)\scantree.obj+
!endif
$(objpath)\timefn.obj+
$(objpath)\getbits.obj+
$(objpath)\rarvm.obj+
$(objpath)\rdwrfn.obj+
$(objpath)\consio.obj+
$(objpath)\secpassword.obj+
$(objpath)\cmddata.obj+
$(objpath)\options.obj+
$(objpath)\ulinks.obj+
$(objpath)\volume.obj+
$(objpath)\extinfo.obj+
$(objpath)\extract.obj+
$(objpath)\rs.obj+
$(objpath)\recvol.obj+
!ifndef SILENT
!ifndef GUI
$(objpath)\list.obj+
!endif
!endif
!ifdef RARDLL
$(objpath)\dll.obj+
!endif
$(objpath)\errhnd.obj+
$(objpath)\unpack.obj+
$(objpath)\rar.obj
$<,$*
$(libpath)\cw32.lib+
$(libpath)\import32.lib
!ifdef RARDLL
$(rarpath)\dll.def
!else
!endif
|
!endif
$(objpath)\rar.obj : $(rarpath)\rar.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rar.cpp
|
$(objpath)\strlist.obj : $(rarpath)\strlist.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\strlist.cpp
|
$(objpath)\strfn.obj : $(rarpath)\strfn.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\strfn.cpp
|
$(objpath)\pathfn.obj : $(rarpath)\pathfn.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\pathfn.cpp
|
$(objpath)\savepos.obj : $(rarpath)\savepos.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\savepos.cpp
|
$(objpath)\smallfn.obj : $(rarpath)\smallfn.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\smallfn.cpp
|
$(objpath)\global.obj : $(rarpath)\global.cpp
$(cc) -q @&&|
$(compopt) -H- -o$@ $(rarpath)\global.cpp
|
$(objpath)\file.obj : $(rarpath)\file.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\file.cpp
|
$(objpath)\filefn.obj : $(rarpath)\filefn.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\filefn.cpp
|
$(objpath)\filestr.obj : $(rarpath)\filestr.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\filestr.cpp
|
$(objpath)\filcreat.obj : $(rarpath)\filcreat.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\filcreat.cpp
|
$(objpath)\sha1.obj : $(rarpath)\sha1.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\sha1.cpp
|
$(objpath)\archive.obj : $(rarpath)\archive.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\archive.cpp
|
$(objpath)\arcread.obj : $(rarpath)\arcread.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\arcread.cpp
|
$(objpath)\unicode.obj : $(rarpath)\unicode.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\unicode.cpp
|
$(objpath)\system.obj : $(rarpath)\system.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\system.cpp
|
$(objpath)\isnt.obj : $(rarpath)\isnt.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\isnt.cpp
|
$(objpath)\crc.obj : $(rarpath)\crc.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\crc.cpp
|
$(objpath)\crypt.obj : $(rarpath)\crypt.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\crypt.cpp
|
$(objpath)\rijndael.obj : $(rarpath)\rijndael.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rijndael.cpp
|
$(objpath)\rawread.obj : $(rarpath)\rawread.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rawread.cpp
|
$(objpath)\rawwrite.obj : $(rarpath)\rawwrite.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rawwrite.cpp
|
$(objpath)\encname.obj : $(rarpath)\encname.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\encname.cpp
|
$(objpath)\resource.obj : $(rarpath)\resource.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\resource.cpp
|
$(objpath)\match.obj : $(rarpath)\match.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\match.cpp
|
$(objpath)\find.obj : $(rarpath)\find.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\find.cpp
|
$(objpath)\scantree.obj : $(rarpath)\scantree.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\scantree.cpp
|
$(objpath)\timefn.obj : $(rarpath)\timefn.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\timefn.cpp
|
$(objpath)\getbits.obj : $(rarpath)\getbits.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\getbits.cpp
|
$(objpath)\rarvm.obj : $(rarpath)\rarvm.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rarvm.cpp
|
$(objpath)\putbits.obj : $(rarpath)\putbits.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\putbits.cpp
|
$(objpath)\pack.obj : $(rarpath)\pack.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\pack.cpp
|
$(objpath)\packbord.obj : $(rarpath)\packbord.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\packbord.cpp
|
$(objpath)\packanlz.obj : $(rarpath)\packanlz.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\packanlz.cpp
|
$(objpath)\cblock.obj : $(rarpath)\cblock.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\cblock.cpp
|
$(objpath)\add.obj : $(rarpath)\add.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\add.cpp
|
$(objpath)\addlist.obj : $(rarpath)\addlist.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\addlist.cpp
|
$(objpath)\procarc.obj : $(rarpath)\procarc.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\procarc.cpp
|
$(objpath)\sfx.obj : $(rarpath)\sfx.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\sfx.cpp
|
$(objpath)\comment.obj : $(rarpath)\comment.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\comment.cpp
|
$(objpath)\rs.obj : $(rarpath)\rs.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rs.cpp
|
$(objpath)\recvol.obj : $(rarpath)\recvol.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\recvol.cpp
|
$(objpath)\repair.obj : $(rarpath)\repair.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\repair.cpp
|
$(objpath)\rdwrfn.obj : $(rarpath)\rdwrfn.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rdwrfn.cpp
|
$(objpath)\consio.obj : $(rarpath)\consio.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\consio.cpp
|
$(objpath)\secpassword.obj : $(rarpath)\secpassword.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\secpassword.cpp
|
$(objpath)\cmddata.obj : $(rarpath)\cmddata.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\cmddata.cpp
|
$(objpath)\options.obj : $(rarpath)\options.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\options.cpp
|
$(objpath)\ulinks.obj : $(rarpath)\ulinks.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\ulinks.cpp
|
$(objpath)\errhnd.obj : $(rarpath)\errhnd.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\errhnd.cpp
|
$(objpath)\volume.obj : $(rarpath)\volume.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\volume.cpp
|
$(objpath)\extinfo.obj : $(rarpath)\extinfo.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\extinfo.cpp
|
$(objpath)\extract.obj : $(rarpath)\extract.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\extract.cpp
|
$(objpath)\list.obj : $(rarpath)\list.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\list.cpp
|
$(objpath)\rtl.obj : $(rarpath)\rtl.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\rtl.cpp
|
$(objpath)\unpack.obj : $(rarpath)\unpack.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\unpack.cpp
|
$(objpath)\dll.obj : $(rarpath)\dll.cpp
$(cc) -q @&&|
$(compopt) -o$@ $(rarpath)\dll.cpp
|

50
src/unrar/makefile.dj Normal file
View File

@ -0,0 +1,50 @@
#
# Makefile for DJGPP - unrar
#
# Note: you have to 'make clean' before you can build
# the sfx module
#
# DOS32 using DJGPP 2.03 Patchlevel 2 and GCC 2.95.3
CXX = gpp
CXXFLAGS = -O2 -Wno-deprecated
#DEFINES = -D_MSC_VER -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
##########################
.PHONY: all clean veryclean
COMPILE=$(CXX) $(CXXFLAGS) $(DEFINES)
LINK=$(CXX)
UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o
OBJECTS=rar.o strlist.o strfn.o pathfn.o savepos.o smallfn.o global.o \
file.o filefn.o filcreat.o archive.o arcread.o unicode.o \
system.o isnt.o crypt.o crc.o rawread.o encname.o \
resource.o match.o timefn.o rdwrfn.o consio.o options.o \
ulinks.o errhnd.o rarvm.o rijndael.o getbits.o sha1.o \
extinfo.o extract.o volume.o list.o find.o unpack.o secpassword.o cmddata.o
.cpp.o:
$(COMPILE) -D$(WHAT) -c $<
all: unrar
unrar: WHAT=UNRAR
unrar: $(OBJECTS) $(UNRAR_OBJ)
$(LINK) -Wl,-s -o unrar.exe $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
exe2coff unrar.exe
cp -u $(DJDIR)/bin/cwsdstub.exe .
copy /b cwsdstub.exe+unrar unrar.exe
-upx --ultra-brute unrar.exe
sfx: WHAT=SFX_MODULE
sfx: $(OBJECTS)
$(LINK) -Wl,-s -o default.sfx $(LDFLAGS) $(OBJECTS) -DSFX_MODULE
clean:
$(RM) $(OBJECTS) $(UNRAR_OBJ)
veryclean: clean
$(RM) unrar.exe default.sfx cwsdstub.exe unrar

54
src/unrar/makefile.dmc Normal file
View File

@ -0,0 +1,54 @@
# Makefile for Digital Mars C++ Compiler
# http://www.rarlab.com
# http://www.digitalmars.com
#
# DEFINES: UNRAR RARDLL GUI SFX_MODULE SILENT
NAME = unrar
EXT = exe
CPP = dmc
LINK = link
# --------------
# Release Build
# --------------
DEFINES = -DNDEBUG -D_MSC_VER -DUNRAR
CPPFLAGS = -o+all -ff -Nc -g- -Ae
LNKFLAGS = /EXETYPE:NT /MACHINE:i386 /SUBSYSTEM:CONSOLE /NOLOGO /NODEBUG /NOCODEVIEW /PACKFUNCTIONS
# --------------
# Debug Build
# --------------
#DEFINES = -D_DEBUG -D_MSC_VER -DUNRAR
#CPPFLAGS = -o+none -Nc -S -gf -Ae
#LNKFLAGS = /EXETYPE:NT /MACHINE:i386 /SUBSYSTEM:CONSOLE /NOLOGO /DEBUG
OBJ = rar.obj strlist.obj strfn.obj pathfn.obj savepos.obj smallfn.o global.obj \
file.obj filefn.obj filcreat.obj archive.obj arcread.obj unicode.obj \
system.obj isnt.obj crypt.obj crc.obj rawread.obj encname.obj \
resource.obj match.obj timefn.obj rdwrfn.obj consio.obj options.obj \
ulinks.obj errhnd.obj rarvm.obj rijndael.obj getbits.obj sha1.obj \
extinfo.obj extract.obj volume.obj find.obj unpack.obj cmddata.obj \
secpassword.obj filestr.obj recvol.obj rs.obj scantree.obj \
list.obj \
# dll.obj \
LIB = kernel32.lib+user32.lib+advapi32.lib
#DEF = dll.def
link: $(OBJ)
$(LINK) $(LNKFLAGS) $(OBJ), $(NAME).$(EXT), $(NAME).map, $(LIB), $(DEF)
.c.obj:
$(CPP) $(CPPFLAGS) $(DEFINES) -c $< -o $@
.cpp.obj:
$(CPP) $(CPPFLAGS) $(DEFINES) -c $< -o $@
clean:
del $(OBJ)
del $(NAME).$(EXT)
del $(NAME).map

146
src/unrar/makefile.unix Normal file
View File

@ -0,0 +1,146 @@
#
# Makefile for UNIX - unrar
# Linux using GCC
CXX=g++
CXXFLAGS=-O2
LIBFLAGS=-fPIC
DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
STRIP=strip
DESTDIR=/usr
# Linux using LCC
#CXX=lcc
#CXXFLAGS=-O2
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=strip
#DESTDIR=/usr
# HP UX using aCC
#CXX=aCC
#CXXFLAGS=-AA +O2 +Onolimit
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=strip
#DESTDIR=/usr
# IRIX using GCC
#CXX=g++
#CXXFLAGS=-O2
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1
#STRIP=strip
#DESTDIR=/usr
# IRIX using MIPSPro (experimental)
#CXX=CC
#CXXFLAGS=-O2 -mips3 -woff 1234,1156,3284 -LANG:std
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -Dint64=int64_t
#STRIP=strip
#DESTDIR=/usr
# AIX using xlC (IBM VisualAge C++ 5.0)
#CXX=xlC
#CXXFLAGS=-O -qinline -qro -qroconst -qmaxmem=16384 -qcpluscmt
#DEFINES=-D_LARGE_FILES -D_LARGE_FILE_API
#LIBS=-lbsd
#STRIP=strip
#DESTDIR=/usr
# Solaris using CC
#CXX=CC
#CXXFLAGS=-fast -erroff=wvarhidemem
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=strip
#DESTDIR=/usr
# Solaris using GCC (optimized for UltraSPARC 1 CPU)
#CXX=g++
#CXXFLAGS=-O3 -mcpu=v9 -mtune=ultrasparc -m32
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=/usr/ccs/bin/strip
#DESTDIR=/usr
# Tru64 5.1B using GCC3
#CXX=g++
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_XOPEN_SOURCE=500
#STRIP=strip
#LDFLAGS=-rpath /usr/local/gcc/lib
#DESTDIR=/usr
# Tru64 5.1B using DEC C++
#CXX=cxx
#CXXFLAGS=-O4 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Dint64=long
#STRIP=strip
#LDFLAGS=
#DESTDIR=/usr
# QNX 6.x using GCC
#CXX=g++
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fexceptions
#STRIP=strip
#LDFLAGS=-fexceptions
#DESTDIR=/usr
# Cross-compile
# Linux using arm-linux-g++
#CXX=arm-linux-g++
#CXXFLAGS=-O2
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=arm-linux-strip
#LDFLAGS=-static
#DESTDIR=/usr
##########################
COMPILE=$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES)
LINK=$(CXX)
WHAT=UNRAR
UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o
LIB_OBJ=filestr.o scantree.o dll.o
OBJECTS=rar.o strlist.o strfn.o pathfn.o savepos.o smallfn.o global.o file.o filefn.o filcreat.o \
archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
resource.o match.o timefn.o rdwrfn.o consio.o options.o ulinks.o errhnd.o rarvm.o secpassword.o \
rijndael.o getbits.o sha1.o extinfo.o extract.o volume.o list.o find.o unpack.o cmddata.o
.cpp.o:
$(COMPILE) -D$(WHAT) -c $<
all: unrar
install: install-unrar
uninstall: uninstall-unrar
clean:
@rm -f *.o *.bak *~
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
@rm -f unrar
$(LINK) -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
$(STRIP) unrar
sfx: WHAT=SFX_MODULE
sfx: clean $(OBJECTS)
@rm -f default.sfx
$(LINK) -o default.sfx $(LDFLAGS) $(OBJECTS)
$(STRIP) default.sfx
lib: WHAT=RARDLL
lib: CXXFLAGS+=$(LIBFLAGS)
lib: clean $(OBJECTS) $(LIB_OBJ)
@rm -f libunrar.so
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
install-unrar:
install -D unrar $(DESTDIR)/bin/unrar
uninstall-unrar:
rm -f $(DESTDIR)/bin/unrar
install-lib:
install libunrar.so $(DESTDIR)/lib
uninstall-lib:
rm -f $(DESTDIR)/lib/libunrar.so

300
src/unrar/match.cpp Normal file
View File

@ -0,0 +1,300 @@
#include "rar.hpp"
static bool match(const char *pattern,const char *string,bool ForceCase);
static bool match(const wchar *pattern,const wchar *string,bool ForceCase);
static int mstricompc(const char *Str1,const char *Str2,bool ForceCase);
static int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase);
static int mstrnicompc(const char *Str1,const char *Str2,size_t N,bool ForceCase);
static int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase);
inline uint toupperc(byte ch,bool ForceCase)
{
if (ForceCase)
return(ch);
#ifdef _WIN_ALL
return((uint)(LPARAM)CharUpper((LPTSTR)(ch)));
#elif defined(_UNIX)
return(ch);
#else
return(toupper(ch));
#endif
}
inline uint touppercw(uint ch,bool ForceCase)
{
if (ForceCase)
return(ch);
#if defined(_UNIX)
return(ch);
#else
return(toupperw(ch));
#endif
}
bool CmpName(const char *Wildcard,const char *Name,int CmpMode)
{
bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0;
CmpMode&=MATCH_MODEMASK;
if (CmpMode!=MATCH_NAMES)
{
size_t WildLength=strlen(Wildcard);
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH &&
mstrnicompc(Wildcard,Name,WildLength,ForceCase)==0)
{
// For all modes except MATCH_NAMES, MATCH_EXACT and MATCH_EXACTPATH
// "path1" mask must match "path1\path2\filename.ext" and "path1" names.
char NextCh=Name[WildLength];
if (NextCh=='\\' || NextCh=='/' || NextCh==0)
return(true);
}
// Nothing more to compare for MATCH_SUBPATHONLY.
if (CmpMode==MATCH_SUBPATHONLY)
return(false);
char Path1[NM],Path2[NM];
GetFilePath(Wildcard,Path1,ASIZE(Path1));
GetFilePath(Name,Path2,ASIZE(Path1));
if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
mstricompc(Path1,Path2,ForceCase)!=0)
return(false);
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
if (IsWildcard(Path1))
return(match(Wildcard,Name,ForceCase));
else
if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard))
{
if (*Path1 && mstrnicompc(Path1,Path2,strlen(Path1),ForceCase)!=0)
return(false);
}
else
if (mstricompc(Path1,Path2,ForceCase)!=0)
return(false);
}
char *Name1=PointToName(Wildcard);
char *Name2=PointToName(Name);
// Always return false for RAR temporary files to exclude them
// from archiving operations.
if (mstrnicompc("__rar_",Name2,6,false)==0)
return(false);
if (CmpMode==MATCH_EXACT)
return(mstricompc(Name1,Name2,ForceCase)==0);
return(match(Name1,Name2,ForceCase));
}
#ifndef SFX_MODULE
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
{
bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0;
CmpMode&=MATCH_MODEMASK;
if (CmpMode!=MATCH_NAMES)
{
size_t WildLength=wcslen(Wildcard);
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH &&
mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
{
// For all modes except MATCH_NAMES, MATCH_EXACT and MATCH_EXACTPATH
// "path1" mask must match "path1\path2\filename.ext" and "path1" names.
wchar NextCh=Name[WildLength];
if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
return(true);
}
// Nothing more to compare for MATCH_SUBPATHONLY.
if (CmpMode==MATCH_SUBPATHONLY)
return(false);
wchar Path1[NM],Path2[NM];
GetFilePath(Wildcard,Path1,ASIZE(Path1));
GetFilePath(Name,Path2,ASIZE(Path2));
if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
mwcsicompc(Path1,Path2,ForceCase)!=0)
return(false);
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
if (IsWildcard(NULL,Path1))
return(match(Wildcard,Name,ForceCase));
else
if (CmpMode==MATCH_SUBPATH || IsWildcard(NULL,Wildcard))
{
if (*Path1 && mwcsnicompc(Path1,Path2,wcslen(Path1),ForceCase)!=0)
return(false);
}
else
if (mwcsicompc(Path1,Path2,ForceCase)!=0)
return(false);
}
wchar *Name1=PointToName(Wildcard);
wchar *Name2=PointToName(Name);
// Always return false for RAR temporary files to exclude them
// from archiving operations.
if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
return(false);
if (CmpMode==MATCH_EXACT)
return(mwcsicompc(Name1,Name2,ForceCase)==0);
return(match(Name1,Name2,ForceCase));
}
#endif
bool match(const char *pattern,const char *string,bool ForceCase)
{
for (;; ++string)
{
char stringc=toupperc(*string,ForceCase);
char patternc=toupperc(*pattern++,ForceCase);
switch (patternc)
{
case 0:
return(stringc==0);
case '?':
if (stringc == 0)
return(false);
break;
case '*':
if (*pattern==0)
return(true);
if (*pattern=='.')
{
if (pattern[1]=='*' && pattern[2]==0)
return(true);
const char *dot=strchr(string,'.');
if (pattern[1]==0)
return (dot==NULL || dot[1]==0);
if (dot!=NULL)
{
string=dot;
if (strpbrk(pattern,"*?")==NULL && strchr(string+1,'.')==NULL)
return(mstricompc(pattern+1,string+1,ForceCase)==0);
}
}
while (*string)
if (match(pattern,string++,ForceCase))
return(true);
return(false);
default:
if (patternc != stringc)
{
// Allow "name." mask match "name" and "name.\" match "name\".
if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.'))
return(match(pattern,string,ForceCase));
else
return(false);
}
break;
}
}
}
#ifndef SFX_MODULE
bool match(const wchar *pattern,const wchar *string,bool ForceCase)
{
for (;; ++string)
{
wchar stringc=touppercw(*string,ForceCase);
wchar patternc=touppercw(*pattern++,ForceCase);
switch (patternc)
{
case 0:
return(stringc==0);
case '?':
if (stringc == 0)
return(false);
break;
case '*':
if (*pattern==0)
return(true);
if (*pattern=='.')
{
if (pattern[1]=='*' && pattern[2]==0)
return(true);
const wchar *dot=wcschr(string,'.');
if (pattern[1]==0)
return (dot==NULL || dot[1]==0);
if (dot!=NULL)
{
string=dot;
if (wcspbrk(pattern,L"*?")==NULL && wcschr(string+1,'.')==NULL)
return(mwcsicompc(pattern+1,string+1,ForceCase)==0);
}
}
while (*string)
if (match(pattern,string++,ForceCase))
return(true);
return(false);
default:
if (patternc != stringc)
{
// Allow "name." mask match "name" and "name.\" match "name\".
if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.'))
return(match(pattern,string,ForceCase));
else
return(false);
}
break;
}
}
}
#endif
int mstricompc(const char *Str1,const char *Str2,bool ForceCase)
{
if (ForceCase)
return(strcmp(Str1,Str2));
return(stricompc(Str1,Str2));
}
#ifndef SFX_MODULE
int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase)
{
if (ForceCase)
return(wcscmp(Str1,Str2));
return(wcsicompc(Str1,Str2));
}
#endif
int mstrnicompc(const char *Str1,const char *Str2,size_t N,bool ForceCase)
{
if (ForceCase)
return(strncmp(Str1,Str2,N));
#if defined(_UNIX)
return(strncmp(Str1,Str2,N));
#else
return(strnicomp(Str1,Str2,N));
#endif
}
#ifndef SFX_MODULE
int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase)
{
if (ForceCase)
return(wcsncmp(Str1,Str2,N));
#if defined(_UNIX)
return(wcsncmp(Str1,Str2,N));
#else
return(wcsnicomp(Str1,Str2,N));
#endif
}
#endif

35
src/unrar/match.hpp Normal file
View File

@ -0,0 +1,35 @@
#ifndef _RAR_MATCH_
#define _RAR_MATCH_
enum {
MATCH_NAMES, // Paths are ignored.
// Compares names only using wildcards.
MATCH_SUBPATHONLY, // Paths must match either exactly or path in wildcard
// must be present in the beginning of file path.
// For example, "c:\path1\*" or "c:\path1" will match
// "c:\path1\path2\file".
// Names are not compared.
MATCH_EXACT, // Paths must match exactly.
// Names must match exactly.
MATCH_EXACTPATH, // Paths must match exactly.
// Names are compared using wildcards.
MATCH_SUBPATH, // Names must be the same, but path in mask is allowed
// to be only a part of name path. In other words,
// we match all files matching the file mask
// in current folder and subfolders.
MATCH_WILDSUBPATH // Works as MATCH_SUBPATH if file mask contains
// wildcards and as MATCH_EXACTPATH otherwise.
};
#define MATCH_MODEMASK 0x0000ffff
#define MATCH_FORCECASESENSITIVE 0x80000000
bool CmpName(const char *Wildcard,const char *Name,int CmpMode);
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode);
#endif

610
src/unrar/model.cpp Normal file
View File

@ -0,0 +1,610 @@
/****************************************************************************
* This file is part of PPMd project *
* Written and distributed to public domain by Dmitry Shkarin 1997, *
* 1999-2000 *
* Contents: model description and encoding/decoding routines *
****************************************************************************/
inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats,
STATE& FirstState)
{
PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext();
if ( pc )
{
pc->NumStats=1;
pc->OneState=FirstState;
pc->Suffix=this;
pStats->Successor=pc;
}
return pc;
}
ModelPPM::ModelPPM()
{
MinContext=NULL;
MaxContext=NULL;
MedContext=NULL;
}
void ModelPPM::RestartModelRare()
{
int i, k, m;
memset(CharMask,0,sizeof(CharMask));
SubAlloc.InitSubAllocator();
InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext();
MinContext->Suffix=NULL;
OrderFall=MaxOrder;
MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2);
for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
{
MinContext->U.Stats[i].Symbol=i;
MinContext->U.Stats[i].Freq=1;
MinContext->U.Stats[i].Successor=NULL;
}
static const ushort InitBinEsc[]={
0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051
};
for (i=0;i < 128;i++)
for (k=0;k < 8;k++)
for (m=0;m < 64;m += 8)
BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2);
for (i=0;i < 25;i++)
for (k=0;k < 16;k++)
SEE2Cont[i][k].init(5*i+10);
}
void ModelPPM::StartModelRare(int MaxOrder)
{
int i, k, m ,Step;
EscCount=1;
/*
if (MaxOrder < 2)
{
memset(CharMask,0,sizeof(CharMask));
OrderFall=ModelPPM::MaxOrder;
MinContext=MaxContext;
while (MinContext->Suffix != NULL)
{
MinContext=MinContext->Suffix;
OrderFall--;
}
FoundState=MinContext->U.Stats;
MinContext=MaxContext;
}
else
*/
{
ModelPPM::MaxOrder=MaxOrder;
RestartModelRare();
NS2BSIndx[0]=2*0;
NS2BSIndx[1]=2*1;
memset(NS2BSIndx+2,2*2,9);
memset(NS2BSIndx+11,2*3,256-11);
for (i=0;i < 3;i++)
NS2Indx[i]=i;
for (m=i, k=Step=1;i < 256;i++)
{
NS2Indx[i]=m;
if ( !--k )
{
k = ++Step;
m++;
}
}
memset(HB2Flag,0,0x40);
memset(HB2Flag+0x40,0x08,0x100-0x40);
DummySEE2Cont.Shift=PERIOD_BITS;
}
}
void PPM_CONTEXT::rescale(ModelPPM *Model)
{
int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
STATE* p1, * p;
for (p=Model->FoundState;p != U.Stats;p--)
_PPMD_SWAP(p[0],p[-1]);
U.Stats->Freq += 4;
U.SummFreq += 4;
EscFreq=U.SummFreq-p->Freq;
Adder=(Model->OrderFall != 0);
U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
do
{
EscFreq -= (++p)->Freq;
U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
if (p[0].Freq > p[-1].Freq)
{
STATE tmp=*(p1=p);
do
{
p1[0]=p1[-1];
} while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq);
*p1=tmp;
}
} while ( --i );
if (p->Freq == 0)
{
do
{
i++;
} while ((--p)->Freq == 0);
EscFreq += i;
if ((NumStats -= i) == 1)
{
STATE tmp=*U.Stats;
do
{
tmp.Freq-=(tmp.Freq >> 1);
EscFreq>>=1;
} while (EscFreq > 1);
Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1);
*(Model->FoundState=&OneState)=tmp; return;
}
}
U.SummFreq += (EscFreq -= (EscFreq >> 1));
int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
if (n0 != n1)
U.Stats = (STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
Model->FoundState=U.Stats;
}
inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1)
{
#ifdef __ICL
static
#endif
STATE UpState;
PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
STATE * p, * ps[MAX_O], ** pps=ps;
if ( !Skip )
{
*pps++ = FoundState;
if ( !pc->Suffix )
goto NO_LOOP;
}
if ( p1 )
{
p=p1;
pc=pc->Suffix;
goto LOOP_ENTRY;
}
do
{
pc=pc->Suffix;
if (pc->NumStats != 1)
{
if ((p=pc->U.Stats)->Symbol != FoundState->Symbol)
do
{
p++;
} while (p->Symbol != FoundState->Symbol);
}
else
p=&(pc->OneState);
LOOP_ENTRY:
if (p->Successor != UpBranch)
{
pc=p->Successor;
break;
}
*pps++ = p;
} while ( pc->Suffix );
NO_LOOP:
if (pps == ps)
return pc;
UpState.Symbol=*(byte*) UpBranch;
UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
if (pc->NumStats != 1)
{
if ((byte*) pc <= SubAlloc.pText)
return(NULL);
if ((p=pc->U.Stats)->Symbol != UpState.Symbol)
do
{
p++;
} while (p->Symbol != UpState.Symbol);
uint cf=p->Freq-1;
uint s0=pc->U.SummFreq-pc->NumStats-cf;
UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
}
else
UpState.Freq=pc->OneState.Freq;
do
{
pc = pc->createChild(this,*--pps,UpState);
if ( !pc )
return NULL;
} while (pps != ps);
return pc;
}
inline void ModelPPM::UpdateModel()
{
STATE fs = *FoundState, *p = NULL;
PPM_CONTEXT *pc, *Successor;
uint ns1, ns, cf, sf, s0;
if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
{
if (pc->NumStats != 1)
{
if ((p=pc->U.Stats)->Symbol != fs.Symbol)
{
do
{
p++;
} while (p->Symbol != fs.Symbol);
if (p[0].Freq >= p[-1].Freq)
{
_PPMD_SWAP(p[0],p[-1]);
p--;
}
}
if (p->Freq < MAX_FREQ-9)
{
p->Freq += 2;
pc->U.SummFreq += 2;
}
}
else
{
p=&(pc->OneState);
p->Freq += (p->Freq < 32);
}
}
if ( !OrderFall )
{
MinContext=MaxContext=FoundState->Successor=CreateSuccessors(TRUE,p);
if ( !MinContext )
goto RESTART_MODEL;
return;
}
*SubAlloc.pText++ = fs.Symbol;
Successor = (PPM_CONTEXT*) SubAlloc.pText;
if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
goto RESTART_MODEL;
if ( fs.Successor )
{
if ((byte*) fs.Successor <= SubAlloc.pText &&
(fs.Successor=CreateSuccessors(FALSE,p)) == NULL)
goto RESTART_MODEL;
if ( !--OrderFall )
{
Successor=fs.Successor;
SubAlloc.pText -= (MaxContext != MinContext);
}
}
else
{
FoundState->Successor=Successor;
fs.Successor=MinContext;
}
s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1);
for (pc=MaxContext;pc != MinContext;pc=pc->Suffix)
{
if ((ns1=pc->NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
if ( !pc->U.Stats )
goto RESTART_MODEL;
}
pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1));
}
else
{
p=(STATE*) SubAlloc.AllocUnits(1);
if ( !p )
goto RESTART_MODEL;
*p=pc->OneState;
pc->U.Stats=p;
if (p->Freq < MAX_FREQ/4-1)
p->Freq += p->Freq;
else
p->Freq = MAX_FREQ-4;
pc->U.SummFreq=p->Freq+InitEsc+(ns > 3);
}
cf=2*fs.Freq*(pc->U.SummFreq+6);
sf=s0+pc->U.SummFreq;
if (cf < 6*sf)
{
cf=1+(cf > sf)+(cf >= 4*sf);
pc->U.SummFreq += 3;
}
else
{
cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf);
pc->U.SummFreq += cf;
}
p=pc->U.Stats+ns1;
p->Successor=Successor;
p->Symbol = fs.Symbol;
p->Freq = cf;
pc->NumStats=++ns1;
}
MaxContext=MinContext=fs.Successor;
return;
RESTART_MODEL:
RestartModelRare();
EscCount=0;
}
// Tabulated escapes for exponential symbol distribution
static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
{
STATE& rs=OneState;
Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
Model->NS2BSIndx[Suffix->NumStats-1]+
Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+
((Model->RunLength >> 26) & 0x20)];
if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs)
{
Model->FoundState=&rs;
rs.Freq += (rs.Freq < 128);
Model->Coder.SubRange.LowCount=0;
Model->Coder.SubRange.HighCount=bs;
bs = GET_SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
Model->PrevSuccess=1;
Model->RunLength++;
}
else
{
Model->Coder.SubRange.LowCount=bs;
bs = GET_SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
Model->Coder.SubRange.HighCount=BIN_SCALE;
Model->InitEsc=ExpEscape[bs >> 10];
Model->NumMasked=1;
Model->CharMask[rs.Symbol]=Model->EscCount;
Model->PrevSuccess=0;
Model->FoundState=NULL;
}
}
inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
{
(Model->FoundState=p)->Freq += 4;
U.SummFreq += 4;
if (p[0].Freq > p[-1].Freq)
{
_PPMD_SWAP(p[0],p[-1]);
Model->FoundState=--p;
if (p->Freq > MAX_FREQ)
rescale(Model);
}
}
inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
{
Model->Coder.SubRange.scale=U.SummFreq;
STATE* p=U.Stats;
int i, HiCnt;
int count=Model->Coder.GetCurrentCount();
if (count>=(int)Model->Coder.SubRange.scale)
return(false);
if (count < (HiCnt=p->Freq))
{
Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale);
Model->RunLength += Model->PrevSuccess;
(Model->FoundState=p)->Freq=(HiCnt += 4);
U.SummFreq += 4;
if (HiCnt > MAX_FREQ)
rescale(Model);
Model->Coder.SubRange.LowCount=0;
return(true);
}
else
if (Model->FoundState==NULL)
return(false);
Model->PrevSuccess=0;
i=NumStats-1;
while ((HiCnt += (++p)->Freq) <= count)
if (--i == 0)
{
Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
Model->Coder.SubRange.LowCount=HiCnt;
Model->CharMask[p->Symbol]=Model->EscCount;
i=(Model->NumMasked=NumStats)-1;
Model->FoundState=NULL;
do
{
Model->CharMask[(--p)->Symbol]=Model->EscCount;
} while ( --i );
Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
return(true);
}
Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
update1(Model,p);
return(true);
}
inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
{
(Model->FoundState=p)->Freq += 4;
U.SummFreq += 4;
if (p->Freq > MAX_FREQ)
rescale(Model);
Model->EscCount++;
Model->RunLength=Model->InitRL;
}
inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
{
SEE2_CONTEXT* psee2c;
if (NumStats != 256)
{
psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
(Diff < Suffix->NumStats-NumStats)+
2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+
Model->HiBitsFlag;
Model->Coder.SubRange.scale=psee2c->getMean();
}
else
{
psee2c=&Model->DummySEE2Cont;
Model->Coder.SubRange.scale=1;
}
return psee2c;
}
inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
{
int count, HiCnt, i=NumStats-Model->NumMasked;
SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
STATE* ps[256], ** pps=ps, * p=U.Stats-1;
HiCnt=0;
do
{
do
{
p++;
} while (Model->CharMask[p->Symbol] == Model->EscCount);
HiCnt += p->Freq;
*pps++ = p;
} while ( --i );
Model->Coder.SubRange.scale += HiCnt;
count=Model->Coder.GetCurrentCount();
if (count>=(int)Model->Coder.SubRange.scale)
return(false);
p=*(pps=ps);
if (count < HiCnt)
{
HiCnt=0;
while ((HiCnt += p->Freq) <= count)
p=*++pps;
Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
psee2c->update();
update2(Model,p);
}
else
{
Model->Coder.SubRange.LowCount=HiCnt;
Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
i=NumStats-Model->NumMasked;
pps--;
do
{
Model->CharMask[(*++pps)->Symbol]=Model->EscCount;
} while ( --i );
psee2c->Summ += Model->Coder.SubRange.scale;
Model->NumMasked = NumStats;
}
return(true);
}
inline void ModelPPM::ClearMask()
{
EscCount=1;
memset(CharMask,0,sizeof(CharMask));
}
// reset PPM variables after data error allowing safe resuming
// of further data processing
void ModelPPM::CleanUp()
{
SubAlloc.StopSubAllocator();
SubAlloc.StartSubAllocator(1);
StartModelRare(2);
}
bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
{
int MaxOrder=UnpackRead->GetChar();
bool Reset=(MaxOrder & 0x20)!=0;
int MaxMB;
if (Reset)
MaxMB=UnpackRead->GetChar();
else
if (SubAlloc.GetAllocatedMemory()==0)
return(false);
if (MaxOrder & 0x40)
EscChar=UnpackRead->GetChar();
Coder.InitDecoder(UnpackRead);
if (Reset)
{
MaxOrder=(MaxOrder & 0x1f)+1;
if (MaxOrder>16)
MaxOrder=16+(MaxOrder-16)*3;
if (MaxOrder==1)
{
SubAlloc.StopSubAllocator();
return(false);
}
SubAlloc.StartSubAllocator(MaxMB+1);
StartModelRare(MaxOrder);
}
return(MinContext!=NULL);
}
int ModelPPM::DecodeChar()
{
if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
return(-1);
if (MinContext->NumStats != 1)
{
if ((byte*)MinContext->U.Stats <= SubAlloc.pText || (byte*)MinContext->U.Stats>SubAlloc.HeapEnd)
return(-1);
if (!MinContext->decodeSymbol1(this))
return(-1);
}
else
MinContext->decodeBinSymbol(this);
Coder.Decode();
while ( !FoundState )
{
ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
do
{
OrderFall++;
MinContext=MinContext->Suffix;
if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
return(-1);
} while (MinContext->NumStats == NumMasked);
if (!MinContext->decodeSymbol2(this))
return(-1);
Coder.Decode();
}
int Symbol=FoundState->Symbol;
if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText)
MinContext=MaxContext=FoundState->Successor;
else
{
UpdateModel();
if (EscCount == 0)
ClearMask();
}
ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
return(Symbol);
}

132
src/unrar/model.hpp Normal file
View File

@ -0,0 +1,132 @@
#ifndef _RAR_PPMMODEL_
#define _RAR_PPMMODEL_
#include "coder.hpp"
#include "suballoc.hpp"
const int MAX_O=64; /* maximum allowed model order */
const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
#ifndef STRICT_ALIGNMENT_REQUIRED
#pragma pack(1)
#endif
struct SEE2_CONTEXT
{ // SEE-contexts for PPM-contexts with masked symbols
ushort Summ;
byte Shift, Count;
void init(int InitVal)
{
Summ=InitVal << (Shift=PERIOD_BITS-4);
Count=4;
}
uint getMean()
{
uint RetVal=GET_SHORT16(Summ) >> Shift;
Summ -= RetVal;
return RetVal+(RetVal == 0);
}
void update()
{
if (Shift < PERIOD_BITS && --Count == 0)
{
Summ += Summ;
Count=3 << Shift++;
}
}
};
class ModelPPM;
struct PPM_CONTEXT;
struct STATE
{
byte Symbol;
byte Freq;
PPM_CONTEXT* Successor;
};
struct FreqData
{
ushort SummFreq;
STATE _PACK_ATTR * Stats;
};
struct PPM_CONTEXT
{
ushort NumStats;
union
{
FreqData U;
STATE OneState;
};
PPM_CONTEXT* Suffix;
inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
inline bool decodeSymbol1(ModelPPM *Model); // other orders:
inline bool decodeSymbol2(ModelPPM *Model); // BCD context
inline void update1(ModelPPM *Model,STATE* p); // CD suffix
inline void update2(ModelPPM *Model,STATE* p); // BCDE successor
void rescale(ModelPPM *Model);
inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
};
#ifndef STRICT_ALIGNMENT_REQUIRED
#ifdef _AIX
#pragma pack(pop)
#else
#pragma pack()
#endif
#endif
const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK));
const uint FIXED_UNIT_SIZE=12;
/*
inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext):
NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; }
inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {}
*/
template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
class ModelPPM
{
private:
friend struct PPM_CONTEXT;
SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
STATE* FoundState; // found next state transition
int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
byte EscCount, PrevSuccess, HiBitsFlag;
ushort BinSumm[128][64]; // binary SEE-contexts
RangeCoder Coder;
SubAllocator SubAlloc;
void RestartModelRare();
void StartModelRare(int MaxOrder);
inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);
inline void UpdateModel();
inline void ClearMask();
public:
ModelPPM();
void CleanUp(); // reset PPM variables after data error
bool DecodeInit(Unpack *UnpackRead,int &EscChar);
int DecodeChar();
};
#endif

2390
src/unrar/msc.dep Normal file

File diff suppressed because it is too large Load Diff

30
src/unrar/options.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "rar.hpp"
RAROptions::RAROptions()
{
Init();
}
RAROptions::~RAROptions()
{
// It is important for security reasons, so we do not have the unnecessary
// password data left in memory.
memset(this,0,sizeof(RAROptions));
}
void RAROptions::Init()
{
memset(this,0,sizeof(RAROptions));
WinSize=0x400000;
Overwrite=OVERWRITE_DEFAULT;
Method=3;
MsgStream=MSG_STDOUT;
ConvertNames=NAMES_ORIGINALCASE;
ProcessEA=true;
xmtime=EXTTIME_HIGH3;
CurVolNum=0;
FileSizeLess=INT64NDF;
FileSizeMore=INT64NDF;
}

175
src/unrar/options.hpp Normal file
View File

@ -0,0 +1,175 @@
#ifndef _RAR_OPTIONS_
#define _RAR_OPTIONS_
#define DEFAULT_RECOVERY -1
#define DEFAULT_RECVOLUMES -10
#define VOLSIZE_AUTO INT64NDF // Automatically detect the volume size.
enum PATH_EXCL_MODE {
EXCL_UNCHANGED=0, // Process paths as is (default).
EXCL_SKIPWHOLEPATH, // -ep (exclude the path completely)
EXCL_BASEPATH, // -ep1 (exclude the base part of path)
EXCL_SAVEFULLPATH, // -ep2 (the full path without the disk letter)
EXCL_ABSPATH, // -ep3 (the full path with the disk letter)
EXCL_SKIPABSPATH // Works as EXCL_BASEPATH for fully qualified paths
// and as EXCL_UNCHANGED for relative paths.
// Used by WinRAR GUI only.
};
enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
SOLID_VOLUME_DEPENDENT=8,SOLID_VOLUME_INDEPENDENT=16};
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
enum EXTTIME_MODE {
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
};
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
enum MESSAGE_TYPE {MSG_STDOUT=0,MSG_STDERR,MSG_ERRONLY,MSG_NULL};
enum RECURSE_MODE
{
RECURSE_NONE=0, // no recurse switches
RECURSE_DISABLE, // switch -r-
RECURSE_ALWAYS, // switch -r
RECURSE_WILDCARDS, // switch -r0
};
enum OVERWRITE_MODE
{
OVERWRITE_DEFAULT=0, // ask for extraction, silently overwrite for archiving
OVERWRITE_ALL,
OVERWRITE_NONE,
OVERWRITE_AUTORENAME,
OVERWRITE_FORCE_ASK
};
enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE };
#define MAX_FILTER_TYPES 16
enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE};
struct FilterMode
{
FilterState State;
int Param1;
int Param2;
};
#define MAX_GENERATE_MASK 128
class RAROptions
{
public:
RAROptions();
~RAROptions();
void Init();
uint ExclFileAttr;
uint InclFileAttr;
bool InclAttrSet;
uint WinSize;
char TempPath[NM];
bool ConfigDisabled; // Switch -cfg-.
char ExtrPath[NM];
wchar ExtrPathW[NM];
char CommentFile[NM];
wchar CommentFileW[NM];
RAR_CHARSET CommentCharset;
RAR_CHARSET FilelistCharset;
char ArcPath[NM];
wchar ArcPathW[NM];
SecPassword Password;
bool EncryptHeaders;
char LogName[NM];
MESSAGE_TYPE MsgStream;
bool Sound;
OVERWRITE_MODE Overwrite;
int Method;
int Recovery;
int RecVolNumber;
bool DisablePercentage;
bool DisableCopyright;
bool DisableDone;
int Solid;
int SolidCount;
bool ClearArc;
bool AddArcOnly;
bool AV;
bool DisableComment;
bool FreshFiles;
bool UpdateFiles;
PATH_EXCL_MODE ExclPath;
RECURSE_MODE Recurse;
int64 VolSize;
Array<int64> NextVolSizes;
uint CurVolNum;
bool AllYes;
bool DisableViewAV;
bool DisableSortSolid;
int ArcTime;
int ConvertNames;
bool ProcessOwners;
bool SaveLinks;
int Priority;
int SleepTime;
bool KeepBroken;
bool OpenShared;
bool DeleteFiles;
#ifndef SFX_MODULE
bool GenerateArcName;
char GenerateMask[MAX_GENERATE_MASK];
#endif
bool SyncFiles;
bool ProcessEA;
bool SaveStreams;
bool SetCompressedAttr;
bool IgnoreGeneralAttr;
RarTime FileTimeBefore;
RarTime FileTimeAfter;
int64 FileSizeLess;
int64 FileSizeMore;
bool OldNumbering;
bool Lock;
bool Test;
bool VolumePause;
FilterMode FilterModes[MAX_FILTER_TYPES];
char EmailTo[NM];
uint VersionControl;
bool NoEndBlock;
bool AppendArcNameToPath;
bool Shutdown;
EXTTIME_MODE xmtime;
EXTTIME_MODE xctime;
EXTTIME_MODE xatime;
EXTTIME_MODE xarctime;
char CompressStdin[NM];
#ifdef RAR_SMP
uint Threads;
#endif
#ifdef RARDLL
char DllDestName[NM];
wchar DllDestNameW[NM];
int DllOpMode;
int DllError;
LPARAM UserData;
UNRARCALLBACK Callback;
CHANGEVOLPROC ChangeVolProc;
PROCESSDATAPROC ProcessDataProc;
#endif
};
#endif

254
src/unrar/os.hpp Normal file
View File

@ -0,0 +1,254 @@
#ifndef _RAR_OS_
#define _RAR_OS_
#define FALSE 0
#define TRUE 1
#ifdef __EMX__
#define INCL_BASE
#endif
#if defined(RARDLL) && !defined(SILENT)
#define SILENT
#endif
#define ENABLE_BAD_ALLOC // Undefine if std::bad_alloc is not supported.
#ifdef ENABLE_BAD_ALLOC
#include <new>
#endif
#if defined(_WIN_ALL) || defined(_EMX)
#define LITTLE_ENDIAN
#define NM 1024
#ifdef _WIN_ALL
#define STRICT
#define UNICODE
#undef WINVER
#undef _WIN32_WINNT
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <prsht.h>
#include <shlwapi.h>
#include <shellapi.h>
#include <shlobj.h>
#include <winioctl.h>
#endif // _WIN_ALL
#include <sys/types.h>
#include <sys/stat.h>
#include <dos.h>
#if !defined(_EMX) && !defined(_MSC_VER)
#include <dir.h>
#endif
#ifdef _MSC_VER
#if _MSC_VER<1500
#define for if (0) ; else for
#endif
#include <direct.h>
#else
#include <dirent.h>
#endif // _MSC_VER
#ifdef _EMX
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#ifdef _DJGPP
#include <utime.h>
#else
#include <os2.h>
#include <sys/utime.h>
#include <emx/syscalls.h>
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <dos.h>
#include <io.h>
#include <time.h>
#include <signal.h>
#define ENABLE_ACCESS
#define DefConfigName "rar.ini"
#define DefLogName "rar.log"
#define PATHDIVIDER "\\"
#define PATHDIVIDERW L"\\"
#define CPATHDIVIDER '\\'
#define MASKALL "*"
#define MASKALLW L"*"
#define READBINARY "rb"
#define READTEXT "rt"
#define UPDATEBINARY "r+b"
#define CREATEBINARY "w+b"
#define WRITEBINARY "wb"
#define APPENDTEXT "at"
#if defined(_WIN_ALL)
#ifdef _MSC_VER
#define _stdfunction __cdecl
#ifdef SFX_MODULE
// We want to keep SFX module small, so let compiler to decide.
#define _forceinline inline
#else
#define _forceinline __forceinline
#endif
#else
#define _stdfunction _USERENTRY
#define _forceinline inline
#endif
#else
#define _stdfunction
#define _forceinline inline
#endif
#endif
#ifdef _UNIX
#define NM 1024
#ifdef _BEOS
#include <be/kernel/fs_info.h>
#include <be/kernel/fs_attr.h>
#endif
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#if defined(__QNXNTO__)
#include <sys/param.h>
#endif
#if defined(RAR_SMP) && defined(__APPLE__)
#include <sys/sysctl.h>
#endif
#if defined(__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__)
#include <sys/param.h>
#include <sys/mount.h>
#else
#endif
#include <pwd.h>
#include <grp.h>
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <time.h>
#include <signal.h>
#include <utime.h>
#include <locale.h>
#ifdef S_IFLNK
#define SAVE_LINKS
#endif
#define ENABLE_ACCESS
#define DefConfigName ".rarrc"
#define DefLogName ".rarlog"
#define PATHDIVIDER "/"
#define PATHDIVIDERW L"/"
#define CPATHDIVIDER '/'
#define MASKALL "*"
#define MASKALLW L"*"
#define READBINARY "r"
#define READTEXT "r"
#define UPDATEBINARY "r+"
#define CREATEBINARY "w+"
#define WRITEBINARY "w"
#define APPENDTEXT "a"
#define _stdfunction
#define _forceinline inline
#ifdef _APPLE
#if defined(__BIG_ENDIAN__) && !defined(BIG_ENDIAN)
#define BIG_ENDIAN
#undef LITTLE_ENDIAN
#endif
#if defined(__i386__) && !defined(LITTLE_ENDIAN)
#define LITTLE_ENDIAN
#undef BIG_ENDIAN
#endif
#endif
#if defined(__sparc) || defined(sparc) || defined(__hpux)
#ifndef BIG_ENDIAN
#define BIG_ENDIAN
#endif
#endif
#endif
typedef const char* MSGID;
#define safebuf static
#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#if defined(__i386) || defined(i386) || defined(__i386__)
#define LITTLE_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
#define LITTLE_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
#define BIG_ENDIAN
#else
#error "Neither LITTLE_ENDIAN nor BIG_ENDIAN are defined. Define one of them."
#endif
#endif
#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
#undef LITTLE_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
#undef BIG_ENDIAN
#else
#error "Both LITTLE_ENDIAN and BIG_ENDIAN are defined. Undef one of them."
#endif
#endif
#if !defined(BIG_ENDIAN) && !defined(_WIN_CE) && defined(_WIN_ALL)
// Allow not aligned integer access, increases speed in some operations.
#define ALLOW_NOT_ALIGNED_INT
#endif
#if defined(__sparc) || defined(sparc) || defined(__sparcv9)
// Prohibit not aligned access to data structures in text compression
// algorithm, increases memory requirements
#define STRICT_ALIGNMENT_REQUIRED
#endif
#endif // _RAR_OS_

94
src/unrar/os2ea.cpp Normal file
View File

@ -0,0 +1,94 @@
#include <os2.h>
void ExtractOS2EA(Archive &Arc,char *FileName)
{
if (_osmode != OS2_MODE)
{
mprintf(St(MSkipEA));
return;
}
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RARX_CRC);
return;
}
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
{
Log(Arc.FileName,St(MEAUnknHeader),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
return;
}
struct StructEAOP2
{
char *GEAPtr;
char *FEAPtr;
unsigned long Error;
} EAOP2;
ComprDataIO DataIO;
Unpack Unpack(&DataIO);
Unpack.Init();
Array<unsigned char> UnpData(Arc.EAHead.UnpSize);
DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
DataIO.EnableShowProgress(false);
DataIO.SetFiles(&Arc,NULL);
Unpack.SetDestSize(Arc.EAHead.UnpSize);
Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RARX_CRC);
return;
}
EAOP2.FEAPtr=(char *)&UnpData[0];
EAOP2.GEAPtr=NULL;
if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
}
File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
mprintf(St(MShowEA));
}
void ExtractOS2EANew(Archive &Arc,char *FileName)
{
if (_osmode != OS2_MODE)
{
mprintf(St(MSkipEA));
return;
}
Array<byte> SubData;
if (!Arc.ReadSubData(&SubData,NULL))
return;
struct StructEAOP2
{
char *GEAPtr;
char *FEAPtr;
unsigned long Error;
} EAOP2;
EAOP2.FEAPtr=(char *)&SubData[0];
EAOP2.GEAPtr=NULL;
if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RARX_WARNING);
}
File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
mprintf(St(MShowEA));
}

1457
src/unrar/pathfn.cpp Normal file

File diff suppressed because it is too large Load Diff

66
src/unrar/pathfn.hpp Normal file
View File

@ -0,0 +1,66 @@
#ifndef _RAR_PATHFN_
#define _RAR_PATHFN_
char* PointToName(const char *Path);
wchar* PointToName(const wchar *Path);
char* PointToLastChar(const char *Path);
wchar* PointToLastChar(const wchar *Path);
char* ConvertPath(const char *SrcPath,char *DestPath);
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath);
void SetExt(char *Name,const char *NewExt);
void SetExt(wchar *Name,const wchar *NewExt);
void SetSFXExt(char *SFXName);
void SetSFXExt(wchar *SFXName);
char *GetExt(const char *Name);
wchar *GetExt(const wchar *Name);
bool CmpExt(const char *Name,const char *Ext);
bool CmpExt(const wchar *Name,const wchar *Ext);
bool IsWildcard(const char *Str,const wchar *StrW=NULL);
bool IsPathDiv(int Ch);
bool IsDriveDiv(int Ch);
int GetPathDisk(const char *Path);
int GetPathDisk(const wchar *Path);
void AddEndSlash(char *Path);
void AddEndSlash(wchar *Path);
void GetFilePath(const char *FullName,char *Path,int MaxLength);
void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength);
void RemoveNameFromPath(char *Path);
void RemoveNameFromPath(wchar *Path);
void GetAppDataPath(char *Path);
void GetAppDataPath(wchar *Path);
void GetRarDataPath(char *Path);
void GetRarDataPath(wchar *Path);
bool EnumConfigPaths(wchar *Path,int Number);
bool EnumConfigPaths(char *Path,int Number);
void GetConfigName(const char *Name,char *FullName,bool CheckExist);
void GetConfigName(const wchar *Name,wchar *FullName,bool CheckExist);
char* GetVolNumPart(char *ArcName);
wchar* GetVolNumPart(wchar *ArcName);
void NextVolumeName(char *ArcName,wchar *ArcNameW,uint MaxLength,bool OldNumbering);
bool IsNameUsable(const char *Name);
bool IsNameUsable(const wchar *Name);
void MakeNameUsable(char *Name,bool Extended);
void MakeNameUsable(wchar *Name,bool Extended);
char* UnixSlashToDos(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
char* DosSlashToUnix(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName=NULL,uint MaxLength=NM);
wchar* DosSlashToUnix(wchar *SrcName,wchar *DestName=NULL,uint MaxLength=NM);
void ConvertNameToFull(const char *Src,char *Dest);
void ConvertNameToFull(const wchar *Src,wchar *Dest);
bool IsFullPath(const char *Path);
bool IsFullPath(const wchar *Path);
bool IsDiskLetter(const char *Path);
bool IsDiskLetter(const wchar *Path);
void GetPathRoot(const char *Path,char *Root);
void GetPathRoot(const wchar *Path,wchar *Root);
int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate);
char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering);
wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,bool NewNumbering);
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize);
char* GetAsciiName(const wchar *NameW,char *Name,size_t DestSize);
#ifndef SFX_MODULE
void GenerateArchiveName(char *ArcName,wchar *ArcNameW,size_t MaxSize,char *GenerateMask,bool Archiving);
#endif
#endif

144
src/unrar/rar.cpp Normal file
View File

@ -0,0 +1,144 @@
#include "rar.hpp"
#if !defined(GUI) && !defined(RARDLL)
int main(int argc, char *argv[])
{
#ifdef _UNIX
setlocale(LC_ALL,"");
#endif
#if defined(_EMX) && !defined(_DJGPP)
uni_init(0);
#endif
#if !defined(_SFX_RTL_) && !defined(_WIN_ALL)
setbuf(stdout,NULL);
#endif
#if !defined(SFX_MODULE) && defined(_EMX)
EnumConfigPaths(argv[0],-1);
#endif
ErrHandler.SetSignalHandlers(true);
RARInitData();
#ifdef SFX_MODULE
char ModuleNameA[NM];
wchar ModuleNameW[NM];
#ifdef _WIN_ALL
GetModuleFileNameW(NULL,ModuleNameW,ASIZE(ModuleNameW));
WideToChar(ModuleNameW,ModuleNameA);
#else
strcpy(ModuleNameA,argv[0]);
*ModuleNameW=0;
#endif
#endif
#ifdef _WIN_ALL
SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
// Must be initialized, normal initialization can be skipped in case of
// exception.
bool ShutdownOnClose=false;
#endif
#ifdef ALLOW_EXCEPTIONS
try
#endif
{
CommandData Cmd;
#ifdef SFX_MODULE
strcpy(Cmd.Command,"X");
char *Switch=NULL;
#ifdef _SFX_RTL_
char *CmdLine=GetCommandLineA();
if (CmdLine!=NULL && *CmdLine=='\"')
CmdLine=strchr(CmdLine+1,'\"');
if (CmdLine!=NULL && (CmdLine=strpbrk(CmdLine," /"))!=NULL)
{
while (IsSpace(*CmdLine))
CmdLine++;
Switch=CmdLine;
}
#else
Switch=argc>1 ? argv[1]:NULL;
#endif
if (Switch!=NULL && Cmd.IsSwitch(Switch[0]))
{
int UpperCmd=etoupper(Switch[1]);
switch(UpperCmd)
{
case 'T':
case 'V':
Cmd.Command[0]=UpperCmd;
break;
case '?':
Cmd.OutHelp(RARX_SUCCESS);
break;
}
}
Cmd.AddArcName(ModuleNameA,ModuleNameW);
Cmd.ParseDone();
#else // !SFX_MODULE
Cmd.PreprocessCommandLine(argc,argv);
if (!Cmd.ConfigDisabled)
{
Cmd.ReadConfig();
Cmd.ParseEnvVar();
}
Cmd.ParseCommandLine(argc,argv);
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
ShutdownOnClose=Cmd.Shutdown;
#endif
InitConsoleOptions(Cmd.MsgStream,Cmd.Sound);
InitLogOptions(Cmd.LogName);
ErrHandler.SetSilent(Cmd.AllYes || Cmd.MsgStream==MSG_NULL);
ErrHandler.SetShutdown(Cmd.Shutdown);
Cmd.OutTitle();
Cmd.ProcessCommand();
}
#ifdef ALLOW_EXCEPTIONS
catch (RAR_EXIT ErrCode)
{
ErrHandler.SetErrorCode(ErrCode);
}
#ifdef ENABLE_BAD_ALLOC
catch (std::bad_alloc)
{
ErrHandler.MemoryErrorMsg();
ErrHandler.SetErrorCode(RARX_MEMORY);
}
#endif
catch (...)
{
ErrHandler.SetErrorCode(RARX_FATAL);
}
#endif
File::RemoveCreated();
#if defined(SFX_MODULE) && defined(_DJGPP)
_chmod(ModuleNameA,1,0x20);
#endif
#if defined(_EMX) && !defined(_DJGPP)
uni_done();
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
if (ShutdownOnClose)
Shutdown();
#endif
return(ErrHandler.GetErrorCode());
}
#endif

79
src/unrar/rar.hpp Normal file
View File

@ -0,0 +1,79 @@
#ifndef _RAR_RARCOMMON_
#define _RAR_RARCOMMON_
#include "raros.hpp"
#include "os.hpp"
#ifdef RARDLL
#include "dll.hpp"
#endif
#ifndef _WIN_CE
#include "version.hpp"
#endif
#include "rartypes.hpp"
#include "rardefs.hpp"
#include "rarlang.hpp"
#include "unicode.hpp"
#include "errhnd.hpp"
#include "array.hpp"
#include "timefn.hpp"
#include "secpassword.hpp"
#include "options.hpp"
#include "headers.hpp"
#include "pathfn.hpp"
#include "strfn.hpp"
#include "strlist.hpp"
#include "file.hpp"
#include "sha1.hpp"
#include "crc.hpp"
#include "rijndael.hpp"
#include "crypt.hpp"
#include "filefn.hpp"
#include "filestr.hpp"
#include "find.hpp"
#include "scantree.hpp"
#include "savepos.hpp"
#include "getbits.hpp"
#include "rdwrfn.hpp"
#include "archive.hpp"
#include "match.hpp"
#include "cmddata.hpp"
#include "filcreat.hpp"
#include "consio.hpp"
#include "system.hpp"
#ifdef _WIN_ALL
#include "isnt.hpp"
#endif
#include "log.hpp"
#include "rawread.hpp"
#include "encname.hpp"
#include "resource.hpp"
#include "compress.hpp"
#include "rarvm.hpp"
#include "model.hpp"
#include "unpack.hpp"
#include "extinfo.hpp"
#include "extract.hpp"
#include "list.hpp"
#include "rs.hpp"
#include "recvol.hpp"
#include "volume.hpp"
#include "smallfn.hpp"
#include "ulinks.hpp"
#include "global.hpp"
#endif

28
src/unrar/rardefs.hpp Normal file
View File

@ -0,0 +1,28 @@
#ifndef _RAR_DEFS_
#define _RAR_DEFS_
#define Min(x,y) (((x)<(y)) ? (x):(y))
#define Max(x,y) (((x)>(y)) ? (x):(y))
#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
// MAXPASSWORD is expected to be multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE (16)
// for CryptProtectMemory in SecPassword.
#define MAXPASSWORD 128
#define MAXSFXSIZE 0x100000
#define DefSFXName "default.sfx"
#define DefSortListName "rarfiles.lst"
#ifndef FA_RDONLY
#define FA_RDONLY 0x01
#define FA_HIDDEN 0x02
#define FA_SYSTEM 0x04
#define FA_LABEL 0x08
#define FA_DIREC 0x10
#define FA_ARCH 0x20
#endif
#endif

10
src/unrar/rarlang.hpp Normal file
View File

@ -0,0 +1,10 @@
#ifndef _RAR_LANG_
#define _RAR_LANG_
#ifdef USE_RC
#include "rarres.hpp"
#else
#include "loclang.hpp"
#endif
#endif

46
src/unrar/raros.hpp Normal file
View File

@ -0,0 +1,46 @@
#ifndef _RAR_RAROS_
#define _RAR_RAROS_
#ifdef __EMX__
#define _EMX
#endif
#ifdef __DJGPP__
#define _DJGPP
#define _EMX
#endif
#if defined(__WIN32__) || defined(_WIN32)
#define _WIN_ALL // Defined for all Windows platforms, 32 and 64 bit, mobile and desktop.
#ifdef _M_X64
#define _WIN_64
#else
#define _WIN_32
#endif
#endif
#ifdef _WIN32_WCE
#define _WIN_ALL
#define _WIN_CE
#ifdef WM_FILECHANGEINFO
#define PC2002
#else
#undef PC2002
#endif
#endif
#ifdef __BEOS__
#define _UNIX
#define _BEOS
#endif
#ifdef __APPLE__
#define _UNIX
#define _APPLE
#endif
#if !defined(_EMX) && !defined(_WIN_ALL) && !defined(_BEOS) && !defined(_APPLE)
#define _UNIX
#endif
#endif

2
src/unrar/rarpch.cpp Normal file
View File

@ -0,0 +1,2 @@
// We use rarpch.cpp to create precompiled headers for MS Visual C++.
#include "rar.hpp"

47
src/unrar/rartypes.hpp Normal file
View File

@ -0,0 +1,47 @@
#ifndef _RAR_TYPES_
#define _RAR_TYPES_
typedef unsigned char byte; // unsigned 8 bits
typedef unsigned short ushort; // preferably 16 bits, but can be more
typedef unsigned int uint; // 32 bits or more
#define PRESENT_INT32 // undefine if signed 32 bits is not available
typedef unsigned int uint32; // 32 bits exactly
typedef signed int int32; // signed 32 bits exactly
// If compiler does not support 64 bit variables, we can define
// uint64 and int64 as 32 bit, but it will limit the maximum processed
// file size to 2 GB.
#if defined(__BORLANDC__) || defined(_MSC_VER)
typedef unsigned __int64 uint64; // unsigned 64 bits
typedef signed __int64 int64; // signed 64 bits
#else
typedef unsigned long long uint64; // unsigned 64 bits
typedef signed long long int64; // signed 64 bits
#endif
#if defined(_WIN_ALL) || defined(__GNUC__) || defined(__sgi) || defined(_AIX) || defined(__sun) || defined(__hpux) || defined(_OSF_SOURCE)
typedef wchar_t wchar;
#else
typedef ushort wchar;
#endif
// Get lowest 16 bits.
#define GET_SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
// Get lowest 32 bits.
#define GET_UINT32(x) (sizeof(uint32)==4 ? (uint32)(x):((x)&0xffffffff))
// 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.
// 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.
#define INT64NDF INT32TO64(0x7fffffff,0x7fffffff)
#endif

1139
src/unrar/rarvm.cpp Normal file

File diff suppressed because it is too large Load Diff

113
src/unrar/rarvm.hpp Normal file
View File

@ -0,0 +1,113 @@
#ifndef _RAR_VM_
#define _RAR_VM_
#define VM_STANDARDFILTERS
#ifndef SFX_MODULE
#define VM_OPTIMIZE
#endif
#define VM_MEMSIZE 0x40000
#define VM_MEMMASK (VM_MEMSIZE-1)
#define VM_GLOBALMEMADDR 0x3C000
#define VM_GLOBALMEMSIZE 0x2000
#define VM_FIXEDGLOBALSIZE 64
enum VM_Commands
{
VM_MOV, VM_CMP, VM_ADD, VM_SUB, VM_JZ, VM_JNZ, VM_INC, VM_DEC,
VM_JMP, VM_XOR, VM_AND, VM_OR, VM_TEST, VM_JS, VM_JNS, VM_JB,
VM_JBE, VM_JA, VM_JAE, VM_PUSH, VM_POP, VM_CALL, VM_RET, VM_NOT,
VM_SHL, VM_SHR, VM_SAR, VM_NEG, VM_PUSHA,VM_POPA, VM_PUSHF,VM_POPF,
VM_MOVZX,VM_MOVSX,VM_XCHG, VM_MUL, VM_DIV, VM_ADC, VM_SBB, VM_PRINT,
#ifdef VM_OPTIMIZE
VM_MOVB, VM_MOVD, VM_CMPB, VM_CMPD,
VM_ADDB, VM_ADDD, VM_SUBB, VM_SUBD, VM_INCB, VM_INCD, VM_DECB, VM_DECD,
VM_NEGB, VM_NEGD,
#endif
VM_STANDARD
};
enum VM_StandardFilters {
VMSF_NONE, VMSF_E8, VMSF_E8E9, VMSF_ITANIUM, VMSF_RGB, VMSF_AUDIO,
VMSF_DELTA, VMSF_UPCASE
};
enum VM_Flags {VM_FC=1,VM_FZ=2,VM_FS=0x80000000};
enum VM_OpType {VM_OPREG,VM_OPINT,VM_OPREGMEM,VM_OPNONE};
struct VM_PreparedOperand
{
VM_OpType Type;
uint Data;
uint Base;
uint *Addr;
};
struct VM_PreparedCommand
{
VM_Commands OpCode;
bool ByteMode;
VM_PreparedOperand Op1,Op2;
};
struct VM_PreparedProgram
{
VM_PreparedProgram()
{
AltCmd=NULL;
FilteredDataSize=0;
CmdCount=0;
}
Array<VM_PreparedCommand> Cmd;
VM_PreparedCommand *AltCmd;
int CmdCount;
Array<byte> GlobalData;
Array<byte> StaticData; // static data contained in DB operators
uint InitR[7];
byte *FilteredData;
uint FilteredDataSize;
};
class RarVM:private BitInput
{
private:
inline uint GetValue(bool ByteMode,uint *Addr);
inline void SetValue(bool ByteMode,uint *Addr,uint Value);
inline uint* GetOperand(VM_PreparedOperand *CmdOp);
void DecodeArg(VM_PreparedOperand &Op,bool ByteMode);
#ifdef VM_OPTIMIZE
void Optimize(VM_PreparedProgram *Prg);
#endif
bool ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize);
#ifdef VM_STANDARDFILTERS
VM_StandardFilters IsStandardFilter(byte *Code,uint CodeSize);
void ExecuteStandardFilter(VM_StandardFilters FilterType);
uint FilterItanium_GetBits(byte *Data,int BitPos,int BitCount);
void FilterItanium_SetBits(byte *Data,uint BitField,int BitPos,int BitCount);
#endif
byte *Mem;
uint R[8];
uint Flags;
public:
RarVM();
~RarVM();
void Init();
void Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg);
void Execute(VM_PreparedProgram *Prg);
void SetLowEndianValue(uint *Addr,uint Value);
void SetMemory(uint Pos,byte *Data,uint DataSize);
static uint ReadData(BitInput &Inp);
};
#endif

53
src/unrar/rarvmtbl.cpp Normal file
View File

@ -0,0 +1,53 @@
#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
};

126
src/unrar/rawread.cpp Normal file
View File

@ -0,0 +1,126 @@
#include "rar.hpp"
RawRead::RawRead(File *SrcFile)
{
RawRead::SrcFile=SrcFile;
ReadPos=0;
DataSize=0;
#ifndef SHELL_EXT
Crypt=NULL;
#endif
}
void RawRead::Read(size_t Size)
{
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
if (Crypt!=NULL)
{
size_t CurSize=Data.Size();
size_t SizeToRead=Size-(CurSize-DataSize);
if (SizeToRead>0)
{
size_t AlignedReadSize=SizeToRead+((~SizeToRead+1)&0xf);
Data.Add(AlignedReadSize);
size_t ReadSize=SrcFile->Read(&Data[CurSize],AlignedReadSize);
Crypt->DecryptBlock(&Data[CurSize],AlignedReadSize);
DataSize+=ReadSize==0 ? 0:Size;
}
else
DataSize+=Size;
}
else
#endif
if (Size!=0)
{
Data.Add(Size);
DataSize+=SrcFile->Read(&Data[DataSize],Size);
}
}
void RawRead::Read(byte *SrcData,size_t Size)
{
if (Size!=0)
{
Data.Add(Size);
memcpy(&Data[DataSize],SrcData,Size);
DataSize+=Size;
}
}
void RawRead::Get(byte &Field)
{
if (ReadPos<DataSize)
{
Field=Data[ReadPos];
ReadPos++;
}
else
Field=0;
}
void RawRead::Get(ushort &Field)
{
if (ReadPos+1<DataSize)
{
Field=Data[ReadPos]+(Data[ReadPos+1]<<8);
ReadPos+=2;
}
else
Field=0;
}
void RawRead::Get(uint &Field)
{
if (ReadPos+3<DataSize)
{
Field=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
(Data[ReadPos+3]<<24);
ReadPos+=4;
}
else
Field=0;
}
void RawRead::Get8(int64 &Field)
{
uint Low,High;
Get(Low);
Get(High);
Field=INT32TO64(High,Low);
}
void RawRead::Get(byte *Field,size_t Size)
{
if (ReadPos+Size-1<DataSize)
{
memcpy(Field,&Data[ReadPos],Size);
ReadPos+=Size;
}
else
memset(Field,0,Size);
}
void RawRead::Get(wchar *Field,size_t Size)
{
if (ReadPos+2*Size-1<DataSize)
{
RawToWide(&Data[ReadPos],Field,Size);
ReadPos+=sizeof(wchar)*Size;
}
else
memset(Field,0,sizeof(wchar)*Size);
}
uint RawRead::GetCRC(bool ProcessedOnly)
{
return(DataSize>2 ? CRC(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2):0xffffffff);
}

32
src/unrar/rawread.hpp Normal file
View File

@ -0,0 +1,32 @@
#ifndef _RAR_RAWREAD_
#define _RAR_RAWREAD_
class RawRead
{
private:
Array<byte> Data;
File *SrcFile;
size_t DataSize;
size_t ReadPos;
#ifndef SHELL_EXT
CryptData *Crypt;
#endif
public:
RawRead(File *SrcFile);
void Read(size_t Size);
void Read(byte *SrcData,size_t Size);
void Get(byte &Field);
void Get(ushort &Field);
void Get(uint &Field);
void Get8(int64 &Field);
void Get(byte *Field,size_t Size);
void Get(wchar *Field,size_t Size);
uint GetCRC(bool ProcessedOnly);
size_t Size() {return DataSize;}
size_t PaddedSize() {return Data.Size()-DataSize;}
#ifndef SHELL_EXT
void SetCrypt(CryptData *Crypt) {RawRead::Crypt=Crypt;}
#endif
};
#endif

295
src/unrar/rdwrfn.cpp Normal file
View File

@ -0,0 +1,295 @@
#include "rar.hpp"
ComprDataIO::ComprDataIO()
{
Init();
}
void ComprDataIO::Init()
{
UnpackFromMemory=false;
UnpackToMemory=false;
UnpPackedSize=0;
ShowProgress=true;
TestMode=false;
SkipUnpCRC=false;
PackVolume=false;
UnpVolume=false;
NextVolumeMissing=false;
SrcFile=NULL;
DestFile=NULL;
UnpWrSize=0;
Command=NULL;
Encryption=0;
Decryption=0;
TotalPackRead=0;
CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=0;
PackFileCRC=UnpFileCRC=PackedCRC=0xffffffff;
LastPercent=-1;
SubHead=NULL;
SubHeadPos=NULL;
CurrentCommand=0;
ProcessedArcSize=TotalArcSize=0;
}
int ComprDataIO::UnpRead(byte *Addr,size_t Count)
{
int RetCode=0,TotalRead=0;
byte *ReadAddr;
ReadAddr=Addr;
while (Count > 0)
{
Archive *SrcArc=(Archive *)SrcFile;
size_t ReadSize=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count;
if (UnpackFromMemory)
{
memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize);
RetCode=(int)UnpackFromMemorySize;
UnpackFromMemorySize=0;
}
else
{
if (!SrcFile->IsOpened())
return(-1);
RetCode=SrcFile->Read(ReadAddr,ReadSize);
FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->NewLhd;
if (hd->Flags & LHD_SPLIT_AFTER)
PackedCRC=CRC(PackedCRC,ReadAddr,RetCode);
}
CurUnpRead+=RetCode;
TotalRead+=RetCode;
#ifndef NOVOLUME
// These variable are not used in NOVOLUME mode, so it is better
// to exclude commands below to avoid compiler warnings.
ReadAddr+=RetCode;
Count-=RetCode;
#endif
UnpPackedSize-=RetCode;
if (UnpPackedSize == 0 && UnpVolume)
{
#ifndef NOVOLUME
if (!MergeArchive(*SrcArc,this,true,CurrentCommand))
#endif
{
NextVolumeMissing=true;
return(-1);
}
}
else
break;
}
Archive *SrcArc=(Archive *)SrcFile;
if (SrcArc!=NULL)
ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize);
if (RetCode!=-1)
{
RetCode=TotalRead;
#ifndef RAR_NOCRYPT
if (Decryption)
#ifndef SFX_MODULE
if (Decryption<20)
Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE);
else
if (Decryption==20)
for (int I=0;I<RetCode;I+=16)
Decrypt.DecryptBlock20(&Addr[I]);
else
#endif
{
int CryptSize=(RetCode & 0xf)==0 ? RetCode:((RetCode & ~0xf)+16);
Decrypt.DecryptBlock(Addr,CryptSize);
}
#endif
}
Wait();
return(RetCode);
}
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
// Disable the run time stack check for unrar.dll, so we can manipulate
// with ProcessDataProc call type below. Run time check would intercept
// a wrong ESP before we restore it.
#pragma runtime_checks( "s", off )
#endif
void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
{
#ifdef RARDLL
RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
if (Cmd->DllOpMode!=RAR_SKIP)
{
if (Cmd->Callback!=NULL &&
Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1)
ErrHandler.Exit(RARX_USERBREAK);
if (Cmd->ProcessDataProc!=NULL)
{
// Here we preserve ESP value. It is necessary for those developers,
// who still define ProcessDataProc callback as "C" type function,
// even though in year 2001 we announced in unrar.dll whatsnew.txt
// that it will be PASCAL type (for compatibility with Visual Basic).
#if defined(_MSC_VER)
#ifndef _WIN_64
__asm mov ebx,esp
#endif
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
_EBX=_ESP;
#endif
int RetCode=Cmd->ProcessDataProc(Addr,(int)Count);
// Restore ESP after ProcessDataProc with wrongly defined calling
// convention broken it.
#if defined(_MSC_VER)
#ifndef _WIN_64
__asm mov esp,ebx
#endif
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
_ESP=_EBX;
#endif
if (RetCode==0)
ErrHandler.Exit(RARX_USERBREAK);
}
}
#endif // RARDLL
UnpWrAddr=Addr;
UnpWrSize=Count;
if (UnpackToMemory)
{
if (Count <= UnpackToMemorySize)
{
memcpy(UnpackToMemoryAddr,Addr,Count);
UnpackToMemoryAddr+=Count;
UnpackToMemorySize-=Count;
}
}
else
if (!TestMode)
DestFile->Write(Addr,Count);
CurUnpWrite+=Count;
if (!SkipUnpCRC)
#ifndef SFX_MODULE
if (((Archive *)SrcFile)->OldFormat)
UnpFileCRC=OldCRC((ushort)UnpFileCRC,Addr,Count);
else
#endif
UnpFileCRC=CRC(UnpFileCRC,Addr,Count);
ShowUnpWrite();
Wait();
}
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
// Restore the run time stack check for unrar.dll.
#pragma runtime_checks( "s", restore )
#endif
void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
{
if (ShowProgress && SrcFile!=NULL)
{
if (TotalArcSize!=0)
{
// important when processing several archives or multivolume archive
ArcSize=TotalArcSize;
ArcPos+=ProcessedArcSize;
}
Archive *SrcArc=(Archive *)SrcFile;
RAROptions *Cmd=SrcArc->GetRAROptions();
int CurPercent=ToPercent(ArcPos,ArcSize);
if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
{
mprintf("\b\b\b\b%3d%%",CurPercent);
LastPercent=CurPercent;
}
}
}
void ComprDataIO::ShowUnpWrite()
{
}
void ComprDataIO::SetFiles(File *SrcFile,File *DestFile)
{
if (SrcFile!=NULL)
ComprDataIO::SrcFile=SrcFile;
if (DestFile!=NULL)
ComprDataIO::DestFile=DestFile;
LastPercent=-1;
}
void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size)
{
*Data=UnpWrAddr;
*Size=UnpWrSize;
}
void ComprDataIO::SetEncryption(int Method,SecPassword *Password,const byte *Salt,bool Encrypt,bool HandsOffHash)
{
if (Encrypt)
{
Encryption=Password->IsSet() ? Method:0;
#ifndef RAR_NOCRYPT
Crypt.SetCryptKeys(Password,Salt,Encrypt,false,HandsOffHash);
#endif
}
else
{
Decryption=Password->IsSet() ? Method:0;
#ifndef RAR_NOCRYPT
Decrypt.SetCryptKeys(Password,Salt,Encrypt,Method<29,HandsOffHash);
#endif
}
}
#if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
void ComprDataIO::SetAV15Encryption()
{
Decryption=15;
Decrypt.SetAV15Encryption();
}
#endif
#if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
void ComprDataIO::SetCmt13Encryption()
{
Decryption=13;
Decrypt.SetCmt13Encryption();
}
#endif
void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size)
{
UnpackToMemory=true;
UnpackToMemoryAddr=Addr;
UnpackToMemorySize=Size;
}

88
src/unrar/rdwrfn.hpp Normal file
View File

@ -0,0 +1,88 @@
#ifndef _RAR_DATAIO_
#define _RAR_DATAIO_
class CmdAdd;
class Unpack;
class ComprDataIO
{
private:
void ShowUnpRead(int64 ArcPos,int64 ArcSize);
void ShowUnpWrite();
bool UnpackFromMemory;
size_t UnpackFromMemorySize;
byte *UnpackFromMemoryAddr;
bool UnpackToMemory;
size_t UnpackToMemorySize;
byte *UnpackToMemoryAddr;
size_t UnpWrSize;
byte *UnpWrAddr;
int64 UnpPackedSize;
bool ShowProgress;
bool TestMode;
bool SkipUnpCRC;
File *SrcFile;
File *DestFile;
CmdAdd *Command;
FileHeader *SubHead;
int64 *SubHeadPos;
#ifndef RAR_NOCRYPT
CryptData Crypt;
CryptData Decrypt;
#endif
int LastPercent;
char CurrentCommand;
public:
ComprDataIO();
void Init();
int UnpRead(byte *Addr,size_t Count);
void UnpWrite(byte *Addr,size_t Count);
void EnableShowProgress(bool Show) {ShowProgress=Show;}
void GetUnpackedData(byte **Data,size_t *Size);
void SetPackedSizeToRead(int64 Size) {UnpPackedSize=Size;}
void SetTestMode(bool Mode) {TestMode=Mode;}
void SetSkipUnpCRC(bool Skip) {SkipUnpCRC=Skip;}
void SetFiles(File *SrcFile,File *DestFile);
void SetCommand(CmdAdd *Cmd) {Command=Cmd;}
void SetSubHeader(FileHeader *hd,int64 *Pos) {SubHead=hd;SubHeadPos=Pos;}
void SetEncryption(int Method,SecPassword *Password,const byte *Salt,bool Encrypt,bool HandsOffHash);
void SetAV15Encryption();
void SetCmt13Encryption();
void SetUnpackToMemory(byte *Addr,uint Size);
void SetCurrentCommand(char Cmd) {CurrentCommand=Cmd;}
bool PackVolume;
bool UnpVolume;
bool NextVolumeMissing;
int64 TotalPackRead;
int64 UnpArcSize;
int64 CurPackRead,CurPackWrite,CurUnpRead,CurUnpWrite;
// Size of already processed archives.
// Used to calculate the total operation progress.
int64 ProcessedArcSize;
int64 TotalArcSize;
uint PackFileCRC,UnpFileCRC,PackedCRC;
int Encryption;
int Decryption;
};
#endif

66
src/unrar/readme.txt Normal file
View File

@ -0,0 +1,66 @@
Portable UnRAR version
1. General
This package includes freeware Unrar C++ source and a few makefiles
(makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source
is subset of RAR and generated from RAR source automatically,
by a small program removing blocks like '#ifndef UNRAR ... #endif'.
Such method is not perfect and you may find some RAR related
stuff unnecessary in Unrar, especially in header files.
If you wish to port Unrar to a new platform, you may need to edit
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
in rartypes.hpp.
if computer architecture does not allow not aligned data access,
you need to undefine ALLOW_NOT_ALIGNED_INT and define
STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory
requirements.
If you use Borland C++ makefile (makefile.bcc), you need to define
BASEPATHCC environment (or makefile) variable containing
the path to Borland C++ installation.
Makefile.unix contains numerous compiler option sets.
GCC Linux is selected by default. If you need to compile Unrar
for other platforms, uncomment corresponding lines.
UnRAR.vcproj and UnRARDll.vcproj are projects for Microsoft Visual C++.
UnRARDll.vcproj lets to build unrar.dll library.
2. Unrar binaries
If you compiled Unrar for OS, which is not present in "Downloads"
and "RAR extras" on www.rarlab.com, we will appreciate if you send
us the compiled executable to place it to our site.
3. Acknowledgements
This source includes parts of code written by the following authors:
Dmitry Shkarin PPMII v.H text compression
Dmitry Subbotin Carryless rangecoder
Szymon Stefanek AES encryption
Brian Gladman AES encryption
Steve Reid SHA-1 hash function
Marcus Herbert makefile.unix file
Tomasz Klim fixes for libunrar.so
Robert Riebisch makefile.dj and patches for DJGPP
4. Legal stuff
Unrar source may be used in any software to handle RAR archives
without limitations free of charge, but cannot be used to re-create
the RAR compression algorithm, which is proprietary. Distribution
of modified Unrar source in separate form or as a part of other
software is permitted, provided that it is clearly stated in
the documentation and source comments that the code may not be used
to develop a RAR (WinRAR) compatible archiver.
More detailed license text is available in license.txt.

572
src/unrar/recvol.cpp Normal file
View File

@ -0,0 +1,572 @@
#include "rar.hpp"
// Buffer size for all volumes involved.
static const size_t TotalBufferSize=0x4000000;
class RSEncode // Encode or decode data area, one object per one thread.
{
private:
RSCoder RSC;
public:
void EncodeBuf();
void DecodeBuf();
void Init(int RecVolNumber) {RSC.Init(RecVolNumber);}
byte *Buf;
byte *OutBuf;
int BufStart;
int BufEnd;
int FileNumber;
int RecVolNumber;
size_t RecBufferSize;
int *Erasures;
int EraSize;
};
#ifdef RAR_SMP
THREAD_PROC(RSEncodeThread)
{
RSEncode *rs=(RSEncode *)Data;
rs->EncodeBuf();
}
THREAD_PROC(RSDecodeThread)
{
RSEncode *rs=(RSEncode *)Data;
rs->DecodeBuf();
}
#endif
RecVolumes::RecVolumes()
{
Buf.Alloc(TotalBufferSize);
memset(SrcFile,0,sizeof(SrcFile));
}
RecVolumes::~RecVolumes()
{
for (int I=0;I<ASIZE(SrcFile);I++)
delete SrcFile[I];
}
void RSEncode::EncodeBuf()
{
for (int BufPos=BufStart;BufPos<BufEnd;BufPos++)
{
byte Data[256],Code[256];
for (int I=0;I<FileNumber;I++)
Data[I]=Buf[I*RecBufferSize+BufPos];
RSC.Encode(Data,FileNumber,Code);
for (int I=0;I<RecVolNumber;I++)
OutBuf[I*RecBufferSize+BufPos]=Code[I];
}
}
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
const wchar *NameW,bool Silent)
{
char ArcName[NM];
wchar ArcNameW[NM];
strcpy(ArcName,Name);
wcscpy(ArcNameW,NameW);
char *Ext=GetExt(ArcName);
bool NewStyle=false;
bool RevName=Ext!=NULL && stricomp(Ext,".rev")==0;
if (RevName)
{
for (int DigitGroup=0;Ext>ArcName && DigitGroup<3;Ext--)
if (!IsDigit(*Ext))
if (IsDigit(*(Ext-1)) && (*Ext=='_' || DigitGroup<2))
DigitGroup++;
else
if (DigitGroup<2)
{
NewStyle=true;
break;
}
while (IsDigit(*Ext) && Ext>ArcName+1)
Ext--;
strcpy(Ext,"*.*");
if (*ArcNameW!=0)
{
wchar *ExtW=GetExt(ArcNameW);
for (int DigitGroup=0;ExtW>ArcNameW && DigitGroup<3;ExtW--)
if (!IsDigit(*ExtW))
if (IsDigit(*(ExtW-1)) && (*ExtW=='_' || DigitGroup<2))
DigitGroup++;
else
if (DigitGroup<2)
{
NewStyle=true;
break;
}
while (IsDigit(*ExtW) && ExtW>ArcNameW+1)
ExtW--;
wcscpy(ExtW,L"*.*");
}
FindFile Find;
Find.SetMask(ArcName);
Find.SetMaskW(ArcNameW);
FindData fd;
while (Find.Next(&fd))
{
Archive Arc(Cmd);
if (Arc.WOpen(fd.Name,fd.NameW) && Arc.IsArchive(true))
{
strcpy(ArcName,fd.Name);
wcscpy(ArcNameW,fd.NameW);
break;
}
}
}
Archive Arc(Cmd);
if (!Arc.WCheckOpen(ArcName,ArcNameW))
return(false);
if (!Arc.Volume)
{
#ifndef SILENT
Log(ArcName,St(MNotVolume),ArcName);
#endif
return(false);
}
bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0;
Arc.Close();
char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering);
char RecVolMask[NM];
strcpy(RecVolMask,ArcName);
size_t BaseNamePartLength=VolNumStart-ArcName;
strcpy(RecVolMask+BaseNamePartLength,"*.rev");
wchar RecVolMaskW[NM];
size_t BaseNamePartLengthW=0;
*RecVolMaskW=0;
if (*ArcNameW!=0)
{
wchar *VolNumStartW=VolNameToFirstName(ArcNameW,ArcNameW,NewNumbering);
wcscpy(RecVolMaskW,ArcNameW);
BaseNamePartLengthW=VolNumStartW-ArcNameW;
wcscpy(RecVolMaskW+BaseNamePartLengthW,L"*.rev");
}
#ifndef SILENT
int64 RecFileSize=0;
#endif
// We cannot display "Calculating CRC..." message here, because we do not
// know if we'll find any recovery volumes. We'll display it after finding
// the first recovery volume.
bool CalcCRCMessageDone=false;
FindFile Find;
Find.SetMask(RecVolMask);
Find.SetMaskW(RecVolMaskW);
FindData RecData;
int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0;
char PrevName[NM];
wchar PrevNameW[NM];
while (Find.Next(&RecData))
{
char *CurName=RecData.Name;
wchar *CurNameW=RecData.NameW;
int P[3];
if (!RevName && !NewStyle)
{
NewStyle=true;
char *Dot=GetExt(CurName);
if (Dot!=NULL)
{
int LineCount=0;
Dot--;
while (Dot>CurName && *Dot!='.')
{
if (*Dot=='_')
LineCount++;
Dot--;
}
if (LineCount==2)
NewStyle=false;
}
wchar *DotW=GetExt(CurNameW);
if (DotW!=NULL)
{
int LineCount=0;
DotW--;
while (DotW>CurNameW && *DotW!='.')
{
if (*DotW=='_')
LineCount++;
DotW--;
}
if (LineCount==2)
NewStyle=false;
}
}
if (NewStyle)
{
if (!CalcCRCMessageDone)
{
#ifndef SILENT
mprintf(St(MCalcCRCAllVol));
#endif
CalcCRCMessageDone=true;
}
#ifndef SILENT
mprintf("\r\n%s",CurName);
#endif
File CurFile;
CurFile.TOpen(CurName,CurNameW);
CurFile.Seek(0,SEEK_END);
int64 Length=CurFile.Tell();
CurFile.Seek(Length-7,SEEK_SET);
for (int I=0;I<3;I++)
P[2-I]=CurFile.GetByte()+1;
uint FileCRC=0;
for (int I=0;I<4;I++)
FileCRC|=CurFile.GetByte()<<(I*8);
if (FileCRC!=CalcFileCRC(&CurFile,Length-4))
{
#ifndef SILENT
mprintf(St(MCRCFailed),CurName);
#endif
continue;
}
}
else
{
char *Dot=GetExt(CurName);
if (Dot==NULL)
continue;
bool WrongParam=false;
for (int I=0;I<ASIZE(P);I++)
{
do
{
Dot--;
} while (IsDigit(*Dot) && Dot>=CurName+BaseNamePartLength);
P[I]=atoi(Dot+1);
if (P[I]==0 || P[I]>255)
WrongParam=true;
}
if (WrongParam)
continue;
}
if (P[1]+P[2]>255)
continue;
if (RecVolNumber!=0 && RecVolNumber!=P[1] || FileNumber!=0 && FileNumber!=P[2])
{
#ifndef SILENT
Log(NULL,St(MRecVolDiffSets),CurName,PrevName);
#endif
return(false);
}
RecVolNumber=P[1];
FileNumber=P[2];
strcpy(PrevName,CurName);
wcscpy(PrevNameW,CurNameW);
File *NewFile=new File;
NewFile->TOpen(CurName,CurNameW);
SrcFile[FileNumber+P[0]-1]=NewFile;
FoundRecVolumes++;
#ifndef SILENT
if (RecFileSize==0)
RecFileSize=NewFile->FileLength();
#endif
}
#ifndef SILENT
if (!Silent || FoundRecVolumes!=0)
{
mprintf(St(MRecVolFound),FoundRecVolumes);
}
#endif
if (FoundRecVolumes==0)
return(false);
bool WriteFlags[256];
memset(WriteFlags,0,sizeof(WriteFlags));
char LastVolName[NM];
*LastVolName=0;
wchar LastVolNameW[NM];
*LastVolNameW=0;
for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++)
{
Archive *NewFile=new Archive;
bool ValidVolume=FileExist(ArcName,ArcNameW);
if (ValidVolume)
{
NewFile->TOpen(ArcName,ArcNameW);
ValidVolume=NewFile->IsArchive(false);
if (ValidVolume)
{
while (NewFile->ReadHeader()!=0)
{
if (NewFile->GetHeaderType()==ENDARC_HEAD)
{
#ifndef SILENT
mprintf("\r\n%s",ArcName);
#endif
if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 &&
NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos))
{
ValidVolume=false;
#ifndef SILENT
mprintf(St(MCRCFailed),ArcName);
#endif
}
break;
}
NewFile->SeekToNext();
}
}
if (!ValidVolume)
{
NewFile->Close();
char NewName[NM];
strcpy(NewName,ArcName);
strcat(NewName,".bad");
wchar NewNameW[NM];
wcscpy(NewNameW,ArcNameW);
if (*NewNameW!=0)
wcscat(NewNameW,L".bad");
#ifndef SILENT
mprintf(St(MBadArc),ArcName);
mprintf(St(MRenaming),ArcName,NewName);
#endif
RenameFile(ArcName,ArcNameW,NewName,NewNameW);
}
NewFile->Seek(0,SEEK_SET);
}
if (!ValidVolume)
{
// It is important to return 'false' instead of aborting here,
// so if we are called from extraction, we will be able to continue
// extracting. It may happen if .rar and .rev are on read-only disks
// like CDs.
if (!NewFile->Create(ArcName,ArcNameW))
{
// We need to display the title of operation before the error message,
// to make clear for user that create error is related to recovery
// volumes. This is why we cannot use WCreate call here. Title must be
// before create error, not after that.
#ifndef SILENT
mprintf(St(MReconstructing));
#endif
ErrHandler.CreateErrorMsg(ArcName,ArcNameW);
return false;
}
WriteFlags[CurArcNum]=true;
MissingVolumes++;
if (CurArcNum==FileNumber-1)
{
strcpy(LastVolName,ArcName);
wcscpy(LastVolNameW,ArcNameW);
}
#ifndef SILENT
mprintf(St(MAbsNextVol),ArcName);
#endif
}
SrcFile[CurArcNum]=(File*)NewFile;
NextVolumeName(ArcName,ArcNameW,ASIZE(ArcName),!NewNumbering);
}
#ifndef SILENT
mprintf(St(MRecVolMissing),MissingVolumes);
#endif
if (MissingVolumes==0)
{
#ifndef SILENT
mprintf(St(MRecVolAllExist));
#endif
return(false);
}
if (MissingVolumes>FoundRecVolumes)
{
#ifndef SILENT
mprintf(St(MRecVolCannotFix));
#endif
return(false);
}
#ifndef SILENT
mprintf(St(MReconstructing));
#endif
int TotalFiles=FileNumber+RecVolNumber;
int Erasures[256],EraSize=0;
for (int I=0;I<TotalFiles;I++)
if (WriteFlags[I] || SrcFile[I]==NULL)
Erasures[EraSize++]=I;
#ifndef SILENT
int64 ProcessedSize=0;
#ifndef GUI
int LastPercent=-1;
mprintf(" ");
#endif
#endif
// Size of per file buffer.
size_t RecBufferSize=TotalBufferSize/TotalFiles;
#ifdef RAR_SMP
uint ThreadNumber=Cmd->Threads;
RSEncode rse[MaxPoolThreads];
uint WaitHandles[MaxPoolThreads];
#else
uint ThreadNumber=1;
RSEncode rse[1];
#endif
for (uint I=0;I<ThreadNumber;I++)
rse[I].Init(RecVolNumber);
while (true)
{
Wait();
int MaxRead=0;
for (int I=0;I<TotalFiles;I++)
if (WriteFlags[I] || SrcFile[I]==NULL)
memset(&Buf[I*RecBufferSize],0,RecBufferSize);
else
{
int ReadSize=SrcFile[I]->Read(&Buf[I*RecBufferSize],RecBufferSize);
if (ReadSize!=RecBufferSize)
memset(&Buf[I*RecBufferSize+ReadSize],0,RecBufferSize-ReadSize);
if (ReadSize>MaxRead)
MaxRead=ReadSize;
}
if (MaxRead==0)
break;
#ifndef SILENT
int CurPercent=ToPercent(ProcessedSize,RecFileSize);
if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
{
mprintf("\b\b\b\b%3d%%",CurPercent);
LastPercent=CurPercent;
}
ProcessedSize+=MaxRead;
#endif
int BlockStart=0;
int BlockSize=MaxRead/ThreadNumber;
if (BlockSize<0x100)
BlockSize=MaxRead;
uint CurThread=0;
while (BlockStart<MaxRead)
{
// Last thread processes all left data including increasement
// from rounding error.
if (CurThread==ThreadNumber-1)
BlockSize=MaxRead-BlockStart;
RSEncode *curenc=rse+CurThread;
curenc->Buf=&Buf[0];
curenc->BufStart=BlockStart;
curenc->BufEnd=BlockStart+BlockSize;
curenc->FileNumber=TotalFiles;
curenc->RecBufferSize=RecBufferSize;
curenc->Erasures=Erasures;
curenc->EraSize=EraSize;
#ifdef RAR_SMP
if (ThreadNumber>1)
{
uint Handle=RSThreadPool.Start(RSDecodeThread,(void*)curenc);
WaitHandles[CurThread++]=Handle;
}
else
curenc->DecodeBuf();
#else
curenc->DecodeBuf();
#endif
BlockStart+=BlockSize;
}
#ifdef RAR_SMP
if (CurThread>0)
RSThreadPool.Wait(WaitHandles,CurThread);
#endif // RAR_SMP
for (int I=0;I<FileNumber;I++)
if (WriteFlags[I])
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
}
for (int I=0;I<RecVolNumber+FileNumber;I++)
if (SrcFile[I]!=NULL)
{
File *CurFile=SrcFile[I];
if (NewStyle && WriteFlags[I])
{
int64 Length=CurFile->Tell();
CurFile->Seek(Length-7,SEEK_SET);
for (int J=0;J<7;J++)
CurFile->PutByte(0);
}
CurFile->Close();
SrcFile[I]=NULL;
}
if (*LastVolName!=0 || *LastVolNameW!=0)
{
// Truncate the last volume to its real size.
Archive Arc(Cmd);
if (Arc.Open(LastVolName,LastVolNameW,FMF_UPDATE) && Arc.IsArchive(true) &&
Arc.SearchBlock(ENDARC_HEAD))
{
Arc.Seek(Arc.NextBlockPos,SEEK_SET);
char Buf[8192];
int ReadSize=Arc.Read(Buf,sizeof(Buf));
int ZeroCount=0;
while (ZeroCount<ReadSize && Buf[ZeroCount]==0)
ZeroCount++;
if (ZeroCount==ReadSize)
{
Arc.Seek(Arc.NextBlockPos,SEEK_SET);
Arc.Truncate();
}
}
}
#if !defined(GUI) && !defined(SILENT)
if (!Cmd->DisablePercentage)
mprintf("\b\b\b\b100%%");
if (!Silent && !Cmd->DisableDone)
mprintf(St(MDone));
#endif
return(true);
}
void RSEncode::DecodeBuf()
{
for (int BufPos=BufStart;BufPos<BufEnd;BufPos++)
{
byte Data[256];
for (int I=0;I<FileNumber;I++)
Data[I]=Buf[I*RecBufferSize+BufPos];
RSC.Decode(Data,FileNumber,Erasures,EraSize);
for (int I=0;I<EraSize;I++)
Buf[Erasures[I]*RecBufferSize+BufPos]=Data[Erasures[I]];
}
}

20
src/unrar/recvol.hpp Normal file
View File

@ -0,0 +1,20 @@
#ifndef _RAR_RECVOL_
#define _RAR_RECVOL_
class RecVolumes
{
private:
File *SrcFile[256];
Array<byte> Buf;
#ifdef RAR_SMP
ThreadPool RSThreadPool;
#endif
public:
RecVolumes();
~RecVolumes();
void Make(RAROptions *Cmd,char *ArcName,wchar *ArcNameW);
bool Restore(RAROptions *Cmd,const char *Name,const wchar *NameW,bool Silent);
};
#endif

27
src/unrar/resource.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "rar.hpp"
#ifndef RARDLL
const char *St(MSGID StringId)
{
return(StringId);
}
#endif
#ifndef RARDLL
const wchar *StW(MSGID StringId)
{
static wchar StrTable[8][512];
static int StrNum=0;
if (++StrNum >= sizeof(StrTable)/sizeof(StrTable[0]))
StrNum=0;
wchar *Str=StrTable[StrNum];
*Str=0;
CharToWide(StringId,Str,ASIZE(StrTable[0]));
return(Str);
}
#endif

13
src/unrar/resource.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef _RAR_RESOURCE_
#define _RAR_RESOURCE_
#ifdef RARDLL
#define St(x) ( "")
#define StW(x) (L"")
#else
const char *St (MSGID StringId);
const wchar *StW (MSGID StringId);
#endif
#endif

298
src/unrar/rijndael.cpp Normal file
View File

@ -0,0 +1,298 @@
/**************************************************************************
* This code is based on Szymon Stefanek AES implementation: *
* http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-cpplib.tar.gz *
* *
* Dynamic tables generation is based on the Brian Gladman work: *
* http://fp.gladman.plus.com/cryptography_technology/rijndael *
**************************************************************************/
#include "rar.hpp"
const int uKeyLenInBytes=16, m_uRounds=10;
static byte S[256],S5[256],rcon[30];
static byte T1[256][4],T2[256][4],T3[256][4],T4[256][4];
static byte T5[256][4],T6[256][4],T7[256][4],T8[256][4];
static byte U1[256][4],U2[256][4],U3[256][4],U4[256][4];
inline void Xor128(byte *dest,const byte *arg1,const byte *arg2)
{
#if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
((uint32*)dest)[0]=((uint32*)arg1)[0]^((uint32*)arg2)[0];
((uint32*)dest)[1]=((uint32*)arg1)[1]^((uint32*)arg2)[1];
((uint32*)dest)[2]=((uint32*)arg1)[2]^((uint32*)arg2)[2];
((uint32*)dest)[3]=((uint32*)arg1)[3]^((uint32*)arg2)[3];
#else
for (int I=0;I<16;I++)
dest[I]=arg1[I]^arg2[I];
#endif
}
inline void Xor128(byte *dest,const byte *arg1,const byte *arg2,
const byte *arg3,const byte *arg4)
{
#if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
(*(uint32*)dest)=(*(uint32*)arg1)^(*(uint32*)arg2)^(*(uint32*)arg3)^(*(uint32*)arg4);
#else
for (int I=0;I<4;I++)
dest[I]=arg1[I]^arg2[I]^arg3[I]^arg4[I];
#endif
}
inline void Copy128(byte *dest,const byte *src)
{
#if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
((uint32*)dest)[0]=((uint32*)src)[0];
((uint32*)dest)[1]=((uint32*)src)[1];
((uint32*)dest)[2]=((uint32*)src)[2];
((uint32*)dest)[3]=((uint32*)src)[3];
#else
for (int I=0;I<16;I++)
dest[I]=src[I];
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// API
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Rijndael::Rijndael()
{
if (S[0]==0)
GenerateTables();
}
void Rijndael::init(Direction dir,const byte * key,byte * initVector)
{
m_direction = dir;
byte keyMatrix[_MAX_KEY_COLUMNS][4];
for(uint i = 0;i < uKeyLenInBytes;i++)
keyMatrix[i >> 2][i & 3] = key[i];
for(int i = 0;i < MAX_IV_SIZE;i++)
m_initVector[i] = initVector[i];
keySched(keyMatrix);
if(m_direction == Decrypt)
keyEncToDec();
}
size_t Rijndael::blockDecrypt(const byte *input, size_t inputLen, byte *outBuffer)
{
if (input == 0 || inputLen <= 0)
return 0;
byte block[16], iv[4][4];
memcpy(iv,m_initVector,16);
size_t numBlocks=inputLen/16;
for (size_t i = numBlocks; i > 0; i--)
{
decrypt(input, block);
Xor128(block,block,(byte*)iv);
#if STRICT_ALIGN
memcpy(iv, input, 16);
memcpy(outBuf, block, 16);
#else
Copy128((byte*)iv,input);
Copy128(outBuffer,block);
#endif
input += 16;
outBuffer += 16;
}
memcpy(m_initVector,iv,16);
return 16*numBlocks;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ALGORITHM
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Rijndael::keySched(byte key[_MAX_KEY_COLUMNS][4])
{
int j,rconpointer = 0;
// Calculate the necessary round keys
// The number of calculations depends on keyBits and blockBits
int uKeyColumns = m_uRounds - 6;
byte tempKey[_MAX_KEY_COLUMNS][4];
// Copy the input key to the temporary key matrix
memcpy(tempKey,key,sizeof(tempKey));
int r = 0;
int t = 0;
// copy values into round key array
for(j = 0;(j < uKeyColumns) && (r <= m_uRounds); )
{
for(;(j < uKeyColumns) && (t < 4); j++, t++)
for (int k=0;k<4;k++)
m_expandedKey[r][t][k]=tempKey[j][k];
if(t == 4)
{
r++;
t = 0;
}
}
while(r <= m_uRounds)
{
tempKey[0][0] ^= S[tempKey[uKeyColumns-1][1]];
tempKey[0][1] ^= S[tempKey[uKeyColumns-1][2]];
tempKey[0][2] ^= S[tempKey[uKeyColumns-1][3]];
tempKey[0][3] ^= S[tempKey[uKeyColumns-1][0]];
tempKey[0][0] ^= rcon[rconpointer++];
if (uKeyColumns != 8)
for(j = 1; j < uKeyColumns; j++)
for (int k=0;k<4;k++)
tempKey[j][k] ^= tempKey[j-1][k];
else
{
for(j = 1; j < uKeyColumns/2; j++)
for (int k=0;k<4;k++)
tempKey[j][k] ^= tempKey[j-1][k];
tempKey[uKeyColumns/2][0] ^= S[tempKey[uKeyColumns/2 - 1][0]];
tempKey[uKeyColumns/2][1] ^= S[tempKey[uKeyColumns/2 - 1][1]];
tempKey[uKeyColumns/2][2] ^= S[tempKey[uKeyColumns/2 - 1][2]];
tempKey[uKeyColumns/2][3] ^= S[tempKey[uKeyColumns/2 - 1][3]];
for(j = uKeyColumns/2 + 1; j < uKeyColumns; j++)
for (int k=0;k<4;k++)
tempKey[j][k] ^= tempKey[j-1][k];
}
for(j = 0; (j < uKeyColumns) && (r <= m_uRounds); )
{
for(; (j < uKeyColumns) && (t < 4); j++, t++)
for (int k=0;k<4;k++)
m_expandedKey[r][t][k] = tempKey[j][k];
if(t == 4)
{
r++;
t = 0;
}
}
}
}
void Rijndael::keyEncToDec()
{
for(int r = 1; r < m_uRounds; r++)
{
byte n_expandedKey[4][4];
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
{
byte *w=m_expandedKey[r][j];
n_expandedKey[j][i]=U1[w[0]][i]^U2[w[1]][i]^U3[w[2]][i]^U4[w[3]][i];
}
memcpy(m_expandedKey[r],n_expandedKey,sizeof(m_expandedKey[0]));
}
}
void Rijndael::decrypt(const byte a[16], byte b[16])
{
int r;
byte temp[4][4];
Xor128((byte*)temp,(byte*)a,(byte*)m_expandedKey[m_uRounds]);
Xor128(b, T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
Xor128(b+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
Xor128(b+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
Xor128(b+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
for(r = m_uRounds-1; r > 1; r--)
{
Xor128((byte*)temp,(byte*)b,(byte*)m_expandedKey[r]);
Xor128(b, T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
Xor128(b+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
Xor128(b+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
Xor128(b+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
}
Xor128((byte*)temp,(byte*)b,(byte*)m_expandedKey[1]);
b[ 0] = S5[temp[0][0]];
b[ 1] = S5[temp[3][1]];
b[ 2] = S5[temp[2][2]];
b[ 3] = S5[temp[1][3]];
b[ 4] = S5[temp[1][0]];
b[ 5] = S5[temp[0][1]];
b[ 6] = S5[temp[3][2]];
b[ 7] = S5[temp[2][3]];
b[ 8] = S5[temp[2][0]];
b[ 9] = S5[temp[1][1]];
b[10] = S5[temp[0][2]];
b[11] = S5[temp[3][3]];
b[12] = S5[temp[3][0]];
b[13] = S5[temp[2][1]];
b[14] = S5[temp[1][2]];
b[15] = S5[temp[0][3]];
Xor128((byte*)b,(byte*)b,(byte*)m_expandedKey[0]);
}
#define ff_poly 0x011b
#define ff_hi 0x80
#define FFinv(x) ((x) ? pow[255 - log[x]]: 0)
#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0)
#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0)
#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0)
#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0)
#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0)
#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0)
#define fwd_affine(x) \
(w = (uint)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), (byte)(0x63^(w^(w>>8))))
#define inv_affine(x) \
(w = (uint)x, w = (w<<1)^(w<<3)^(w<<6), (byte)(0x05^(w^(w>>8))))
void Rijndael::GenerateTables()
{
unsigned char pow[512],log[256];
int i = 0, w = 1;
do
{
pow[i] = (byte)w;
pow[i + 255] = (byte)w;
log[w] = (byte)i++;
w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0);
} while (w != 1);
for (int i = 0,w = 1; i < sizeof(rcon)/sizeof(rcon[0]); i++)
{
rcon[i] = w;
w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
}
for(int i = 0; i < 256; ++i)
{
unsigned char b=S[i]=fwd_affine(FFinv((byte)i));
T1[i][1]=T1[i][2]=T2[i][2]=T2[i][3]=T3[i][0]=T3[i][3]=T4[i][0]=T4[i][1]=b;
T1[i][0]=T2[i][1]=T3[i][2]=T4[i][3]=FFmul02(b);
T1[i][3]=T2[i][0]=T3[i][1]=T4[i][2]=FFmul03(b);
S5[i] = b = FFinv(inv_affine((byte)i));
U1[b][3]=U2[b][0]=U3[b][1]=U4[b][2]=T5[i][3]=T6[i][0]=T7[i][1]=T8[i][2]=FFmul0b(b);
U1[b][1]=U2[b][2]=U3[b][3]=U4[b][0]=T5[i][1]=T6[i][2]=T7[i][3]=T8[i][0]=FFmul09(b);
U1[b][2]=U2[b][3]=U3[b][0]=U4[b][1]=T5[i][2]=T6[i][3]=T7[i][0]=T8[i][1]=FFmul0d(b);
U1[b][0]=U2[b][1]=U3[b][2]=U4[b][3]=T5[i][0]=T6[i][1]=T7[i][2]=T8[i][3]=FFmul0e(b);
}
}

37
src/unrar/rijndael.hpp Normal file
View File

@ -0,0 +1,37 @@
#ifndef _RIJNDAEL_H_
#define _RIJNDAEL_H_
/**************************************************************************
* This code is based on Szymon Stefanek AES implementation: *
* http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-cpplib.tar.gz *
* *
* Dynamic tables generation is based on the Brian Gladman's work: *
* http://fp.gladman.plus.com/cryptography_technology/rijndael *
**************************************************************************/
#define _MAX_KEY_COLUMNS (256/32)
#define _MAX_ROUNDS 14
#define MAX_IV_SIZE 16
class Rijndael
{
public:
enum Direction { Encrypt , Decrypt };
private:
void keySched(byte key[_MAX_KEY_COLUMNS][4]);
void keyEncToDec();
void encrypt(const byte a[16], byte b[16]);
void decrypt(const byte a[16], byte b[16]);
void GenerateTables();
Direction m_direction;
byte m_initVector[MAX_IV_SIZE];
byte m_expandedKey[_MAX_ROUNDS+1][4][4];
public:
Rijndael();
void init(Direction dir,const byte *key,byte *initVector);
size_t blockEncrypt(const byte *input, size_t inputLen, byte *outBuffer);
size_t blockDecrypt(const byte *input, size_t inputLen, byte *outBuffer);
};
#endif // _RIJNDAEL_H_

172
src/unrar/rs.cpp Normal file
View File

@ -0,0 +1,172 @@
#include "rar.hpp"
#define Clean(D,S) {for (int I=0;I<(S);I++) (D)[I]=0;}
void RSCoder::Init(int ParSize)
{
RSCoder::ParSize=ParSize; // Store the number of recovery volumes.
FirstBlockDone=false;
gfInit();
pnInit();
}
// Initialize logarithms and exponents Galois field tables.
void RSCoder::gfInit()
{
for (int I=0,J=1;I<MAXPAR;I++)
{
gfLog[J]=I;
gfExp[I]=J;
J<<=1;
if (J & 0x100)
J^=0x11D; // 0x11D field-generator polynomial (x^8+x^4+x^3+x^2+1).
}
for (int I=MAXPAR;I<MAXPOL;I++)
gfExp[I]=gfExp[I-MAXPAR];
}
// Multiplication over Galois field.
inline int RSCoder::gfMult(int a,int b)
{
return(a==0 || b == 0 ? 0:gfExp[gfLog[a]+gfLog[b]]);
}
// Create the generator polynomial g(x).
// g(x)=(x-a)(x-a^2)(x-a^3)..(x-a^N)
void RSCoder::pnInit()
{
int p2[MAXPAR+1]; // Currently calculated part of g(x).
Clean(p2,ParSize);
p2[0]=1; // Set p2 polynomial to 1.
for (int I=1;I<=ParSize;I++)
{
int p1[MAXPAR+1]; // We use p1 as current (x+a^i) expression.
Clean(p1,ParSize);
p1[0]=gfExp[I];
p1[1]=1; // Set p1 polynomial to x+a^i.
// Multiply the already calucated part of g(x) to next (x+a^i).
pnMult(p1,p2,GXPol);
// p2=g(x).
for (int J=0;J<ParSize;J++)
p2[J]=GXPol[J];
}
}
// Multiply polynomial 'p1' to 'p2' and store the result in 'r'.
void RSCoder::pnMult(int *p1,int *p2,int *r)
{
Clean(r,ParSize);
for (int I=0;I<ParSize;I++)
if (p1[I]!=0)
for(int J=0;J<ParSize-I;J++)
r[I+J]^=gfMult(p1[I],p2[J]);
}
void RSCoder::Encode(byte *Data,int DataSize,byte *DestData)
{
int ShiftReg[MAXPAR+1]; // Linear Feedback Shift Register.
Clean(ShiftReg,ParSize+1);
for (int I=0;I<DataSize;I++)
{
int D=Data[I]^ShiftReg[ParSize-1];
// Use g(x) to define feedback taps.
for (int J=ParSize-1;J>0;J--)
ShiftReg[J]=ShiftReg[J-1]^gfMult(GXPol[J],D);
ShiftReg[0]=gfMult(GXPol[0],D);
}
for (int I=0;I<ParSize;I++)
DestData[I]=ShiftReg[ParSize-I-1];
}
bool RSCoder::Decode(byte *Data,int DataSize,int *EraLoc,int EraSize)
{
int SynData[MAXPOL]; // Syndrome data.
bool AllZeroes=true;
for (int I=0;I<ParSize;I++)
{
int Sum=Data[0],J=1,Exp=gfExp[I+1];
for (;J+8<=DataSize;J+=8) // Unroll the loop for speed.
{
Sum=Data[J]^gfMult(Exp,Sum);
Sum=Data[J+1]^gfMult(Exp,Sum);
Sum=Data[J+2]^gfMult(Exp,Sum);
Sum=Data[J+3]^gfMult(Exp,Sum);
Sum=Data[J+4]^gfMult(Exp,Sum);
Sum=Data[J+5]^gfMult(Exp,Sum);
Sum=Data[J+6]^gfMult(Exp,Sum);
Sum=Data[J+7]^gfMult(Exp,Sum);
}
for (;J<DataSize;J++)
Sum=Data[J]^gfMult(Exp,Sum);
if ((SynData[I]=Sum)!=0)
AllZeroes=false;
}
// If all syndrome numbers are zero, message does not have errors.
if (AllZeroes)
return(true);
if (!FirstBlockDone) // Do things which we need to do once for all data.
{
FirstBlockDone=true;
// Calculate the error locator polynomial.
Clean(ELPol,ParSize+1);
ELPol[0]=1;
for (int EraPos=0;EraPos<EraSize;EraPos++)
for (int I=ParSize,M=gfExp[DataSize-EraLoc[EraPos]-1];I>0;I--)
ELPol[I]^=gfMult(M,ELPol[I-1]);
ErrCount=0;
// Find roots of error locator polynomial.
for (int Root=MAXPAR-DataSize;Root<MAXPAR+1;Root++)
{
int Sum=0;
for (int B=0;B<ParSize+1;B++)
Sum^=gfMult(gfExp[(B*Root)%MAXPAR],ELPol[B]);
if (Sum==0) // Root found.
{
ErrorLocs[ErrCount]=MAXPAR-Root; // Location of error.
// Calculate the denominator for every error location.
Dnm[ErrCount]=0;
for (int I=1;I<ParSize+1;I+=2)
Dnm[ErrCount]^= gfMult(ELPol[I],gfExp[Root*(I-1)%MAXPAR]);
ErrCount++;
}
}
}
int EEPol[MAXPOL]; // Error Evaluator Polynomial.
pnMult(ELPol,SynData,EEPol);
// If errors are present and their number is correctable.
if ((ErrCount<=ParSize) && ErrCount>0)
for (int I=0;I<ErrCount;I++)
{
int Loc=ErrorLocs[I],DLoc=MAXPAR-Loc,N=0;
for (int J=0;J<ParSize;J++)
N^=gfMult(EEPol[J],gfExp[DLoc*J%MAXPAR]);
int DataPos=DataSize-Loc-1;
// Perform bounds check and correct the data error.
if (DataPos>=0 && DataPos<DataSize)
Data[DataPos]^=gfMult(N,gfExp[MAXPAR-gfLog[Dnm[I]]]);
}
return(ErrCount<=ParSize); // Return true if success.
}

32
src/unrar/rs.hpp Normal file
View File

@ -0,0 +1,32 @@
#ifndef _RAR_RS_
#define _RAR_RS_
#define MAXPAR 255 // Maximum parity data size.
#define MAXPOL 512 // Maximum polynomial degree.
class RSCoder
{
private:
void gfInit();
int gfMult(int a,int b);
void pnInit();
void pnMult(int *p1,int *p2,int *r);
int gfExp[MAXPOL]; // Galois field exponents.
int gfLog[MAXPAR+1]; // Galois field logarithms.
int GXPol[MAXPOL*2]; // Generator polynomial g(x).
int ErrorLocs[MAXPAR+1],ErrCount;
int Dnm[MAXPAR+1];
int ParSize; // Parity bytes size and so the number of recovery volumes.
int ELPol[MAXPOL]; // Error locator polynomial.
bool FirstBlockDone;
public:
void Init(int ParSize);
void Encode(byte *Data,int DataSize,byte *DestData);
bool Decode(byte *Data,int DataSize,int *EraLoc,int EraSize);
};
#endif

15
src/unrar/savepos.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "rar.hpp"
SaveFilePos::SaveFilePos(File &SaveFile)
{
SaveFilePos::SaveFile=&SaveFile;
SavePos=SaveFile.Tell();
CloseCount=SaveFile.CloseCount;
}
SaveFilePos::~SaveFilePos()
{
if (CloseCount==SaveFile->CloseCount)
SaveFile->Seek(SavePos,SEEK_SET);
}

15
src/unrar/savepos.hpp Normal file
View File

@ -0,0 +1,15 @@
#ifndef _RAR_SAVEPOS_
#define _RAR_SAVEPOS_
class SaveFilePos
{
private:
File *SaveFile;
int64 SavePos;
uint CloseCount;
public:
SaveFilePos(File &SaveFile);
~SaveFilePos();
};
#endif

413
src/unrar/scantree.cpp Normal file
View File

@ -0,0 +1,413 @@
#include "rar.hpp"
ScanTree::ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs)
{
ScanTree::FileMasks=FileMasks;
ScanTree::Recurse=Recurse;
ScanTree::GetLinks=GetLinks;
ScanTree::GetDirs=GetDirs;
ScanEntireDisk=false;
SetAllMaskDepth=0;
*CurMask=0;
*CurMaskW=0;
memset(FindStack,0,sizeof(FindStack));
Depth=0;
Errors=0;
*ErrArcName=0;
Cmd=NULL;
}
ScanTree::~ScanTree()
{
for (int I=Depth;I>=0;I--)
if (FindStack[I]!=NULL)
delete FindStack[I];
}
SCAN_CODE ScanTree::GetNext(FindData *FindData)
{
if (Depth<0)
return(SCAN_DONE);
SCAN_CODE FindCode;
while (1)
{
if (*CurMask==0 && !GetNextMask())
return(SCAN_DONE);
FindCode=FindProc(FindData);
if (FindCode==SCAN_ERROR)
{
Errors++;
continue;
}
if (FindCode==SCAN_NEXT)
continue;
if (FindCode==SCAN_SUCCESS && FindData->IsDir && GetDirs==SCAN_SKIPDIRS)
continue;
if (FindCode==SCAN_DONE && GetNextMask())
continue;
break;
}
return(FindCode);
}
bool ScanTree::GetNextMask()
{
if (!FileMasks->GetString(CurMask,CurMaskW,ASIZE(CurMask)))
return(false);
if (*CurMask==0 && *CurMaskW!=0)
{
// Unicode only mask is present. It is very unlikely in console tools,
// but possible if called from GUI WinRAR. We still need to have
// ASCII mask, because we use ASCII only mask in some checks later.
// So let's convert Unicode to ASCII.
WideToChar(CurMaskW,CurMask,ASIZE(CurMask));
}
CurMask[ASIZE(CurMask)-1]=0;
CurMaskW[ASIZE(CurMaskW)-1]=0;
#ifdef _WIN_ALL
UnixSlashToDos(CurMask);
#endif
// We wish to scan entire disk if mask like c:\ is specified
// regardless of recursion mode. Use c:\*.* mask when need to scan only
// the root directory.
ScanEntireDisk=IsDiskLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;
char *Name=PointToName(CurMask);
if (*Name==0)
strcat(CurMask,MASKALL);
if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
{
AddEndSlash(CurMask);
strcat(CurMask,MASKALL);
}
SpecPathLength=Name-CurMask;
bool WideName=(*CurMaskW!=0);
if (WideName)
{
wchar *NameW=PointToName(CurMaskW);
if (*NameW==0)
wcscat(CurMaskW,MASKALLW);
if (NameW[0]=='.' && (NameW[1]==0 || NameW[1]=='.' && NameW[2]==0))
{
AddEndSlash(CurMaskW);
wcscat(CurMaskW,MASKALLW);
}
SpecPathLengthW=NameW-CurMaskW;
}
else
{
wchar WideMask[NM];
CharToWide(CurMask,WideMask);
SpecPathLengthW=PointToName(WideMask)-WideMask;
}
Depth=0;
strcpy(OrigCurMask,CurMask);
// It is better to have non-empty OrigCurMaskW even if CurMaskW is empty.
// We need OrigCurMaskW to process Unicode masks generated by FindProc
// when encountering Unicode directory name.
GetWideName(CurMask,CurMaskW,OrigCurMaskW,ASIZE(OrigCurMaskW));
return(true);
}
SCAN_CODE ScanTree::FindProc(FindData *FD)
{
if (*CurMask==0)
return(SCAN_NEXT);
bool FastFindFile=false;
if (FindStack[Depth]==NULL) // No FindFile object for this depth yet.
{
bool Wildcards=IsWildcard(CurMask,CurMaskW);
// If we have a file name without wildcards, we can try to use
// FastFind to optimize speed. For example, in Unix it results in
// stat call instead of opendir/readdir/closedir.
bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FD,GetLinks);
bool IsDir=FindCode && FD->IsDir;
// SearchAll means that we'll use "*" mask for search, so we'll find
// subdirectories and will be able to recurse into them.
// We do not use "*" for directories at any level or for files
// at top level in recursion mode.
bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
Wildcards && Recurse==RECURSE_WILDCARDS ||
ScanEntireDisk && Recurse!=RECURSE_DISABLE);
if (Depth==0)
SearchAllInRoot=SearchAll;
if (SearchAll || Wildcards)
{
// Create the new FindFile object for wildcard based search.
FindStack[Depth]=new FindFile;
char SearchMask[NM];
strcpy(SearchMask,CurMask);
if (SearchAll)
strcpy(PointToName(SearchMask),MASKALL);
FindStack[Depth]->SetMask(SearchMask);
if (*CurMaskW!=0)
{
wchar SearchMaskW[NM];
wcscpy(SearchMaskW,CurMaskW);
if (SearchAll)
wcscpy(PointToName(SearchMaskW),MASKALLW);
FindStack[Depth]->SetMaskW(SearchMaskW);
}
}
else
{
// Either we failed to fast find or we found a file or we found
// a directory in RECURSE_DISABLE mode, so we do not need to scan it.
// We can return here and do not need to process further.
// We need to process further only if we fast found a directory.
if (!FindCode || !FD->IsDir || Recurse==RECURSE_DISABLE)
{
// Return SCAN_SUCCESS if we found a file.
SCAN_CODE RetCode=SCAN_SUCCESS;
if (!FindCode)
{
// Return SCAN_ERROR if problem is more serious than just
// "file not found".
RetCode=FD->Error ? SCAN_ERROR:SCAN_NEXT;
// If we failed to find an object, but our current mask is excluded,
// we skip this object and avoid indicating an error.
if (Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true))
RetCode=SCAN_NEXT;
else
ErrHandler.OpenErrorMsg(ErrArcName,NULL,CurMask,CurMaskW);
}
// If we searched only for one file or directory in "fast find"
// (without a wildcard) mode, let's set masks to zero,
// so calling function will know that current mask is used
// and next one must be read from mask list for next call.
// It is not necessary for directories, because even in "fast find"
// mode, directory recursing will quit by (Depth < 0) condition,
// which returns SCAN_DONE to calling function.
*CurMask=0;
*CurMaskW=0;
return(RetCode);
}
// We found a directory using only FindFile::FastFind function.
FastFindFile=true;
}
}
if (!FastFindFile && !FindStack[Depth]->Next(FD,GetLinks))
{
// We cannot find anything more in directory either because of
// some error or just as result of all directory entries already read.
bool Error=FD->Error;
#ifdef _WIN_ALL
if (Error)
{
// Do not display an error if we cannot scan contents of reparse
// point. Vista contains a lot of reparse (or junction) points,
// which are not accessible.
if ((FD->FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
Error=false;
// Do not display an error if we cannot scan contents of
// "System Volume Information" folder. Normally it is not accessible.
if (strstr(CurMask,"System Volume Information\\")!=NULL)
Error=false;
}
#endif
if (Error && Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true))
Error=false;
#ifndef SILENT
if (Error)
{
Log(NULL,St(MScanError),CurMask);
ErrHandler.SysErrMsg();
}
#endif
char DirName[NM];
wchar DirNameW[NM];
*DirName=0;
*DirNameW=0;
// Going to at least one directory level higher.
delete FindStack[Depth];
FindStack[Depth--]=NULL;
while (Depth>=0 && FindStack[Depth]==NULL)
Depth--;
if (Depth < 0)
{
// Directories scanned both in normal and FastFindFile mode,
// finally exit from scan here, by (Depth < 0) condition.
if (Error)
Errors++;
return(SCAN_DONE);
}
char *Slash=strrchrd(CurMask,CPATHDIVIDER);
if (Slash!=NULL)
{
char Mask[NM];
strcpy(Mask,Slash);
if (Depth<SetAllMaskDepth)
strcpy(Mask+1,PointToName(OrigCurMask));
*Slash=0;
strcpy(DirName,CurMask);
char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
if (PrevSlash==NULL)
strcpy(CurMask,Mask+1);
else
strcpy(PrevSlash,Mask);
}
if (*CurMaskW!=0)
{
wchar *Slash=wcsrchr(CurMaskW,CPATHDIVIDER);
if (Slash!=NULL)
{
wchar Mask[NM];
wcscpy(Mask,Slash);
if (Depth<SetAllMaskDepth)
{
wcscpy(Mask+1,PointToName(OrigCurMaskW));
// FindProc function can generate Unicode CurMaskW when encountering
// Unicode directory name even if Unicode mask was not specified.
// But we must reset such temporary mask here if OrigCurMaskW is
// empty, because we cannot shorten it correctly. It should not
// happen normally though, because we attempt to ensure that
// OrigCurMaskW is not empty. So it can happen only if converting
// OrigCurMask to OrigCurMaskW has been failed.
if (*OrigCurMaskW==0)
*CurMaskW=Mask[0]=Mask[1]=0;
}
*Slash=0;
wcscpy(DirNameW,CurMaskW);
wchar *PrevSlash=wcsrchr(CurMaskW,CPATHDIVIDER);
if (PrevSlash==NULL)
wcscpy(CurMaskW,Mask+1);
else
wcscpy(PrevSlash,Mask);
}
#ifndef _WIN_CE
// if (LowAscii(CurMaskW))
// *CurMaskW=0;
#endif
}
if (GetDirs==SCAN_GETDIRSTWICE &&
FindFile::FastFind(DirName,DirNameW,FD,GetLinks) && FD->IsDir)
{
FD->Flags|=FDDF_SECONDDIR;
return(Error ? SCAN_ERROR:SCAN_SUCCESS);
}
return(Error ? SCAN_ERROR:SCAN_NEXT);
}
if (FD->IsDir)
{
// If we found the directory in top (Depth==0) directory
// and if we are not in "fast find" (directory name only as argument)
// or in recurse (SearchAll was set when opening the top directory) mode,
// we do not recurse into this directory. We either return it by itself
// or skip it.
if (!FastFindFile && Depth==0 && !SearchAllInRoot)
return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);
// Let's check if directory name is excluded, so we do not waste
// time searching in directory, which will be excluded anyway.
if (Cmd!=NULL && (Cmd->ExclCheck(FD->Name,true,false,false) ||
Cmd->ExclDirByAttr(FD->FileAttr)))
{
// If we are here in "fast find" mode, it means that entire directory
// specified in command line is excluded. Then we need to return
// SCAN_DONE to go to next mask and avoid the infinite loop
// in GetNext() function. Such loop would be possible in case of
// SCAN_NEXT code and "rar a arc dir -xdir" command.
return(FastFindFile ? SCAN_DONE:SCAN_NEXT);
}
char Mask[NM];
strcpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask));
strcpy(CurMask,FD->Name);
if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
{
#ifndef SILENT
Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
Log(NULL,St(MPathTooLong));
#endif
return(SCAN_ERROR);
}
AddEndSlash(CurMask);
strcat(CurMask,Mask);
if (*CurMaskW!=0 && *FD->NameW==0)
CharToWide(FD->Name,FD->NameW);
if (*FD->NameW!=0)
{
wchar Mask[NM];
if (FastFindFile)
wcscpy(Mask,MASKALLW);
else
if (*CurMaskW!=0)
wcscpy(Mask,PointToName(CurMaskW));
else
CharToWide(PointToName(CurMask),Mask);
wcscpy(CurMaskW,FD->NameW);
AddEndSlash(CurMaskW);
wcscat(CurMaskW,Mask);
}
Depth++;
// We need to use OrigCurMask for depths less than SetAllMaskDepth
// and "*" for depths equal or larger than SetAllMaskDepth.
// It is important when "fast finding" directories at Depth > 0.
// For example, if current directory is RootFolder and we compress
// the following directories structure:
// RootFolder
// +--Folder1
// | +--Folder2
// | +--Folder3
// +--Folder4
// with 'rar a -r arcname Folder2' command, rar could add not only
// Folder1\Folder2 contents, but also Folder1\Folder3 if we were using
// "*" mask at all levels. We need to use "*" mask inside of Folder2,
// but return to "Folder2" mask when completing scanning Folder2.
// We can rewrite SearchAll expression above to avoid fast finding
// directories at Depth > 0, but then 'rar a -r arcname Folder2'
// will add the empty Folder2 and do not add its contents.
if (FastFindFile)
SetAllMaskDepth=Depth;
}
if (!FastFindFile && !CmpName(CurMask,FD->Name,MATCH_NAMES))
return(SCAN_NEXT);
return(SCAN_SUCCESS);
}

60
src/unrar/scantree.hpp Normal file
View File

@ -0,0 +1,60 @@
#ifndef _RAR_SCANTREE_
#define _RAR_SCANTREE_
enum SCAN_DIRS
{
SCAN_SKIPDIRS, // Skip directories, but recurse for files if recursion mode is enabled.
SCAN_GETDIRS, // Get subdirectories in recurse mode.
SCAN_GETDIRSTWICE, // Get the directory name both before and after the list of files it contains.
SCAN_GETCURDIRS // Get subdirectories in current directory even in RECURSE_NONE mode.
};
enum SCAN_CODE { SCAN_SUCCESS,SCAN_DONE,SCAN_ERROR,SCAN_NEXT };
#define MAXSCANDEPTH (NM/2)
class CommandData;
class ScanTree
{
private:
bool GetNextMask();
SCAN_CODE FindProc(FindData *FD);
FindFile *FindStack[MAXSCANDEPTH];
int Depth;
int SetAllMaskDepth;
StringList *FileMasks;
RECURSE_MODE Recurse;
bool GetLinks;
SCAN_DIRS GetDirs;
int Errors;
// set when processing paths like c:\ (root directory without wildcards)
bool ScanEntireDisk;
char CurMask[NM];
wchar CurMaskW[NM];
char OrigCurMask[NM];
wchar OrigCurMaskW[NM];
bool SearchAllInRoot;
size_t SpecPathLength;
size_t SpecPathLengthW;
char ErrArcName[NM];
CommandData *Cmd;
public:
ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs);
~ScanTree();
SCAN_CODE GetNext(FindData *FindData);
size_t GetSpecPathLength() {return(SpecPathLength);};
size_t GetSpecPathLengthW() {return(SpecPathLengthW);};
int GetErrors() {return(Errors);};
void SetErrArcName(const char *Name) {strcpy(ErrArcName,Name);}
void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;}
};
#endif

203
src/unrar/secpassword.cpp Normal file
View File

@ -0,0 +1,203 @@
#include "rar.hpp"
#ifdef _WIN_ALL
typedef BOOL (WINAPI *CRYPTPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags);
typedef BOOL (WINAPI *CRYPTUNPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags);
#ifndef CRYPTPROTECTMEMORY_BLOCK_SIZE
#define CRYPTPROTECTMEMORY_BLOCK_SIZE 16
#define CRYPTPROTECTMEMORY_SAME_PROCESS 0x00
#endif
class CryptLoader
{
private:
HMODULE hCrypt;
bool LoadCalled;
public:
CryptLoader()
{
hCrypt=NULL;
pCryptProtectMemory=NULL;
pCryptUnprotectMemory=NULL;
LoadCalled=false;
}
~CryptLoader()
{
if (hCrypt!=NULL)
FreeLibrary(hCrypt);
hCrypt=NULL;
pCryptProtectMemory=NULL;
pCryptUnprotectMemory=NULL;
};
void Load()
{
if (!LoadCalled)
{
hCrypt = LoadLibraryW(L"Crypt32.dll");
if (hCrypt != NULL)
{
pCryptProtectMemory = (CRYPTPROTECTMEMORY)GetProcAddress(hCrypt, "CryptProtectMemory");
pCryptUnprotectMemory = (CRYPTUNPROTECTMEMORY)GetProcAddress(hCrypt, "CryptUnprotectMemory");
}
LoadCalled=true;
}
}
CRYPTPROTECTMEMORY pCryptProtectMemory;
CRYPTUNPROTECTMEMORY pCryptUnprotectMemory;
};
// We want to call FreeLibrary when RAR is exiting.
CryptLoader GlobalCryptLoader;
#endif
SecPassword::SecPassword()
{
Set(L"");
}
SecPassword::~SecPassword()
{
Clean();
}
void SecPassword::Clean()
{
PasswordSet=false;
cleandata(Password,sizeof(Password));
}
// When we call memset in end of function to clean local variables
// for security reason, compiler optimizer can remove such call.
// So we use our own function for this purpose.
void cleandata(void *data,size_t size)
{
#if defined(_WIN_ALL) && defined(_MSC_VER)
SecureZeroMemory(data,size);
#else
// 'volatile' is required. Otherwise optimizers can remove this function
// if cleaning local variables, which are not used after that.
volatile byte *d = (volatile byte *)data;
for (size_t i=0;i<size;i++)
d[i]=0;
#endif
}
// We got a complain from user that it is possible to create WinRAR dump
// with "Create dump file" command in Windows Task Manager and then easily
// locate Unicode password string in the dump. It is unsecure if several
// people share the same computer and somebody left WinRAR copy with entered
// password. So we decided to obfuscate the password to make it more difficult
// to find it in dump.
void SecPassword::Process(const wchar *Src,wchar *Dst,size_t MaxSize,bool Encode)
{
#ifdef _WIN_ALL
// Try to utilize the secure Crypt[Un]ProtectMemory if possible.
if (GlobalCryptLoader.pCryptProtectMemory==NULL)
GlobalCryptLoader.Load();
if (Encode)
{
if (GlobalCryptLoader.pCryptProtectMemory!=NULL &&
MaxSize%CRYPTPROTECTMEMORY_BLOCK_SIZE==0)
{
memcpy(Dst,Src,MaxSize*sizeof(*Dst));
if (!GlobalCryptLoader.pCryptProtectMemory(Dst,DWORD(MaxSize*sizeof(*Dst)),
CRYPTPROTECTMEMORY_SAME_PROCESS))
{
ErrHandler.GeneralErrMsg("CryptProtectMemory failed");
ErrHandler.SysErrMsg();
ErrHandler.Exit(RARX_FATAL);
}
return;
}
}
else
{
if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL &&
MaxSize%CRYPTPROTECTMEMORY_BLOCK_SIZE==0)
{
memcpy(Dst,Src,MaxSize*sizeof(*Dst));
if (!GlobalCryptLoader.pCryptUnprotectMemory(Dst,DWORD(MaxSize*sizeof(*Dst)),
CRYPTPROTECTMEMORY_SAME_PROCESS))
{
ErrHandler.GeneralErrMsg("CryptUnprotectMemory failed");
ErrHandler.SysErrMsg();
ErrHandler.Exit(RARX_FATAL);
}
return;
}
}
#endif
// CryptProtectMemory is not available, so only slightly obfuscate data.
uint Key;
#ifdef _WIN_ALL
Key=GetCurrentProcessId();
#elif defined(_UNIX)
Key=getpid();
#else
Key=10203040; // Just an arbitrary value.
#endif
for (size_t I=0;I<MaxSize;I++)
Dst[I]=wchar(Src[I]^(Key+I+75));
}
void SecPassword::Get(wchar *Psw,size_t MaxSize)
{
if (PasswordSet)
{
Process(Password,Psw,MaxSize,false);
Psw[MaxSize-1]=0;
}
else
*Psw=0;
}
void SecPassword::Set(const wchar *Psw)
{
if (*Psw==0)
{
PasswordSet=false;
memset(Password,0,sizeof(Password));
}
else
{
PasswordSet=true;
Process(Psw,Password,ASIZE(Password),true);
}
}
size_t SecPassword::Length()
{
wchar Plain[MAXPASSWORD];
Get(Plain,ASIZE(Plain));
size_t Length=wcslen(Plain);
cleandata(Plain,ASIZE(Plain));
return Length;
}
bool SecPassword::operator == (SecPassword &psw)
{
// We cannot compare encoded data directly, because there is no guarantee
// than encryption function will always produce the same result for same
// data (salt?) and because we do not clean the rest of password buffer
// after trailing zero before encoding password. So we decode first.
wchar Plain1[MAXPASSWORD],Plain2[MAXPASSWORD];
Get(Plain1,ASIZE(Plain1));
psw.Get(Plain2,ASIZE(Plain2));
bool Result=wcscmp(Plain1,Plain2)==0;
cleandata(Plain1,ASIZE(Plain1));
cleandata(Plain2,ASIZE(Plain2));
return Result;
}

30
src/unrar/secpassword.hpp Normal file
View File

@ -0,0 +1,30 @@
#ifndef _RAR_SECURE_PASSWORD_
#define _RAR_SECURE_PASSWORD_
// Store a password securely (if data encryption is provided by OS)
// or obfuscated to make search for password in memory dump less trivial.
class SecPassword
{
private:
void Process(const wchar *Src,wchar *Dst,size_t MaxSize,bool Encode);
wchar Password[MAXPASSWORD];
// It is important to have this 'bool' value, so if our object is cleaned
// with memset as a part of larger structure, it is handled correctly.
bool PasswordSet;
public:
SecPassword();
~SecPassword();
void Clean();
void Get(wchar *Psw,size_t MaxSize);
void Set(const wchar *Psw);
bool IsSet() {return PasswordSet;}
size_t Length();
bool operator == (SecPassword &psw);
};
void cleandata(void *data,size_t size);
#endif

248
src/unrar/sha1.cpp Normal file
View File

@ -0,0 +1,248 @@
#include "rar.hpp"
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#if defined(_M_IX86) || defined(_M_I86) || defined(__alpha)
#define LITTLE_ENDIAN
#else
#error "LITTLE_ENDIAN or BIG_ENDIAN must be defined"
#endif
#endif
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifdef LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) {z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);}
#define R1(v,w,x,y,z,i) {z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);}
#define R2(v,w,x,y,z,i) {z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);}
#define R3(v,w,x,y,z,i) {z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);}
#define R4(v,w,x,y,z,i) {z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);}
#ifdef _MSC_VER
#pragma optimize( "", off )
// We need to disable the optimization to really wipe these variables.
#endif
static void wipevars(uint32 &a,uint32 &b,uint32 &c,uint32 &d,uint32 &e)
{
// Wipe used variables for safety reason.
a=b=c=d=e=0;
}
#ifdef _MSC_VER
#pragma optimize( "", on )
#endif
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(uint32 state[5], unsigned char workspace[64], unsigned char buffer[64], bool handsoff)
{
#ifndef SFX_MODULE
uint32 a, b, c, d, e;
#endif
typedef union {
unsigned char c[64];
uint32 l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
if (handsoff)
{
block = (CHAR64LONG16*)workspace;
memcpy(block, buffer, 64);
}
else
block = (CHAR64LONG16*)buffer;
#ifdef SFX_MODULE
static int pos[80][5];
static bool pinit=false;
if (!pinit)
{
for (int I=0,P=0;I<80;I++,P=(P ? P-1:4))
{
pos[I][0]=P;
pos[I][1]=(P+1)%5;
pos[I][2]=(P+2)%5;
pos[I][3]=(P+3)%5;
pos[I][4]=(P+4)%5;
}
pinit=true;
}
uint32 s[5];
for (int I=0;I<sizeof(s)/sizeof(s[0]);I++)
s[I]=state[I];
for (int I=0;I<16;I++)
R0(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
for (int I=16;I<20;I++)
R1(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
for (int I=20;I<40;I++)
R2(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
for (int I=40;I<60;I++)
R3(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
for (int I=60;I<80;I++)
R4(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
for (int I=0;I<sizeof(s)/sizeof(s[0]);I++)
state[I]+=s[I];
#else
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
// Such wipe method does not work in optimizing compilers.
// a = b = c = d = e = 0;
// memset(&a,0,sizeof(a));
wipevars(a,b,c,d,e);
#endif
}
/* Initialize new context */
void hash_initial(hash_context* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void hash_process( hash_context * context, unsigned char * data, size_t len,
bool handsoff )
{
unsigned int i, j;
uint blen = ((uint)len)<<3;
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += blen) < blen ) context->count[1]++;
context->count[1] += (uint32)(len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->workspace, context->buffer, handsoff);
for ( ; i + 63 < len; i += 64) {
#ifdef ALLOW_NOT_ALIGNED_INT
SHA1Transform(context->state, context->workspace, &data[i], handsoff);
#else
unsigned char buffer[64];
memcpy(buffer,data+i,sizeof(buffer));
SHA1Transform(context->state, context->workspace, buffer, handsoff);
memcpy(data+i,buffer,sizeof(buffer));
#endif
#ifdef BIG_ENDIAN
if (!handsoff)
{
unsigned char *d=data+i;
for (int k=0;k<64;k+=4)
{
byte b0=d[k],b1=d[k+1];
d[k]=d[k+3];
d[k+1]=d[k+2];
d[k+2]=b1;
d[k+3]=b0;
}
}
#endif
}
j = 0;
}
else i = 0;
if (len > i)
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
void hash_final( hash_context* context, uint32 digest[5], bool handsoff)
{
uint i, j;
unsigned char finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
unsigned char ch=(unsigned char)'\200';
hash_process(context, &ch, 1, handsoff);
while ((context->count[0] & 504) != 448) {
ch=0;
hash_process(context, &ch, 1, handsoff);
}
hash_process(context, finalcount, 8, handsoff); /* Should cause a SHA1Transform() */
for (i = 0; i < 5; i++) {
digest[i] = context->state[i] & 0xffffffff;
}
/* Wipe variables */
cleandata(&i,sizeof(i));
cleandata(&j,sizeof(j));
cleandata(context->buffer, 64);
cleandata(context->state, 20);
cleandata(context->count, 8);
cleandata(&finalcount, 8);
if (handsoff)
memset(context->workspace,0,sizeof(context->workspace)); // Wipe the temporary buffer.
// SHA1Transform(context->state, context->workspace, context->buffer, true); /* make SHA1Transform overwrite it's own static vars */
}

Some files were not shown because too many files have changed in this diff Show More